Fixed types, basic auth, fixed geting location, added loginpage

master
franciszek 3 years ago
parent 5110955b22
commit 4ea0a209f5

@ -1,6 +0,0 @@
{
"phabricator.uri": "https://hub.sealcode.org/",
"load": [
"arcanist-linters"
]
}

@ -1,14 +0,0 @@
{
"linters": {
"prettier": {
"type": "prettier",
"bin": "./node_modules/.bin/prettier",
"include": ["(\\.js$)", "(\\.ts$)", "(\\.css$)"]
},
"eslint": {
"type": "eslint",
"include": ["(\\.ts$)", "(\\.js$)"]
}
}
}

@ -1,7 +1,7 @@
module.exports = {
env: { node: true },
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint", "prettier"],
plugins: ["@typescript-eslint", "prettier", "jsdoc"],
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
@ -14,11 +14,11 @@ module.exports = {
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" } },

96
package-lock.json generated

@ -1842,19 +1842,11 @@
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
},
"axios": {
"version": "0.18.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz",
"integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==",
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": {
"follow-redirects": "1.5.10",
"is-buffer": "^2.0.2"
},
"dependencies": {
"is-buffer": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="
}
"follow-redirects": "^1.10.0"
}
},
"babel-plugin-dynamic-import-node": {
@ -3768,6 +3760,14 @@
}
}
},
"eslint-plugin-prettier": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz",
"integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==",
"requires": {
"prettier-linter-helpers": "^1.0.0"
}
},
"eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@ -4044,6 +4044,11 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"fast-diff": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w=="
},
"fast-glob": {
"version": "2.2.7",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz",
@ -4140,27 +4145,9 @@
"dev": true
},
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
"requires": {
"debug": "=3.1.0"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz",
"integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA=="
},
"for-in": {
"version": "1.0.2",
@ -7246,6 +7233,14 @@
"integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==",
"dev": true
},
"prettier-linter-helpers": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
"requires": {
"fast-diff": "^1.1.2"
}
},
"pretty-ms": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz",
@ -7978,6 +7973,15 @@
"color-convert": "^2.0.1"
}
},
"axios": {
"version": "0.18.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz",
"integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==",
"requires": {
"follow-redirects": "1.5.10",
"is-buffer": "^2.0.2"
}
},
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
@ -8029,6 +8033,22 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
},
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
"requires": {
"debug": "=3.1.0"
}
},
"get-port": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz",
@ -8039,11 +8059,21 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"is-buffer": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="
},
"mime": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz",
"integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag=="
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",

@ -6,8 +6,8 @@
"scripts": {
"back:build": "tsc",
"back:watch": "npm run back:build -- --watch",
"front:build": "parcel build --out-dir public src/front/index.html",
"front:watch": "parcel watch --out-dir public src/front/index.html",
"front:build": "parcel build --out-dir public src/front/*.html",
"front:watch": "parcel watch --out-dir public src/front/*.html",
"start": "nodemon lib/back/index.js"
},
"repository": {
@ -24,6 +24,8 @@
"@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",
@ -32,18 +34,17 @@
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-leaflet": "^3.0.5",
"sealious": "^0.13.8",
"typescript": "^4.1.3"
"sealious": "^0.13.8"
},
"devDependencies": {
"@types/leaflet": "^1.5.19",
"@types/node": "^14.14.20",
"@types/request": "^2.48.5",
"sass": "^1.32.0",
"typescript": "^4.1.3",
"prettier": "^2.0.5",
"eslint-plugin-jsdoc": "^30.0.3",
"eslint": "^7.5.0",
"eslint-config-prettier": "^6.11.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"
}
}

