Compare commits
	
		
			No commits in common. 'master' and 'submitter-web' have entirely different histories. 
		
	
	
		
			master
			...
			submitter-
		
	
		
	@ -1,38 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
	env: { node: true },
 | 
					 | 
				
			||||||
	parser: "@typescript-eslint/parser",
 | 
					 | 
				
			||||||
	plugins: ["@typescript-eslint", "prettier", "jsdoc"],
 | 
					 | 
				
			||||||
	extends: [
 | 
					 | 
				
			||||||
		"eslint:recommended",
 | 
					 | 
				
			||||||
		"plugin:@typescript-eslint/recommended",
 | 
					 | 
				
			||||||
		"plugin:@typescript-eslint/recommended-requiring-type-checking",
 | 
					 | 
				
			||||||
		"plugin:prettier/recommended",
 | 
					 | 
				
			||||||
	],
 | 
					 | 
				
			||||||
	parserOptions: {
 | 
					 | 
				
			||||||
		sourceType: "module",
 | 
					 | 
				
			||||||
		ecmaFeatures: {
 | 
					 | 
				
			||||||
			modules: true,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		project: "./tsconfig.json",
 | 
					 | 
				
			||||||
		tsconfigRootDir: __dirname,
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	rules: {
 | 
					 | 
				
			||||||
		"@typescript-eslint/require-await": 0,
 | 
					 | 
				
			||||||
		"jsdoc/require-description": 2,
 | 
					 | 
				
			||||||
		"no-await-in-loop": 2,
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	settings: { jsdoc: { mode: "typescript" } },
 | 
					 | 
				
			||||||
	overrides: [
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			files: ["*.subtest.ts", "*.test.ts"],
 | 
					 | 
				
			||||||
			rules: {
 | 
					 | 
				
			||||||
				"@typescript-eslint/no-unsafe-member-access": 0,
 | 
					 | 
				
			||||||
				"prefer-const": 0,
 | 
					 | 
				
			||||||
				"@typescript-eslint/no-unsafe-call": 0,
 | 
					 | 
				
			||||||
				"@typescript-eslint/no-unsafe-return": 0,
 | 
					 | 
				
			||||||
				"@typescript-eslint/no-unsafe-assignment": 0,
 | 
					 | 
				
			||||||
				"no-await-in-loop": 1, // sometimes it's easier to debug when requests run sequentially
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	],
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
@ -1,11 +1,3 @@
 | 
				
			|||||||
node_modules
 | 
					/.cache/
 | 
				
			||||||
.node_repl_history
 | 
					/dist/
 | 
				
			||||||
.config
 | 
					/node_modules/
 | 
				
			||||||
.npm
 | 
					 | 
				
			||||||
.idea
 | 
					 | 
				
			||||||
.DS_Store
 | 
					 | 
				
			||||||
lib
 | 
					 | 
				
			||||||
dist
 | 
					 | 
				
			||||||
@types
 | 
					 | 
				
			||||||
.cache
 | 
					 | 
				
			||||||
public
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,14 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
	"useTabs": true,
 | 
					 | 
				
			||||||
	"tabWidth": 4,
 | 
					 | 
				
			||||||
	"trailingComma": "es5",
 | 
					 | 
				
			||||||
	"overrides": [
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"files": "*.yml",
 | 
					 | 
				
			||||||
			"options": {
 | 
					 | 
				
			||||||
				"tabWidth": 2,
 | 
					 | 
				
			||||||
				"useTabs": false
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,11 +0,0 @@
 | 
				
			|||||||
version: "3.7"
 | 
					 | 
				
			||||||
services:
 | 
					 | 
				
			||||||
  db:
 | 
					 | 
				
			||||||
    image: mongo:4.4-bionic
 | 
					 | 
				
			||||||
    ports:
 | 
					 | 
				
			||||||
      - "127.0.0.1:20724:27017"
 | 
					 | 
				
			||||||
  mailcatcher:
 | 
					 | 
				
			||||||
    image: schickling/mailcatcher:latest
 | 
					 | 
				
			||||||
    ports:
 | 
					 | 
				
			||||||
      - "127.0.0.1:1080:1080"
 | 
					 | 
				
			||||||
      - "127.0.0.1:1025:1025"
 | 
					 | 
				
			||||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -1,50 +1,18 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	"name": "zglaszansko-web",
 | 
					  "name": "zglaszansko-web",
 | 
				
			||||||
	"version": "0.1.0",
 | 
					  "version": "0.1.0",
 | 
				
			||||||
	"description": "Web aplikacja ułatwiająca wysyłanie zgłoszeń do Poznańskiej Straży Miejskiej",
 | 
					  "description": "Web aplikacja ułatwiająca wysyłanie zgłoszeń do Poznańskiej Straży Miejskiej",
 | 
				
			||||||
	"main": "./dist/back/index.js",
 | 
					  "main": "index.js",
 | 
				
			||||||
	"scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
		"back:build": "tsc",
 | 
					    "start": "parcel src/index.html"
 | 
				
			||||||
		"back:watch": "npm run back:build -- --watch",
 | 
					  },
 | 
				
			||||||
		"front:build": "parcel build --out-dir public src/front/*.html",
 | 
					  "repository": {
 | 
				
			||||||
		"front:watch": "parcel watch --out-dir public src/front/*.html",
 | 
					    "type": "git",
 | 
				
			||||||
		"start": "nodemon lib/back/index.js"
 | 
					    "url": "gitea@git.kuba-orlik.name:kuba/zglaszansko-web.git"
 | 
				
			||||||
	},
 | 
					  },
 | 
				
			||||||
	"repository": {
 | 
					  "author": "foki",
 | 
				
			||||||
		"type": "git",
 | 
					  "license": "ISC",
 | 
				
			||||||
		"url": "gitea@git.kuba-orlik.name:kuba/zglaszansko-web.git"
 | 
					  "dependencies": {
 | 
				
			||||||
	},
 | 
					    "parcel-bundler": "^1.12.4"
 | 
				
			||||||
	"author": "foki",
 | 
					  }
 | 
				
			||||||
	"license": "ISC",
 | 
					 | 
				
			||||||
	"dependencies": {
 | 
					 | 
				
			||||||
		"@koa/router": "^10.0.0",
 | 
					 | 
				
			||||||
		"@types/koa": "^2.11.6",
 | 
					 | 
				
			||||||
		"@types/koa-mount": "^4.0.0",
 | 
					 | 
				
			||||||
		"@types/koa-static": "^4.0.1",
 | 
					 | 
				
			||||||
		"@types/koa__router": "^8.0.3",
 | 
					 | 
				
			||||||
		"@types/react": "^17.0.0",
 | 
					 | 
				
			||||||
		"@types/react-dom": "^17.0.0",
 | 
					 | 
				
			||||||
		"axios": "^0.21.1",
 | 
					 | 
				
			||||||
		"eslint-plugin-prettier": "^3.3.1",
 | 
					 | 
				
			||||||
		"koa": "^2.13.0",
 | 
					 | 
				
			||||||
		"koa-mount": "^4.0.0",
 | 
					 | 
				
			||||||
		"koa-static": "^5.0.0",
 | 
					 | 
				
			||||||
		"leaflet": "^1.7.1",
 | 
					 | 
				
			||||||
		"parcel-bundler": "^1.12.4",
 | 
					 | 
				
			||||||
		"react": "^17.0.1",
 | 
					 | 
				
			||||||
		"react-dom": "^17.0.1",
 | 
					 | 
				
			||||||
		"react-leaflet": "^3.0.5",
 | 
					 | 
				
			||||||
		"sealious": "^0.13.8"
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	"devDependencies": {
 | 
					 | 
				
			||||||
		"@types/leaflet": "^1.5.19",
 | 
					 | 
				
			||||||
		"@types/node": "^14.14.20",
 | 
					 | 
				
			||||||
		"@types/request": "^2.48.5",
 | 
					 | 
				
			||||||
		"eslint": "^7.5.0",
 | 
					 | 
				
			||||||
		"eslint-config-prettier": "^6.11.0",
 | 
					 | 
				
			||||||
		"eslint-plugin-jsdoc": "^30.0.3",
 | 
					 | 
				
			||||||
		"prettier": "^2.0.5",
 | 
					 | 
				
			||||||
		"sass": "^1.32.0",
 | 
					 | 
				
			||||||
		"typescript": "^4.1.3"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
											
												Binary file not shown.
											
										
									
								| 
		 Before Width: | Height: | Size: 328 B  | 
@ -1,51 +0,0 @@
 | 
				
			|||||||
import Koa from "koa";
 | 
					 | 
				
			||||||
import _locreq from "locreq";
 | 
					 | 
				
			||||||
import { resolve } from "path";
 | 
					 | 
				
			||||||
import Static from "koa-static";
 | 
					 | 
				
			||||||
import Router from "@koa/router";
 | 
					 | 
				
			||||||
import mount from "koa-mount";
 | 
					 | 
				
			||||||
const locreq = _locreq(__dirname);
 | 
					 | 
				
			||||||
import Sealious, { App } from "sealious";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
declare module "koa" {
 | 
					 | 
				
			||||||
	interface BaseContext {
 | 
					 | 
				
			||||||
		$context: Sealious.Context;
 | 
					 | 
				
			||||||
		$app: Sealious.App;
 | 
					 | 
				
			||||||
		$body: Record<string, unknown>;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
const app = new (class extends App {
 | 
					 | 
				
			||||||
	config = {
 | 
					 | 
				
			||||||
		upload_path: locreq.resolve("uploaded_files"),
 | 
					 | 
				
			||||||
		datastore_mongo: {
 | 
					 | 
				
			||||||
			host: "localhost",
 | 
					 | 
				
			||||||
			port: 20724,
 | 
					 | 
				
			||||||
			db_name: "zglaszansko-web",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		email: {
 | 
					 | 
				
			||||||
			from_address: "sealious-playground@example.com",
 | 
					 | 
				
			||||||
			from_name: "Sealious playground app",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	manifest = {
 | 
					 | 
				
			||||||
		name: "Sealious Playground",
 | 
					 | 
				
			||||||
		logo: resolve(__dirname, "../assets/logo.png"),
 | 
					 | 
				
			||||||
		version: "0.0.1",
 | 
					 | 
				
			||||||
		default_language: "en",
 | 
					 | 
				
			||||||
		base_url: "http://localhost:8080",
 | 
					 | 
				
			||||||
		admin_email: "admin@example.com",
 | 
					 | 
				
			||||||
		colors: {
 | 
					 | 
				
			||||||
			primary: "#5294a1",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	collections = {
 | 
					 | 
				
			||||||
		...App.BaseCollections,
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const port = 8080;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
console.log(`Listening on 127.0.0.1:${port}`);
 | 
					 | 
				
			||||||
app.start();
 | 
					 | 
				
			||||||
app.HTTPServer.addStaticRoute("/", locreq.resolve("public"));
 | 
					 | 
				
			||||||
@ -1,52 +0,0 @@
 | 
				
			|||||||
import axios from "axios";
 | 
					 | 
				
			||||||
import React, { ReactElement } from "react";
 | 
					 | 
				
			||||||
import "./styles/nav.scss";
 | 
					 | 
				
			||||||
interface Props {
 | 
					 | 
				
			||||||
	isLogged: boolean;
 | 
					 | 
				
			||||||
	logoutState: () => void;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
const NOT_LOGGED = [
 | 
					 | 
				
			||||||
	{ name: "aplikacja", href: "/" },
 | 
					 | 
				
			||||||
	{ name: "logowanie", href: "login.html" },
 | 
					 | 
				
			||||||
	{ name: "rejestracja", href: "register.html" },
 | 
					 | 
				
			||||||
];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const LOGGED = [{ name: "aplikacja", href: "/" }];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function Nav({ isLogged, logoutState }: Props): ReactElement {
 | 
					 | 
				
			||||||
	const logout = async () => {
 | 
					 | 
				
			||||||
		await axios.delete(
 | 
					 | 
				
			||||||
			"http://localhost:8080/api/v1/collections/sessions/current"
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
		logoutState();
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (
 | 
					 | 
				
			||||||
		<nav className="navbar">
 | 
					 | 
				
			||||||
			<h2 className="navbar__title">Zgłaszańsko web</h2>
 | 
					 | 
				
			||||||
			<div className="navbar__links">
 | 
					 | 
				
			||||||
				{isLogged
 | 
					 | 
				
			||||||
					? LOGGED.map((ele) => (
 | 
					 | 
				
			||||||
							<>
 | 
					 | 
				
			||||||
								<a href={ele.href} className="button-link">
 | 
					 | 
				
			||||||
									{ele.name}
 | 
					 | 
				
			||||||
								</a>
 | 
					 | 
				
			||||||
								<button
 | 
					 | 
				
			||||||
									onClick={logout}
 | 
					 | 
				
			||||||
									className="button-link"
 | 
					 | 
				
			||||||
								>
 | 
					 | 
				
			||||||
									Wyloguj
 | 
					 | 
				
			||||||
								</button>
 | 
					 | 
				
			||||||
							</>
 | 
					 | 
				
			||||||
					  ))
 | 
					 | 
				
			||||||
					: NOT_LOGGED.map((ele) => (
 | 
					 | 
				
			||||||
							<a href={ele.href} className="button-link">
 | 
					 | 
				
			||||||
								{ele.name}
 | 
					 | 
				
			||||||
							</a>
 | 
					 | 
				
			||||||
					  ))}
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		</nav>
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default Nav;
 | 
					 | 
				
			||||||
@ -1,347 +0,0 @@
 | 
				
			|||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
					 | 
				
			||||||
import React, {
 | 
					 | 
				
			||||||
	useState,
 | 
					 | 
				
			||||||
	useReducer,
 | 
					 | 
				
			||||||
	MouseEvent,
 | 
					 | 
				
			||||||
	FC,
 | 
					 | 
				
			||||||
	ChangeEvent,
 | 
					 | 
				
			||||||
	FormEvent,
 | 
					 | 
				
			||||||
	useEffect,
 | 
					 | 
				
			||||||
} from "react";
 | 
					 | 
				
			||||||
import { render } from "react-dom";
 | 
					 | 
				
			||||||
import { offenses } from "./offenses";
 | 
					 | 
				
			||||||
import axios from "axios";
 | 
					 | 
				
			||||||
import Nav from "./Nav";
 | 
					 | 
				
			||||||
//Importing fileReducer to use in useReducer hook, and File interface to use in looping over array of files
 | 
					 | 
				
			||||||
import { fileReducer, filesInitialState, File } from "./fileReducer";
 | 
					 | 
				
			||||||
import { formReducer, fromInitialState } from "./formReducer";
 | 
					 | 
				
			||||||
import "regenerator-runtime/runtime";
 | 
					 | 
				
			||||||
import { MapContainer, TileLayer, Marker, useMapEvents } from "react-leaflet";
 | 
					 | 
				
			||||||
import "./styles/reset.css";
 | 
					 | 
				
			||||||
import "./styles/app.scss";
 | 
					 | 
				
			||||||
import { getAddress } from "./location";
 | 
					 | 
				
			||||||
import { FileType } from "./file";
 | 
					 | 
				
			||||||
const App: FC = () => {
 | 
					 | 
				
			||||||
	const [isLogged, setIsLogged] = useState(false);
 | 
					 | 
				
			||||||
	const [fileState, fileDispatch] = useReducer(
 | 
					 | 
				
			||||||
		fileReducer,
 | 
					 | 
				
			||||||
		filesInitialState
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
	const [formState, formDispatch] = useReducer(formReducer, fromInitialState);
 | 
					 | 
				
			||||||
	const [mapPin, setMapPin] = useState({ lat: 0, lon: 0 });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const checkUser = async (): Promise<void> => {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			await axios.get(
 | 
					 | 
				
			||||||
				"http://localhost:8080/api/v1/collections/users/me"
 | 
					 | 
				
			||||||
			);
 | 
					 | 
				
			||||||
			setIsLogged(true);
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			setIsLogged(false);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	useEffect(() => {
 | 
					 | 
				
			||||||
		void checkUser();
 | 
					 | 
				
			||||||
	}, []);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	useEffect(() => {
 | 
					 | 
				
			||||||
		void getAddress(mapPin).then((blob) =>
 | 
					 | 
				
			||||||
			formDispatch({
 | 
					 | 
				
			||||||
				type: "CHANGE_FIELD",
 | 
					 | 
				
			||||||
				payload: {
 | 
					 | 
				
			||||||
					field: "address",
 | 
					 | 
				
			||||||
					value: blob,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
	}, [mapPin]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const handleSubmit = async (
 | 
					 | 
				
			||||||
		event: FormEvent<HTMLFormElement> | MouseEvent<HTMLButtonElement>
 | 
					 | 
				
			||||||
	): Promise<void> => {
 | 
					 | 
				
			||||||
		event.preventDefault();
 | 
					 | 
				
			||||||
		console.log(fileState, formState);
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const handleUpload = (e: ChangeEvent<HTMLInputElement>) => {
 | 
					 | 
				
			||||||
		const files = e.target.files;
 | 
					 | 
				
			||||||
		const readAndPreview = (file: FileType) => {
 | 
					 | 
				
			||||||
			console.log(file);
 | 
					 | 
				
			||||||
			// Make sure `file.name` matches our extensions criteria
 | 
					 | 
				
			||||||
			// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
 | 
					 | 
				
			||||||
			if (/\.(jpe?g|png|svg)$/i.test(file.name)) {
 | 
					 | 
				
			||||||
				const reader = new FileReader();
 | 
					 | 
				
			||||||
				reader.addEventListener(
 | 
					 | 
				
			||||||
					"load",
 | 
					 | 
				
			||||||
					function () {
 | 
					 | 
				
			||||||
						fileDispatch({
 | 
					 | 
				
			||||||
							type: "ADD_FILE",
 | 
					 | 
				
			||||||
							payload: {
 | 
					 | 
				
			||||||
								img: this.result,
 | 
					 | 
				
			||||||
								id: Date.now().toString(),
 | 
					 | 
				
			||||||
								selected: false,
 | 
					 | 
				
			||||||
							},
 | 
					 | 
				
			||||||
						});
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
					false
 | 
					 | 
				
			||||||
				);
 | 
					 | 
				
			||||||
				reader.readAsDataURL((file as unknown) as Blob);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		if (files) {
 | 
					 | 
				
			||||||
			[].forEach.call(files, readAndPreview);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const MapComponent = () => {
 | 
					 | 
				
			||||||
		useMapEvents({
 | 
					 | 
				
			||||||
			click: async (e) => {
 | 
					 | 
				
			||||||
				setMapPin({ lat: e.latlng.lat, lon: e.latlng.lng });
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		return null;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const formMessage = `Rejestracja: ${formState.plate}\nMiejsce: ${
 | 
					 | 
				
			||||||
		formState.address.road === undefined ? "" : formState.address.road
 | 
					 | 
				
			||||||
	} ${
 | 
					 | 
				
			||||||
		formState.address.house_number === undefined
 | 
					 | 
				
			||||||
			? ""
 | 
					 | 
				
			||||||
			: formState.address.house_number
 | 
					 | 
				
			||||||
	}\nData: ${new Date().toLocaleString()}\nMoje dane: ${
 | 
					 | 
				
			||||||
		formState.name + ","
 | 
					 | 
				
			||||||
	} ${formState.email}\n${
 | 
					 | 
				
			||||||
		formState.my_address
 | 
					 | 
				
			||||||
	}\nPowód: ${formState.offenses.join(", \n")}\nKomentarz: ${
 | 
					 | 
				
			||||||
		formState.comment
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
  `;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (
 | 
					 | 
				
			||||||
		<>
 | 
					 | 
				
			||||||
			<Nav isLogged={isLogged} logoutState={() => setIsLogged(false)} />
 | 
					 | 
				
			||||||
			<div className="container">
 | 
					 | 
				
			||||||
				<section className="container__section">
 | 
					 | 
				
			||||||
					<h2 className="container__section__title">Zdjęcia</h2>
 | 
					 | 
				
			||||||
					<div className="container__section__photos">
 | 
					 | 
				
			||||||
						{fileState.files.map((file: File, index: number) => (
 | 
					 | 
				
			||||||
							<div
 | 
					 | 
				
			||||||
								key={index}
 | 
					 | 
				
			||||||
								onClick={(e: MouseEvent) =>
 | 
					 | 
				
			||||||
									fileDispatch({
 | 
					 | 
				
			||||||
										type: "SELECT_FILE",
 | 
					 | 
				
			||||||
										payload: {
 | 
					 | 
				
			||||||
											id: (e.target as Element).id,
 | 
					 | 
				
			||||||
										},
 | 
					 | 
				
			||||||
									})
 | 
					 | 
				
			||||||
								}
 | 
					 | 
				
			||||||
								className="section__photos__item"
 | 
					 | 
				
			||||||
							>
 | 
					 | 
				
			||||||
								<img
 | 
					 | 
				
			||||||
									src={file.img as string}
 | 
					 | 
				
			||||||
									id={file.id}
 | 
					 | 
				
			||||||
									className={
 | 
					 | 
				
			||||||
										file.selected ? "img--active" : "img"
 | 
					 | 
				
			||||||
									}
 | 
					 | 
				
			||||||
								/>
 | 
					 | 
				
			||||||
							</div>
 | 
					 | 
				
			||||||
						))}
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
					<input
 | 
					 | 
				
			||||||
						type="file"
 | 
					 | 
				
			||||||
						name="image-upload"
 | 
					 | 
				
			||||||
						id="input"
 | 
					 | 
				
			||||||
						accept="image/*"
 | 
					 | 
				
			||||||
						className="input"
 | 
					 | 
				
			||||||
						multiple
 | 
					 | 
				
			||||||
						onChange={(e) => handleUpload(e)}
 | 
					 | 
				
			||||||
					/>
 | 
					 | 
				
			||||||
				</section>
 | 
					 | 
				
			||||||
				<section className="container__section">
 | 
					 | 
				
			||||||
					<h2 className="container__section__title">Mapa</h2>
 | 
					 | 
				
			||||||
					<div>
 | 
					 | 
				
			||||||
						<MapContainer
 | 
					 | 
				
			||||||
							center={[52.39663, 16.89866]}
 | 
					 | 
				
			||||||
							className="container__section__map"
 | 
					 | 
				
			||||||
							zoom={16}
 | 
					 | 
				
			||||||
							scrollWheelZoom={true}
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
							<TileLayer
 | 
					 | 
				
			||||||
								attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
 | 
					 | 
				
			||||||
								url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"
 | 
					 | 
				
			||||||
							/>
 | 
					 | 
				
			||||||
							{mapPin.lat !== 0 ? (
 | 
					 | 
				
			||||||
								<Marker
 | 
					 | 
				
			||||||
									position={[mapPin.lat, mapPin.lon]}
 | 
					 | 
				
			||||||
								></Marker>
 | 
					 | 
				
			||||||
							) : null}
 | 
					 | 
				
			||||||
							<MapComponent />
 | 
					 | 
				
			||||||
						</MapContainer>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
					<p>
 | 
					 | 
				
			||||||
						Wybrany adres:{" "}
 | 
					 | 
				
			||||||
						{formState.address.road === undefined
 | 
					 | 
				
			||||||
							? ""
 | 
					 | 
				
			||||||
							: formState.address.road}{" "}
 | 
					 | 
				
			||||||
						{formState.address.house_number === undefined
 | 
					 | 
				
			||||||
							? ""
 | 
					 | 
				
			||||||
							: formState.address.house_number}
 | 
					 | 
				
			||||||
					</p>
 | 
					 | 
				
			||||||
				</section>
 | 
					 | 
				
			||||||
				<section className="container__section">
 | 
					 | 
				
			||||||
					<h2 className="container__section__title">
 | 
					 | 
				
			||||||
						Formularz zgłoszeniowy
 | 
					 | 
				
			||||||
					</h2>
 | 
					 | 
				
			||||||
					<form
 | 
					 | 
				
			||||||
						className="container__section__form"
 | 
					 | 
				
			||||||
						onSubmit={(e) => handleSubmit(e)}
 | 
					 | 
				
			||||||
					>
 | 
					 | 
				
			||||||
						<label htmlFor="name">Twoje imię i nazwisko</label>
 | 
					 | 
				
			||||||
						<input
 | 
					 | 
				
			||||||
							type="text"
 | 
					 | 
				
			||||||
							className="input"
 | 
					 | 
				
			||||||
							id="name"
 | 
					 | 
				
			||||||
							value={formState.name}
 | 
					 | 
				
			||||||
							onChange={(e) =>
 | 
					 | 
				
			||||||
								formDispatch({
 | 
					 | 
				
			||||||
									type: "CHANGE_FIELD",
 | 
					 | 
				
			||||||
									payload: {
 | 
					 | 
				
			||||||
										field: e.target.id,
 | 
					 | 
				
			||||||
										value: e.target.value,
 | 
					 | 
				
			||||||
									},
 | 
					 | 
				
			||||||
								})
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						/>
 | 
					 | 
				
			||||||
						<label htmlFor="email">Twój adres email</label>
 | 
					 | 
				
			||||||
						<input
 | 
					 | 
				
			||||||
							type="text"
 | 
					 | 
				
			||||||
							className="input"
 | 
					 | 
				
			||||||
							id="email"
 | 
					 | 
				
			||||||
							value={formState.email}
 | 
					 | 
				
			||||||
							onChange={(e) =>
 | 
					 | 
				
			||||||
								formDispatch({
 | 
					 | 
				
			||||||
									type: "CHANGE_FIELD",
 | 
					 | 
				
			||||||
									payload: {
 | 
					 | 
				
			||||||
										field: e.target.id,
 | 
					 | 
				
			||||||
										value: e.target.value,
 | 
					 | 
				
			||||||
									},
 | 
					 | 
				
			||||||
								})
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						/>
 | 
					 | 
				
			||||||
						<label htmlFor="my_address">
 | 
					 | 
				
			||||||
							Twój adres zamieszkania
 | 
					 | 
				
			||||||
						</label>
 | 
					 | 
				
			||||||
						<input
 | 
					 | 
				
			||||||
							type="text"
 | 
					 | 
				
			||||||
							className="input"
 | 
					 | 
				
			||||||
							id="my_address"
 | 
					 | 
				
			||||||
							value={formState.my_address}
 | 
					 | 
				
			||||||
							onChange={(e) =>
 | 
					 | 
				
			||||||
								formDispatch({
 | 
					 | 
				
			||||||
									type: "CHANGE_FIELD",
 | 
					 | 
				
			||||||
									payload: {
 | 
					 | 
				
			||||||
										field: e.target.id,
 | 
					 | 
				
			||||||
										value: e.target.value,
 | 
					 | 
				
			||||||
									},
 | 
					 | 
				
			||||||
								})
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						/>
 | 
					 | 
				
			||||||
						<label htmlFor="plate">
 | 
					 | 
				
			||||||
							Numer tablicy rejestracyjnej
 | 
					 | 
				
			||||||
						</label>
 | 
					 | 
				
			||||||
						<input
 | 
					 | 
				
			||||||
							type="text"
 | 
					 | 
				
			||||||
							className="input"
 | 
					 | 
				
			||||||
							id="plate"
 | 
					 | 
				
			||||||
							value={formState.plate}
 | 
					 | 
				
			||||||
							onChange={(e) =>
 | 
					 | 
				
			||||||
								formDispatch({
 | 
					 | 
				
			||||||
									type: "CHANGE_FIELD",
 | 
					 | 
				
			||||||
									payload: {
 | 
					 | 
				
			||||||
										field: e.target.id,
 | 
					 | 
				
			||||||
										value: e.target.value,
 | 
					 | 
				
			||||||
									},
 | 
					 | 
				
			||||||
								})
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						/>
 | 
					 | 
				
			||||||
						<div className="container__section__form__offenses">
 | 
					 | 
				
			||||||
							{offenses.map((offence, index) => (
 | 
					 | 
				
			||||||
								<div key={index}>
 | 
					 | 
				
			||||||
									<input
 | 
					 | 
				
			||||||
										type="checkbox"
 | 
					 | 
				
			||||||
										id={offence.id}
 | 
					 | 
				
			||||||
										value={offence.car_is}
 | 
					 | 
				
			||||||
										name={offence.car_is}
 | 
					 | 
				
			||||||
										className="chceckbox"
 | 
					 | 
				
			||||||
										onChange={(e) =>
 | 
					 | 
				
			||||||
											e.target.checked === true
 | 
					 | 
				
			||||||
												? formDispatch({
 | 
					 | 
				
			||||||
														type: "ADD_OFFENCE",
 | 
					 | 
				
			||||||
														payload: {
 | 
					 | 
				
			||||||
															value:
 | 
					 | 
				
			||||||
																e.target.value,
 | 
					 | 
				
			||||||
															field: "checkbox",
 | 
					 | 
				
			||||||
														},
 | 
					 | 
				
			||||||
												  })
 | 
					 | 
				
			||||||
												: formDispatch({
 | 
					 | 
				
			||||||
														type: "DELETE_OFFENCE",
 | 
					 | 
				
			||||||
														payload: {
 | 
					 | 
				
			||||||
															value:
 | 
					 | 
				
			||||||
																e.target.value,
 | 
					 | 
				
			||||||
															field: "checkbox",
 | 
					 | 
				
			||||||
														},
 | 
					 | 
				
			||||||
												  })
 | 
					 | 
				
			||||||
										}
 | 
					 | 
				
			||||||
									/>
 | 
					 | 
				
			||||||
									<label
 | 
					 | 
				
			||||||
										htmlFor={offence.id}
 | 
					 | 
				
			||||||
										className="label"
 | 
					 | 
				
			||||||
									>
 | 
					 | 
				
			||||||
										{offence.name}
 | 
					 | 
				
			||||||
									</label>
 | 
					 | 
				
			||||||
								</div>
 | 
					 | 
				
			||||||
							))}
 | 
					 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
						<label htmlFor="comment">
 | 
					 | 
				
			||||||
							Twój komentarz do zgłoszenia
 | 
					 | 
				
			||||||
						</label>
 | 
					 | 
				
			||||||
						<textarea
 | 
					 | 
				
			||||||
							className="textarea textarea--small"
 | 
					 | 
				
			||||||
							id="comment"
 | 
					 | 
				
			||||||
							name="comment"
 | 
					 | 
				
			||||||
							value={formState.comment}
 | 
					 | 
				
			||||||
							onChange={(e) =>
 | 
					 | 
				
			||||||
								formDispatch({
 | 
					 | 
				
			||||||
									type: "CHANGE_FIELD",
 | 
					 | 
				
			||||||
									payload: {
 | 
					 | 
				
			||||||
										field: e.target.id,
 | 
					 | 
				
			||||||
										value: e.target.value,
 | 
					 | 
				
			||||||
									},
 | 
					 | 
				
			||||||
								})
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						/>
 | 
					 | 
				
			||||||
						<label htmlFor="message">
 | 
					 | 
				
			||||||
							Wiadomość dla straży miejskiej
 | 
					 | 
				
			||||||
						</label>
 | 
					 | 
				
			||||||
						<textarea
 | 
					 | 
				
			||||||
							className="textarea"
 | 
					 | 
				
			||||||
							id="message"
 | 
					 | 
				
			||||||
							disabled={true}
 | 
					 | 
				
			||||||
							value={formMessage}
 | 
					 | 
				
			||||||
						/>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						<button
 | 
					 | 
				
			||||||
							className="button"
 | 
					 | 
				
			||||||
							onClick={(e) => handleSubmit(e)}
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
							Wysłanie zgłoszenia
 | 
					 | 
				
			||||||
						</button>
 | 
					 | 
				
			||||||
					</form>
 | 
					 | 
				
			||||||
				</section>
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		</>
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
render(<App />, document.getElementById("root"));
 | 
					 | 
				
			||||||
@ -1,7 +0,0 @@
 | 
				
			|||||||
export interface FileType {
 | 
					 | 
				
			||||||
	lastModified: number;
 | 
					 | 
				
			||||||
	name: string;
 | 
					 | 
				
			||||||
	size: number;
 | 
					 | 
				
			||||||
	type: string;
 | 
					 | 
				
			||||||
	webkitRelativePath: string;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,49 +0,0 @@
 | 
				
			|||||||
export interface File {
 | 
					 | 
				
			||||||
	img?: unknown;
 | 
					 | 
				
			||||||
	id: string;
 | 
					 | 
				
			||||||
	selected?: boolean;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
interface FilesState {
 | 
					 | 
				
			||||||
	files: Array<File>;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
interface FilesAction {
 | 
					 | 
				
			||||||
	type: string;
 | 
					 | 
				
			||||||
	payload: File;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export const filesInitialState = {
 | 
					 | 
				
			||||||
	files: [],
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
export function fileReducer(
 | 
					 | 
				
			||||||
	state: FilesState,
 | 
					 | 
				
			||||||
	action: FilesAction
 | 
					 | 
				
			||||||
): FilesState {
 | 
					 | 
				
			||||||
	switch (action.type) {
 | 
					 | 
				
			||||||
		case "ADD_FILE":
 | 
					 | 
				
			||||||
			return {
 | 
					 | 
				
			||||||
				...state,
 | 
					 | 
				
			||||||
				files: [
 | 
					 | 
				
			||||||
					...state.files,
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						img: action.payload.img,
 | 
					 | 
				
			||||||
						id: action.payload.id,
 | 
					 | 
				
			||||||
						selected: action.payload.selected,
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				],
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
		case "SELECT_FILE":
 | 
					 | 
				
			||||||
			return {
 | 
					 | 
				
			||||||
				...state,
 | 
					 | 
				
			||||||
				files: state.files.map((file: File) =>
 | 
					 | 
				
			||||||
					file.id == action.payload.id
 | 
					 | 
				
			||||||
						? { ...file, selected: true }
 | 
					 | 
				
			||||||
						: { ...file, selected: false }
 | 
					 | 
				
			||||||
				),
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
		case "CLEAR_FILES":
 | 
					 | 
				
			||||||
			return {
 | 
					 | 
				
			||||||
				files: [],
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			throw new Error();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,60 +0,0 @@
 | 
				
			|||||||
import { Address } from "./location";
 | 
					 | 
				
			||||||
interface FormState {
 | 
					 | 
				
			||||||
	name: string;
 | 
					 | 
				
			||||||
	email: string;
 | 
					 | 
				
			||||||
	plate: string;
 | 
					 | 
				
			||||||
	offenses: (Address | void | string)[];
 | 
					 | 
				
			||||||
	comment: string;
 | 
					 | 
				
			||||||
	my_address: string;
 | 
					 | 
				
			||||||
	address: Address;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
interface FormAction {
 | 
					 | 
				
			||||||
	type: string;
 | 
					 | 
				
			||||||
	payload: {
 | 
					 | 
				
			||||||
		field: string;
 | 
					 | 
				
			||||||
		value: Address | void | string;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export const fromInitialState = {
 | 
					 | 
				
			||||||
	name: "",
 | 
					 | 
				
			||||||
	email: "",
 | 
					 | 
				
			||||||
	plate: "",
 | 
					 | 
				
			||||||
	my_address: "",
 | 
					 | 
				
			||||||
	offenses: [],
 | 
					 | 
				
			||||||
	comment: "",
 | 
					 | 
				
			||||||
	address: {
 | 
					 | 
				
			||||||
		house_number: "",
 | 
					 | 
				
			||||||
		road: "",
 | 
					 | 
				
			||||||
		suburb: "",
 | 
					 | 
				
			||||||
		neighbourhood: "",
 | 
					 | 
				
			||||||
		hamlet: "",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
export function formReducer(state: FormState, action: FormAction): FormState {
 | 
					 | 
				
			||||||
	switch (action.type) {
 | 
					 | 
				
			||||||
		case "CHANGE_FIELD":
 | 
					 | 
				
			||||||
			return {
 | 
					 | 
				
			||||||
				...state,
 | 
					 | 
				
			||||||
				//action.payload.field is equal to name of the imput, example: e.target.name = plate
 | 
					 | 
				
			||||||
				[action.payload.field]: action.payload.value,
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
		case "ADD_OFFENCE":
 | 
					 | 
				
			||||||
			return {
 | 
					 | 
				
			||||||
				...state,
 | 
					 | 
				
			||||||
				offenses: [...state.offenses, action.payload.value],
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
		case "DELETE_OFFENCE":
 | 
					 | 
				
			||||||
			return {
 | 
					 | 
				
			||||||
				...state,
 | 
					 | 
				
			||||||
				offenses: state.offenses.filter(
 | 
					 | 
				
			||||||
					(offence: string) => offence !== action.payload.value
 | 
					 | 
				
			||||||
				),
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
		case "CHANGE_ADDRESS":
 | 
					 | 
				
			||||||
			return {
 | 
					 | 
				
			||||||
				...state,
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			throw new Error();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,14 +0,0 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html>
 | 
					 | 
				
			||||||
  <head>
 | 
					 | 
				
			||||||
    <link
 | 
					 | 
				
			||||||
      href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.3/leaflet.css"
 | 
					 | 
				
			||||||
      rel="stylesheet"
 | 
					 | 
				
			||||||
    />
 | 
					 | 
				
			||||||
    <title>Zgłaszańsko</title>
 | 
					 | 
				
			||||||
  </head>
 | 
					 | 
				
			||||||
  <body>
 | 
					 | 
				
			||||||
    <div id="root"></div>
 | 
					 | 
				
			||||||
    <script src="./app.tsx"></script>
 | 
					 | 
				
			||||||
  </body>
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||
@ -1,24 +0,0 @@
 | 
				
			|||||||
import axios from "axios";
 | 
					 | 
				
			||||||
export type Location = {
 | 
					 | 
				
			||||||
	lat: number;
 | 
					 | 
				
			||||||
	lon: number;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export type Address = {
 | 
					 | 
				
			||||||
	house_number?: string;
 | 
					 | 
				
			||||||
	road?: string;
 | 
					 | 
				
			||||||
	suburb?: string;
 | 
					 | 
				
			||||||
	neighbourhood?: string;
 | 
					 | 
				
			||||||
	hamlet?: string;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function getAddress(location: Location): Promise<Address | void> {
 | 
					 | 
				
			||||||
	const nominatim_url = `https://nominatim.openstreetmap.org/reverse?lat=${location.lat}&lon=${location.lon}&format=jsonv2`;
 | 
					 | 
				
			||||||
	try {
 | 
					 | 
				
			||||||
		const data = await axios.get(nominatim_url);
 | 
					 | 
				
			||||||
		const nominatim_dat = data.data as { address: Address };
 | 
					 | 
				
			||||||
		return nominatim_dat.address;
 | 
					 | 
				
			||||||
	} catch (error) {
 | 
					 | 
				
			||||||
		console.log(123);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,14 +0,0 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html>
 | 
					 | 
				
			||||||
	<head>
 | 
					 | 
				
			||||||
		<link
 | 
					 | 
				
			||||||
			href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.3/leaflet.css"
 | 
					 | 
				
			||||||
			rel="stylesheet"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<title>Zgłaszańsko</title>
 | 
					 | 
				
			||||||
	</head>
 | 
					 | 
				
			||||||
	<body>
 | 
					 | 
				
			||||||
		<div id="root"></div>
 | 
					 | 
				
			||||||
		<script src="./login.tsx"></script>
 | 
					 | 
				
			||||||
	</body>
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||
@ -1,94 +0,0 @@
 | 
				
			|||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
					 | 
				
			||||||
import React, { ReactElement, useEffect, useState } from "react";
 | 
					 | 
				
			||||||
import ReactDOM from "react-dom";
 | 
					 | 
				
			||||||
import Nav from "./Nav";
 | 
					 | 
				
			||||||
import "./styles/reset.css";
 | 
					 | 
				
			||||||
import "./styles/app.scss";
 | 
					 | 
				
			||||||
import "regenerator-runtime/runtime";
 | 
					 | 
				
			||||||
import axios from "axios";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default function Login(): ReactElement {
 | 
					 | 
				
			||||||
	const [isLogged, setIsLogged] = useState(false);
 | 
					 | 
				
			||||||
	const [error, setError] = useState(null);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const [loginState, setLoginState] = useState({
 | 
					 | 
				
			||||||
		username: "",
 | 
					 | 
				
			||||||
		password: "",
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	const checkUser = async (): Promise<void> => {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			await axios.get(
 | 
					 | 
				
			||||||
				"http://localhost:8080/api/v1/collections/users/me"
 | 
					 | 
				
			||||||
			);
 | 
					 | 
				
			||||||
			setIsLogged(true);
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			setIsLogged(false);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	useEffect(() => {
 | 
					 | 
				
			||||||
		void checkUser();
 | 
					 | 
				
			||||||
	}, []);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const postLogin = async () => {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			await axios.post("http://localhost:8080/api/v1/sessions/", {
 | 
					 | 
				
			||||||
				username: loginState.username,
 | 
					 | 
				
			||||||
				password: loginState.password,
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
			void checkUser();
 | 
					 | 
				
			||||||
		} catch (e) {
 | 
					 | 
				
			||||||
			console.log(e);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const notLoggedForm = () => {
 | 
					 | 
				
			||||||
		return (
 | 
					 | 
				
			||||||
			<form>
 | 
					 | 
				
			||||||
				<label htmlFor="username">
 | 
					 | 
				
			||||||
					Nazwa użytkownika
 | 
					 | 
				
			||||||
					<input
 | 
					 | 
				
			||||||
						type="text"
 | 
					 | 
				
			||||||
						name="username"
 | 
					 | 
				
			||||||
						value={loginState.username}
 | 
					 | 
				
			||||||
						onChange={(e) =>
 | 
					 | 
				
			||||||
							setLoginState({
 | 
					 | 
				
			||||||
								...loginState,
 | 
					 | 
				
			||||||
								username: e.target.value,
 | 
					 | 
				
			||||||
							})
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					/>
 | 
					 | 
				
			||||||
				</label>
 | 
					 | 
				
			||||||
				<label htmlFor="password">
 | 
					 | 
				
			||||||
					Hasło
 | 
					 | 
				
			||||||
					<input
 | 
					 | 
				
			||||||
						type="password"
 | 
					 | 
				
			||||||
						name="password"
 | 
					 | 
				
			||||||
						value={loginState.password}
 | 
					 | 
				
			||||||
						onChange={(e) =>
 | 
					 | 
				
			||||||
							setLoginState({
 | 
					 | 
				
			||||||
								...loginState,
 | 
					 | 
				
			||||||
								password: e.target.value,
 | 
					 | 
				
			||||||
							})
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					/>
 | 
					 | 
				
			||||||
				</label>
 | 
					 | 
				
			||||||
				<button
 | 
					 | 
				
			||||||
					type="submit"
 | 
					 | 
				
			||||||
					onClick={(e) => {
 | 
					 | 
				
			||||||
						e.preventDefault();
 | 
					 | 
				
			||||||
						console.log(postLogin());
 | 
					 | 
				
			||||||
					}}
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
					Zaloguj
 | 
					 | 
				
			||||||
				</button>
 | 
					 | 
				
			||||||
			</form>
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	return (
 | 
					 | 
				
			||||||
		<>
 | 
					 | 
				
			||||||
			<Nav isLogged={isLogged} logoutState={() => setIsLogged(false)} />
 | 
					 | 
				
			||||||
			{isLogged ? <h1>Jesteś zalogowany</h1> : notLoggedForm()}
 | 
					 | 
				
			||||||
		</>
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ReactDOM.render(<Login />, document.getElementById("root"));
 | 
					 | 
				
			||||||
@ -1,110 +0,0 @@
 | 
				
			|||||||
export type Offense = {
 | 
					 | 
				
			||||||
	name: string;
 | 
					 | 
				
			||||||
	car_is: string;
 | 
					 | 
				
			||||||
	id: string;
 | 
					 | 
				
			||||||
	implies?: string[];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const offenses: Offense[] = [
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "obszar_wyłączony",
 | 
					 | 
				
			||||||
		name: "Parkowanie na obszarze wyłączonym z ruchu",
 | 
					 | 
				
			||||||
		car_is: "jest zaparkowany na obszarze wyłączonym z ruchu",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "widoczność_pasy",
 | 
					 | 
				
			||||||
		name: "Ograniczanie widoczności na pasach",
 | 
					 | 
				
			||||||
		car_is:
 | 
					 | 
				
			||||||
			"ogranicza widoczność na przejściu dla pieszych, powodując zagrożenie osób korzystających z przejścia",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "widoczność_skrz",
 | 
					 | 
				
			||||||
		name: "Ograniczanie widoczności na skrzyżowaniu",
 | 
					 | 
				
			||||||
		car_is:
 | 
					 | 
				
			||||||
			"ogranicza widoczność na skrzyżowaniu, powodując zagrożenie dla uczestników ruchu",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "utrudnia_ruch_rowerom",
 | 
					 | 
				
			||||||
		name: "Utrudnianie ruchu rowerowego",
 | 
					 | 
				
			||||||
		car_is: "utrudnia ruch rowerowy",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "utrudnia_ruch_pieszym",
 | 
					 | 
				
			||||||
		name: "Utrudnianie ruchu pieszego",
 | 
					 | 
				
			||||||
		car_is: "utrudnia ruch pieszych",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "poza_wyzn",
 | 
					 | 
				
			||||||
		name: "Parkowanie poza wyznaczonym miejscem",
 | 
					 | 
				
			||||||
		car_is: "jest zaparkowany poza wyznaczonym miejscem parkingowym",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "przed_przejsc",
 | 
					 | 
				
			||||||
		name: "Parkowanie <10m przed przejściem dla pieszych",
 | 
					 | 
				
			||||||
		car_is: "jest zaparkowany mniej niż 10m przed przejściem dla pieszych",
 | 
					 | 
				
			||||||
		implies: ["widoczność_pasy"],
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "na_zakazie",
 | 
					 | 
				
			||||||
		name: "Parkowanie za znakiem zakazu parkowania",
 | 
					 | 
				
			||||||
		car_is: "jest zaparkowany za znakiem zakazu parkowania",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "brama",
 | 
					 | 
				
			||||||
		name: "Blokowanie bramy wjazdowej",
 | 
					 | 
				
			||||||
		car_is: "blokuje bramę wjazdową",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "na_chodzie",
 | 
					 | 
				
			||||||
		name: "Postój na chodzie",
 | 
					 | 
				
			||||||
		car_is: "ma włączony silnik podczas postoju",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "blk_chodnik",
 | 
					 | 
				
			||||||
		name: "Blokowanie chodnika",
 | 
					 | 
				
			||||||
		car_is:
 | 
					 | 
				
			||||||
			"jest zaparkowany na chodniku pozostawiając mniej niż 1,5m dla pieszych",
 | 
					 | 
				
			||||||
		implies: ["utrudnia_ruch_pieszym"],
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "chyba2.5t",
 | 
					 | 
				
			||||||
		name: "Duży samochód dostawczy na chodniku",
 | 
					 | 
				
			||||||
		car_is:
 | 
					 | 
				
			||||||
			"najprawdopodobniej przekracza dopuszczalną całkowitą masę 2,5t będąc zaparkowanym na chodniku",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "hydrant",
 | 
					 | 
				
			||||||
		name: "Blokowanie hydrantu",
 | 
					 | 
				
			||||||
		car_is: "blokuje dostęp do hydrantu",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "przystanek_15",
 | 
					 | 
				
			||||||
		name: "Parkowanie <15m od przystanku",
 | 
					 | 
				
			||||||
		car_is:
 | 
					 | 
				
			||||||
			"jest zaparkowany w odległości mniejszej niż 15m od tablicy oznaczającej przystanek",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "utr_innym_zapark",
 | 
					 | 
				
			||||||
		name: "Utrudnianie wyjazdu innym zaparkowanym samochodom",
 | 
					 | 
				
			||||||
		car_is:
 | 
					 | 
				
			||||||
			"dokonuje postoju w miejscu utrudniającym dostęp do innych, prawidłowo zaparkowanych pojazdów lub wyjazd tych pojazdów",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "pas_rowerow",
 | 
					 | 
				
			||||||
		name: "blokuje pas rowerów",
 | 
					 | 
				
			||||||
		car_is: "zaparkowany na pasie dla rowerów",
 | 
					 | 
				
			||||||
		implies: ["utrudnia_ruch_rowerom"],
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "t30",
 | 
					 | 
				
			||||||
		name: "Parkowanie niezgodnie z rysunkiem na tabliczce (T-30)",
 | 
					 | 
				
			||||||
		car_is:
 | 
					 | 
				
			||||||
			"nie stosuje się do znaku T-30, wskazującego sposób ustawienia pojazdu względem krawędzi jezdni",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		id: "blokuje_znak",
 | 
					 | 
				
			||||||
		name: "Zasłanianie znaku drogowego",
 | 
					 | 
				
			||||||
		car_is:
 | 
					 | 
				
			||||||
			"zaparkowany w odległości mniejszej niż 10m od przedniej strony znaku drogowego, zasłaniając go (Art 49, punkt 1, ust. 6)",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
];
 | 
					 | 
				
			||||||
@ -1,14 +0,0 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html>
 | 
					 | 
				
			||||||
	<head>
 | 
					 | 
				
			||||||
		<link
 | 
					 | 
				
			||||||
			href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.3/leaflet.css"
 | 
					 | 
				
			||||||
			rel="stylesheet"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<title>Zgłaszańsko</title>
 | 
					 | 
				
			||||||
	</head>
 | 
					 | 
				
			||||||
	<body>
 | 
					 | 
				
			||||||
		<div id="root"></div>
 | 
					 | 
				
			||||||
		<script src="./register.tsx"></script>
 | 
					 | 
				
			||||||
	</body>
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||
@ -1,78 +0,0 @@
 | 
				
			|||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
					 | 
				
			||||||
import React, { ReactElement, useEffect, useState } from "react";
 | 
					 | 
				
			||||||
import ReactDOM from "react-dom";
 | 
					 | 
				
			||||||
import Nav from "./Nav";
 | 
					 | 
				
			||||||
import "./styles/reset.css";
 | 
					 | 
				
			||||||
import "./styles/app.scss";
 | 
					 | 
				
			||||||
import "regenerator-runtime/runtime";
 | 
					 | 
				
			||||||
import axios from "axios";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default function Register(): ReactElement {
 | 
					 | 
				
			||||||
	const [isLogged, setIsLogged] = useState(false);
 | 
					 | 
				
			||||||
	const [registerState, setRegisterState] = useState({
 | 
					 | 
				
			||||||
		email: "",
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	const [error, setError] = useState(null);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const checkUser = async (): Promise<void> => {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			await axios.get(
 | 
					 | 
				
			||||||
				"http://localhost:8080/api/v1/collections/users/me"
 | 
					 | 
				
			||||||
			);
 | 
					 | 
				
			||||||
			setIsLogged(true);
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			setIsLogged(false);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	useEffect(() => {
 | 
					 | 
				
			||||||
		void checkUser();
 | 
					 | 
				
			||||||
	}, []);
 | 
					 | 
				
			||||||
	const postRegister = async () => {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			await axios.post(
 | 
					 | 
				
			||||||
				"http://localhost:8080/api/v1/collections/registration-intents",
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					email: registerState.email,
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			);
 | 
					 | 
				
			||||||
			void checkUser();
 | 
					 | 
				
			||||||
		} catch (e) {
 | 
					 | 
				
			||||||
			console.log(e);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	const notLoggedForm = () => {
 | 
					 | 
				
			||||||
		return (
 | 
					 | 
				
			||||||
			<form>
 | 
					 | 
				
			||||||
				<label htmlFor="email">
 | 
					 | 
				
			||||||
					Adres email
 | 
					 | 
				
			||||||
					<input
 | 
					 | 
				
			||||||
						type="email"
 | 
					 | 
				
			||||||
						name="email"
 | 
					 | 
				
			||||||
						value={registerState.email}
 | 
					 | 
				
			||||||
						onChange={(e) =>
 | 
					 | 
				
			||||||
							setRegisterState({
 | 
					 | 
				
			||||||
								email: e.target.value,
 | 
					 | 
				
			||||||
							})
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					/>
 | 
					 | 
				
			||||||
				</label>
 | 
					 | 
				
			||||||
				<button
 | 
					 | 
				
			||||||
					type="submit"
 | 
					 | 
				
			||||||
					onClick={(e) => {
 | 
					 | 
				
			||||||
						e.preventDefault();
 | 
					 | 
				
			||||||
						console.log(postRegister());
 | 
					 | 
				
			||||||
					}}
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
					Zaloguj
 | 
					 | 
				
			||||||
				</button>
 | 
					 | 
				
			||||||
			</form>
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	return (
 | 
					 | 
				
			||||||
		<>
 | 
					 | 
				
			||||||
			<Nav isLogged={isLogged} logoutState={() => setIsLogged(false)} />
 | 
					 | 
				
			||||||
			{isLogged ? <h1>Jesteś zalogowany</h1> : notLoggedForm()}
 | 
					 | 
				
			||||||
		</>
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ReactDOM.render(<Register />, document.getElementById("root"));
 | 
					 | 
				
			||||||
@ -1,147 +0,0 @@
 | 
				
			|||||||
.button:hover {
 | 
					 | 
				
			||||||
	filter: brightness(1.1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.container {
 | 
					 | 
				
			||||||
	width: 100%;
 | 
					 | 
				
			||||||
	height: 100vh;
 | 
					 | 
				
			||||||
	display: flex;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.button {
 | 
					 | 
				
			||||||
	background-color: #999;
 | 
					 | 
				
			||||||
	height: 2rem;
 | 
					 | 
				
			||||||
	line-height: 2rem;
 | 
					 | 
				
			||||||
	padding: 0 0.75rem;
 | 
					 | 
				
			||||||
	text-decoration: none;
 | 
					 | 
				
			||||||
	color: white;
 | 
					 | 
				
			||||||
	border: none;
 | 
					 | 
				
			||||||
	cursor: pointer;
 | 
					 | 
				
			||||||
	margin: 0 15px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.container__section {
 | 
					 | 
				
			||||||
	flex: 1;
 | 
					 | 
				
			||||||
	padding: 15px;
 | 
					 | 
				
			||||||
	display: block;
 | 
					 | 
				
			||||||
	height: auto;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.container__section__title {
 | 
					 | 
				
			||||||
	margin: 15px 0;
 | 
					 | 
				
			||||||
	font-size: 1.5em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.container__section__photos {
 | 
					 | 
				
			||||||
	display: grid;
 | 
					 | 
				
			||||||
	grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
 | 
					 | 
				
			||||||
	row-gap: 35px;
 | 
					 | 
				
			||||||
	column-gap: 15px;
 | 
					 | 
				
			||||||
	justify-items: stretch;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.section__photos__item {
 | 
					 | 
				
			||||||
	width: 150px;
 | 
					 | 
				
			||||||
	height: 150px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.section__photos__item--active {
 | 
					 | 
				
			||||||
	width: 150px;
 | 
					 | 
				
			||||||
	height: 150px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.container__section__map {
 | 
					 | 
				
			||||||
	cursor: default;
 | 
					 | 
				
			||||||
	height: 600px;
 | 
					 | 
				
			||||||
	width: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.container__section__form {
 | 
					 | 
				
			||||||
	width: 100%;
 | 
					 | 
				
			||||||
	height: 600px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.input {
 | 
					 | 
				
			||||||
	width: 100%;
 | 
					 | 
				
			||||||
	height: 30px;
 | 
					 | 
				
			||||||
	margin-bottom: 15px;
 | 
					 | 
				
			||||||
	margin-top: 5px;
 | 
					 | 
				
			||||||
	display: block;
 | 
					 | 
				
			||||||
	box-sizing: border-box;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.textarea {
 | 
					 | 
				
			||||||
	width: 100%;
 | 
					 | 
				
			||||||
	height: 350px;
 | 
					 | 
				
			||||||
	margin-bottom: 15px;
 | 
					 | 
				
			||||||
	margin-top: 5px;
 | 
					 | 
				
			||||||
	display: block;
 | 
					 | 
				
			||||||
	box-sizing: border-box;
 | 
					 | 
				
			||||||
	resize: none;
 | 
					 | 
				
			||||||
	font-size: 1.1rem;
 | 
					 | 
				
			||||||
	padding: 3px 8px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.textarea--small {
 | 
					 | 
				
			||||||
	height: 150px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.label {
 | 
					 | 
				
			||||||
	width: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.container__section__form__offenses {
 | 
					 | 
				
			||||||
	margin-bottom: 15px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
//to change name
 | 
					 | 
				
			||||||
.img {
 | 
					 | 
				
			||||||
	width: 100%;
 | 
					 | 
				
			||||||
	height: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.img--active {
 | 
					 | 
				
			||||||
	width: 100%;
 | 
					 | 
				
			||||||
	height: 100%;
 | 
					 | 
				
			||||||
	border: 3px solid seagreen;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.chceckbox {
 | 
					 | 
				
			||||||
	appearance: none;
 | 
					 | 
				
			||||||
	vertical-align: middle;
 | 
					 | 
				
			||||||
	font-size: inherit;
 | 
					 | 
				
			||||||
	cursor: pointer;
 | 
					 | 
				
			||||||
	width: 1.5em;
 | 
					 | 
				
			||||||
	height: 1.5em;
 | 
					 | 
				
			||||||
	background: white;
 | 
					 | 
				
			||||||
	border: 0.1em solid #000000;
 | 
					 | 
				
			||||||
	position: relative;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
input[type="checkbox"]:checked {
 | 
					 | 
				
			||||||
	background: #000000;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/*breakpoint for mobile*/
 | 
					 | 
				
			||||||
@media (max-width: 1200px) {
 | 
					 | 
				
			||||||
	body {
 | 
					 | 
				
			||||||
		font-size: 3rem;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	.container {
 | 
					 | 
				
			||||||
		flex-direction: column;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	.container__section__title {
 | 
					 | 
				
			||||||
		margin: 25px 0;
 | 
					 | 
				
			||||||
		font-size: 1.5em;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	.container__section__photos {
 | 
					 | 
				
			||||||
		grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	.section__photos__item {
 | 
					 | 
				
			||||||
		width: 200px;
 | 
					 | 
				
			||||||
		height: 200px;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	.container__section__form {
 | 
					 | 
				
			||||||
		width: 100%;
 | 
					 | 
				
			||||||
		height: 600px;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	.textarea {
 | 
					 | 
				
			||||||
		font-size: 2rem;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	.input {
 | 
					 | 
				
			||||||
		width: 90%;
 | 
					 | 
				
			||||||
		height: 75px;
 | 
					 | 
				
			||||||
		font-size: 2rem;
 | 
					 | 
				
			||||||
		margin-top: 10px;
 | 
					 | 
				
			||||||
		margin-bottom: 25px;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	.input--textarea {
 | 
					 | 
				
			||||||
		height: 450px;
 | 
					 | 
				
			||||||
		width: 90%;
 | 
					 | 
				
			||||||
		margin-top: 10px;
 | 
					 | 
				
			||||||
		margin-bottom: 25px;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,27 +0,0 @@
 | 
				
			|||||||
.navbar {
 | 
					 | 
				
			||||||
	width: 100%;
 | 
					 | 
				
			||||||
	display: flex;
 | 
					 | 
				
			||||||
	align-items: center;
 | 
					 | 
				
			||||||
	justify-content: space-between;
 | 
					 | 
				
			||||||
	border-bottom: #000000 2px solid;
 | 
					 | 
				
			||||||
	padding: 15px 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.navbar__title {
 | 
					 | 
				
			||||||
	font-size: 1.5em;
 | 
					 | 
				
			||||||
	margin: 0 15px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.navbar__links {
 | 
					 | 
				
			||||||
	display: flex;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.button-link {
 | 
					 | 
				
			||||||
	background-color: #999;
 | 
					 | 
				
			||||||
	height: 2rem;
 | 
					 | 
				
			||||||
	line-height: 2rem;
 | 
					 | 
				
			||||||
	padding: 0 0.75rem;
 | 
					 | 
				
			||||||
	text-decoration: none;
 | 
					 | 
				
			||||||
	color: white;
 | 
					 | 
				
			||||||
	border: none;
 | 
					 | 
				
			||||||
	cursor: pointer;
 | 
					 | 
				
			||||||
	margin: 0 15px;
 | 
					 | 
				
			||||||
	font-size: 0.9em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,127 +0,0 @@
 | 
				
			|||||||
/* http://meyerweb.com/eric/tools/css/reset/ 
 | 
					 | 
				
			||||||
   v2.0 | 20110126
 | 
					 | 
				
			||||||
   License: none (public domain)
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
html,
 | 
					 | 
				
			||||||
body,
 | 
					 | 
				
			||||||
div,
 | 
					 | 
				
			||||||
span,
 | 
					 | 
				
			||||||
applet,
 | 
					 | 
				
			||||||
object,
 | 
					 | 
				
			||||||
iframe,
 | 
					 | 
				
			||||||
h1,
 | 
					 | 
				
			||||||
h2,
 | 
					 | 
				
			||||||
h3,
 | 
					 | 
				
			||||||
h4,
 | 
					 | 
				
			||||||
h5,
 | 
					 | 
				
			||||||
h6,
 | 
					 | 
				
			||||||
p,
 | 
					 | 
				
			||||||
blockquote,
 | 
					 | 
				
			||||||
pre,
 | 
					 | 
				
			||||||
a,
 | 
					 | 
				
			||||||
abbr,
 | 
					 | 
				
			||||||
acronym,
 | 
					 | 
				
			||||||
address,
 | 
					 | 
				
			||||||
big,
 | 
					 | 
				
			||||||
cite,
 | 
					 | 
				
			||||||
code,
 | 
					 | 
				
			||||||
del,
 | 
					 | 
				
			||||||
dfn,
 | 
					 | 
				
			||||||
em,
 | 
					 | 
				
			||||||
img,
 | 
					 | 
				
			||||||
ins,
 | 
					 | 
				
			||||||
kbd,
 | 
					 | 
				
			||||||
q,
 | 
					 | 
				
			||||||
s,
 | 
					 | 
				
			||||||
samp,
 | 
					 | 
				
			||||||
small,
 | 
					 | 
				
			||||||
strike,
 | 
					 | 
				
			||||||
strong,
 | 
					 | 
				
			||||||
sub,
 | 
					 | 
				
			||||||
sup,
 | 
					 | 
				
			||||||
tt,
 | 
					 | 
				
			||||||
var,
 | 
					 | 
				
			||||||
b,
 | 
					 | 
				
			||||||
u,
 | 
					 | 
				
			||||||
i,
 | 
					 | 
				
			||||||
center,
 | 
					 | 
				
			||||||
dl,
 | 
					 | 
				
			||||||
dt,
 | 
					 | 
				
			||||||
dd,
 | 
					 | 
				
			||||||
ol,
 | 
					 | 
				
			||||||
ul,
 | 
					 | 
				
			||||||
li,
 | 
					 | 
				
			||||||
fieldset,
 | 
					 | 
				
			||||||
form,
 | 
					 | 
				
			||||||
label,
 | 
					 | 
				
			||||||
legend,
 | 
					 | 
				
			||||||
table,
 | 
					 | 
				
			||||||
caption,
 | 
					 | 
				
			||||||
tbody,
 | 
					 | 
				
			||||||
tfoot,
 | 
					 | 
				
			||||||
thead,
 | 
					 | 
				
			||||||
tr,
 | 
					 | 
				
			||||||
th,
 | 
					 | 
				
			||||||
td,
 | 
					 | 
				
			||||||
article,
 | 
					 | 
				
			||||||
aside,
 | 
					 | 
				
			||||||
canvas,
 | 
					 | 
				
			||||||
details,
 | 
					 | 
				
			||||||
embed,
 | 
					 | 
				
			||||||
figure,
 | 
					 | 
				
			||||||
figcaption,
 | 
					 | 
				
			||||||
footer,
 | 
					 | 
				
			||||||
header,
 | 
					 | 
				
			||||||
hgroup,
 | 
					 | 
				
			||||||
menu,
 | 
					 | 
				
			||||||
nav,
 | 
					 | 
				
			||||||
output,
 | 
					 | 
				
			||||||
ruby,
 | 
					 | 
				
			||||||
section,
 | 
					 | 
				
			||||||
summary,
 | 
					 | 
				
			||||||
time,
 | 
					 | 
				
			||||||
mark,
 | 
					 | 
				
			||||||
audio,
 | 
					 | 
				
			||||||
video {
 | 
					 | 
				
			||||||
	margin: 0;
 | 
					 | 
				
			||||||
	padding: 0;
 | 
					 | 
				
			||||||
	border: 0;
 | 
					 | 
				
			||||||
	vertical-align: baseline;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/* HTML5 display-role reset for older browsers */
 | 
					 | 
				
			||||||
article,
 | 
					 | 
				
			||||||
aside,
 | 
					 | 
				
			||||||
details,
 | 
					 | 
				
			||||||
figcaption,
 | 
					 | 
				
			||||||
figure,
 | 
					 | 
				
			||||||
footer,
 | 
					 | 
				
			||||||
header,
 | 
					 | 
				
			||||||
hgroup,
 | 
					 | 
				
			||||||
menu,
 | 
					 | 
				
			||||||
nav,
 | 
					 | 
				
			||||||
section {
 | 
					 | 
				
			||||||
	display: block;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
body {
 | 
					 | 
				
			||||||
	line-height: 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ol,
 | 
					 | 
				
			||||||
ul {
 | 
					 | 
				
			||||||
	list-style: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
blockquote,
 | 
					 | 
				
			||||||
q {
 | 
					 | 
				
			||||||
	quotes: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
blockquote:before,
 | 
					 | 
				
			||||||
blockquote:after,
 | 
					 | 
				
			||||||
q:before,
 | 
					 | 
				
			||||||
q:after {
 | 
					 | 
				
			||||||
	content: "";
 | 
					 | 
				
			||||||
	content: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
table {
 | 
					 | 
				
			||||||
	border-collapse: collapse;
 | 
					 | 
				
			||||||
	border-spacing: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					  <title>Zgłaszańsko</title>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					  <h1>Zgłaszańsko</h1>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					import { submit } from "poznan-sm-submit";
 | 
				
			||||||
@ -1,24 +0,0 @@
 | 
				
			|||||||
FROM node:15-alpine
 | 
					 | 
				
			||||||
LABEL maintainer="Jakub Pieńkowski <jakski@sealcode.org>"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ENV UID=node \
 | 
					 | 
				
			||||||
    GID=node \
 | 
					 | 
				
			||||||
    HOME=/opt/sealious
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RUN sed -i 's/http\:\/\/dl-cdn.alpinelinux.org/https\:\/\/mirrors.dotsrc.org/g' /etc/apk/repositories
 | 
					 | 
				
			||||||
# Tini will ensure that any orphaned processes get reaped properly.
 | 
					 | 
				
			||||||
RUN apk add --no-cache tini
 | 
					 | 
				
			||||||
RUN apk --update add git
 | 
					 | 
				
			||||||
RUN apk --update add python
 | 
					 | 
				
			||||||
RUN apk --update add make
 | 
					 | 
				
			||||||
RUN apk --update add g++
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VOLUME $HOME
 | 
					 | 
				
			||||||
WORKDIR $HOME
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
USER $UID:$GID
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EXPOSE 8080
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ENTRYPOINT ["/sbin/tini", "--"]
 | 
					 | 
				
			||||||
CMD ["/usr/local/bin/node", "."]
 | 
					 | 
				
			||||||
@ -1,20 +1,19 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	"compilerOptions": {
 | 
					  "compilerOptions": {
 | 
				
			||||||
		"jsx": "react",
 | 
					    "module": "esnext",
 | 
				
			||||||
		"module": "commonjs",
 | 
					    "moduleResolution": "node",
 | 
				
			||||||
		"moduleResolution": "node",
 | 
					    "noImplicitAny": true,
 | 
				
			||||||
		"noImplicitAny": false,
 | 
					    "noImplicitThis": true,
 | 
				
			||||||
		"noImplicitThis": true,
 | 
					    "strictNullChecks": true,
 | 
				
			||||||
		"strictNullChecks": true,
 | 
					    "target": "ES2020",
 | 
				
			||||||
		"target": "ES6",
 | 
					    "declaration": true,
 | 
				
			||||||
		"declaration": true,
 | 
					    "esModuleInterop": true,
 | 
				
			||||||
		"esModuleInterop": true,
 | 
					    "lib": ["es6", "esnext"],
 | 
				
			||||||
		"lib": ["dom"],
 | 
					    "outDir": "lib",
 | 
				
			||||||
		"outDir": "lib",
 | 
					    "checkJs": true,
 | 
				
			||||||
		"checkJs": true,
 | 
					    "allowJs": true,
 | 
				
			||||||
		"allowJs": true,
 | 
					    "declarationDir": "@types",
 | 
				
			||||||
		"declarationDir": "@types",
 | 
					    "sourceMap": true
 | 
				
			||||||
		"sourceMap": true
 | 
					  },
 | 
				
			||||||
	},
 | 
					  "include": ["src/**/*"]
 | 
				
			||||||
	"include": ["src/**/*"]
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
					Loading…
					
					
				
		Reference in New Issue