@ -20,7 +20,7 @@ const app = new (class extends App {
datastore_mongo: {
host: "localhost",
port: 20724,
db_name: "cloud-dashboard",
db_name: "zglaszansko-web",
},
email: {
from_address: "sealious-playground@example.com",
@ -44,7 +44,7 @@ const app = new (class extends App {
};
})();
const port = 3000;
const port = 8080;
console.log(`Listening on 127.0.0.1:${port}`);
app.start();

@ -1,19 +1,33 @@
import React, { ReactElement } from "react";
import "./styles/app.scss";
import React, { ReactElement, useEffect, useState } from "react";
import "./styles/nav.scss";
interface Props {
isLogged: boolean;
}
const NOT_LOGGED = [
{ name: "aplikacja", href: "/" },
{ name: "logowanie", href: "login.html" },
];
const LOGGED = [
{ name: "aplikacja", href: "/" },
{ name: "wyloguj", href: "login.html" },
];
interface Props {}
const logged = [{ name: "Login" }];
function Nav({}: Props): ReactElement {
function Nav({ isLogged }: Props): ReactElement {
return (
<nav className="navbar">
<h1 className="navbar__title">Zgłaszańsko web</h1>
<h2 className="navbar__title">Zgłaszańsko web</h2>
<div className="navbar__links">
<a href="" className="button-link">
test
</a>{" "}
<a href="" className="button-link">
test
</a>
{isLogged
? LOGGED.map((ele) => (
<a href={ele.href} className="button-link">
{ele.name}
</a>
))
: NOT_LOGGED.map((ele) => (
<a href={ele.href} className="button-link">
{ele.name}
</a>
))}
</div>
</nav>
);

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import React, {
useState,
useReducer,
@ -7,8 +8,9 @@ import React, {
FormEvent,
useEffect,
} from "react";
import * as ReactDOM from "react-dom";
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";
@ -18,8 +20,25 @@ 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 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();
}, []);
//This reducer handles adding and selecting files.
//I'm passing in initial state "{files: []}" from fileReducer file.
//State can be changed by using dispatch function with object contaning right type and payload.
@ -35,7 +54,7 @@ const App: FC = () => {
const [formState, formDispatch] = useReducer(formReducer, fromInitialState);
//This hook handles pining location on the map
const [mapPin, setMapPin] = useState({ lat: 52.39663, lon: 16.89866 });
const [mapPin, setMapPin] = useState({ lat: 0, lon: 0 });
const handleSubmit = async (
event: FormEvent<HTMLFormElement> | MouseEvent<HTMLButtonElement>
@ -46,10 +65,12 @@ const App: FC = () => {
const handleUpload = (e: ChangeEvent<HTMLInputElement>) => {
const files = e.target.files;
const readAndPreview = (file: any) => {
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)) {
let reader = new FileReader();
const reader = new FileReader();
reader.addEventListener(
"load",
function () {
@ -64,15 +85,16 @@ const App: FC = () => {
},
false
);
reader.readAsDataURL(file);
reader.readAsDataURL((file as unknown) as Blob);
}
};
if (files) {
[].forEach.call(files, readAndPreview);
}
};
useEffect(() => {
getAddress(mapPin).then((blob) =>
void getAddress(mapPin).then((blob) =>
formDispatch({
type: "CHANGE_FIELD",
payload: {
@ -82,6 +104,7 @@ const App: FC = () => {
})
);
}, [mapPin]);
const MapComponent = () => {
useMapEvents({
click: async (e) => {
@ -90,7 +113,7 @@ const App: FC = () => {
});
return null;
};
// console.log(getAddress(mapPin));
const formMessage = `Rejestracja: ${formState.plate}\nMiejsce: ${
formState.address.road === undefined ? "" : formState.address.road
} ${
@ -108,7 +131,7 @@ const App: FC = () => {
return (
<>
<Nav />
<Nav isLogged={isLogged} />
<div className="container">
<section className="container__section">
<h2 className="container__section__title">Zdjęcia</h2>
@ -119,13 +142,15 @@ const App: FC = () => {
onClick={(e: MouseEvent) =>
fileDispatch({
type: "SELECT_FILE",
payload: { id: (e.target as any).id },
payload: {
id: (e.target as Element).id,
},
})
}
className="section__photos__item"
>
<img
src={file.img}
src={file.img as string}
id={file.id}
className={
file.selected ? "img--active" : "img"
@ -157,9 +182,11 @@ const App: FC = () => {
attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"
/>
<Marker
position={[mapPin.lat, mapPin.lon]}
></Marker>
{mapPin.lat !== 0 ? (
<Marker
position={[mapPin.lat, mapPin.lon]}
></Marker>
) : null}
<MapComponent />
</MapContainer>
</div>
@ -328,4 +355,4 @@ const App: FC = () => {
);
};
ReactDOM.render(<App />, document.getElementById("root"));
render(<App />, document.getElementById("root"));

@ -0,0 +1,7 @@
export interface FileType {
lastModified: number;
name: string;
size: number;
type: string;
webkitRelativePath: string;
}

@ -1,23 +1,22 @@
export interface File {
img: string;
img?: unknown;
id: string;
selected: boolean;
selected?: boolean;
}
interface FilesState {
files: Array<File>;
}
interface FilesAction {
type: string;
payload: {
img?: any;
id: string;
selected?: boolean;
};
payload: File;
}
export const filesInitialState = {
files: [],
};
export function fileReducer(state: FilesState, action: FilesAction) {
export function fileReducer(
state: FilesState,
action: FilesAction
): FilesState {
switch (action.type) {
case "ADD_FILE":
return {

@ -3,7 +3,7 @@ interface FormState {
name: string;
email: string;
plate: string;
offenses: string[];
offenses: (Address | void | string)[];
comment: string;
my_address: string;
address: Address;
@ -12,7 +12,7 @@ interface FormAction {
type: string;
payload: {
field: string;
value: string | Address;
value: Address | void | string;
};
}
export const fromInitialState = {
@ -30,7 +30,7 @@ export const fromInitialState = {
hamlet: "",
},
};
export function formReducer(state: FormState, action: FormAction) {
export function formReducer(state: FormState, action: FormAction): FormState {
switch (action.type) {
case "CHANGE_FIELD":
return {

@ -1,18 +0,0 @@
import request from "request";
export async function getJSON(uri: string): Promise<Object> {
return new Promise(function (resolve, reject) {
let data = "";
const reply = request({
uri,
headers: {
"User-Agent": "Poznanski Parkingowy Patrol - telegram bot",
},
});
reply.on("data", (chunk) => {
data += chunk;
});
reply.on("error", reject);
reply.on("end", () => resolve(JSON.parse(data)));
});
}

@ -1,22 +1,24 @@
import { getJSON } from "./http";
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;
house_number?: string;
road?: string;
suburb?: string;
neighbourhood?: string;
hamlet?: string;
};
export async function getAddress(location: Location): Promise<Address> {
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`;
const nominatim_data = (await getJSON(nominatim_url)) as {
address: Address;
};
return nominatim_data.address;
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);
}
}

@ -0,0 +1,14 @@
<!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>

@ -0,0 +1,97 @@
/* 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 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 [loginState, setLoginState] = useState({
username: "",
password: "",
});
const [error, setError] = useState(null);
const postLogin = async () => {
try {
await axios.post("http://localhost:8080/api/v1/sessions/", {
username: loginState.username,
password: loginState.password,
});
} catch (e) {
console.log(e);
}
};
const logout = async () => {
const who = await axios.get(
"http://localhost:8080/api/v1/collections/users/me"
);
console.log(who);
const logout = await axios.delete(
"http://localhost:8080/api/v1/collections/sessions/current"
);
console.log(logout);
};
return (
<>
<Nav isLogged={isLogged} />
<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>
<button onClick={logout}>Wyloguj</button>
</>
);
}
ReactDOM.render(<Login />, document.getElementById("root"));

@ -1,110 +1,110 @@
export type Offense = {
name: string;
car_is: string;
id: string;
implies?: string[];
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)",
},
{
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,23 +1,16 @@
.navbar {
width: 100%;
height: 50px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: #000000 2px solid;
}
.navbar__title {
font-size: 1.5em;
margin: 0 15px;
.button:hover {
filter: brightness(1.1);
}
.navbar__links {
.container {
width: 100%;
height: 100vh;
display: flex;
}
.button-link {
.button {
background-color: #999;
height: 2rem;
line-height: 2rem;
display: flex;
padding: 0 0.75rem;
text-decoration: none;
color: white;
@ -25,27 +18,11 @@
cursor: pointer;
margin: 0 15px;
}
.button:hover {
filter: brightness(1.1);
}
.container {
width: 100%;
height: 100vh;
display: flex;
}
.button {
border: rgba(0, 0, 0, 0.116) 1px solid;
background-color: none;
margin: 15px 0;
width: 150px;
height: 50px;
}
.container__section {
flex: 1;
padding: 15px;
display: block;
height: auto;
}
.container__section__title {
margin: 15px 0;
@ -92,7 +69,7 @@
display: block;
box-sizing: border-box;
resize: none;
font-size: 1.2em;
font-size: 1.1rem;
padding: 3px 8px;
}
.textarea--small {
@ -131,7 +108,7 @@ input[type="checkbox"]:checked {
/*breakpoint for mobile*/
@media (max-width: 1200px) {
body {
font-size: 2rem;
font-size: 3rem;
}
.container {
flex-direction: column;
@ -147,15 +124,13 @@ input[type="checkbox"]:checked {
width: 200px;
height: 200px;
}
.button {
width: 250px;
margin: 30px 0;
height: 75px;
}
.container__section__form {
width: 100%;
height: 600px;
}
.textarea {
font-size: 2rem;
}
.input {
width: 90%;
height: 75px;

@ -0,0 +1,26 @@
.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;
}

@ -84,12 +84,10 @@ time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
margin: 0;
padding: 0;
border: 0;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article,
@ -103,27 +101,27 @@ hgroup,
menu,
nav,
section {
display: block;
display: block;
}
body {
line-height: 1;
line-height: 1;
}
ol,
ul {
list-style: none;
list-style: none;
}
blockquote,
q {
quotes: none;
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: "";
content: none;
content: "";
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
border-collapse: collapse;
border-spacing: 0;
}

@ -3,7 +3,7 @@
"jsx": "react",
"module": "commonjs",
"moduleResolution": "node",
"noImplicitAny": true,
"noImplicitAny": false,
"noImplicitThis": true,
"strictNullChecks": true,
"target": "ES6",

Loading…
Cancel
Save