diff --git a/Website/src/app/add_track/page.tsx b/Website/src/app/add_track/page.tsx index b96536c0..2fd62868 100644 --- a/Website/src/app/add_track/page.tsx +++ b/Website/src/app/add_track/page.tsx @@ -1,7 +1,7 @@ 'use client' import {FormEvent, useRef} from "react"; -import {TrackPath} from "@/lib/api.website"; +import {TrackPath} from "@/utils/api.website"; export default function Home(x: any) { const formRef = useRef(null as (null | HTMLFormElement)) diff --git a/Website/src/app/components/base_layout.tsx b/Website/src/app/components/base_layout.tsx new file mode 100644 index 00000000..16620f41 --- /dev/null +++ b/Website/src/app/components/base_layout.tsx @@ -0,0 +1,32 @@ +import './globals.css' +import Header from "@/app/components/header"; +import Footer from "@/app/components/footer"; + +/** + * The general layout for this site to be used both for pages + * using the app-router and the legacy pages-router. + * + * This will ensure that each page has a header and a footer. + * + * Because this is a flex-layout, children can use the `grow` + * class to grow to take up the remaining space on the page. + * + * @param children The actual page this layout should wrap. In JSX, these are the + * children of this element. + * @constructor + */ +export default function BaseLayout({ + children, + }: { + children: React.ReactNode + }) { + return ( + // inline styling using tailwind will keep styling information in the same + // file as the markup information. +
+
+ {children} +
+ ) + } \ No newline at end of file diff --git a/Website/src/app/components/dynlist.tsx b/Website/src/app/components/dynlist.tsx new file mode 100644 index 00000000..79345291 --- /dev/null +++ b/Website/src/app/components/dynlist.tsx @@ -0,0 +1,91 @@ +"use client"; + +import {IMapRefreshConfig, RevalidateError} from "@/utils/types"; +import {Vehicle} from "@/utils/api.website"; +import useSWR from "swr"; +import {batteryLevelFormatter, coordinateFormatter} from "@/utils/helpers"; +import Link from "next/link"; + +var i = 0 +const fetcher = ([url, track_id]: [url: string, track_id: number]) => { + return fetch(url, {method: 'post', body: JSON.stringify({track_id})}).then( + async (res: Response) => { + if (!res.ok) { + // console.log('not ok!'); + throw new RevalidateError('Re-Fetching unsuccessful', res.status); + } + //console.log('ok') + return res; + } + ).then(res => res.json()) + .then(res => { + // console.log(res); + const test_vehicle: Vehicle = { + id: 0, + pos: { + lat: 54.17 + 0.05 * Math.cos(i * Math.PI / 180), + lng: 10.56 + 0.085 * Math.sin(i * Math.PI / 180) + }, + heading: (i + 90) % 360, + name: 'foo', + batteryLevel: 0.5 + }; + // {id: 42, pos: {lat: 54.2 + 0.05 * Math.cos((i.current + 180) * Math.PI / 180), lng: 10.56 + 0.085 * Math.sin((i.current + 180) * Math.PI / 180) }, heading: i.current - 90, name: 'bar', batteryLevel: 1} + // ]; + i += 5.1; + return res.concat([test_vehicle]) + }); +}; + +export default function DynamicList(props: IMapRefreshConfig) { + + const {server_vehicles, track_id, logged_in} = props; + + const {data, error, isLoading} = useSWR((logged_in && track_id) ? ['/webapi/update', track_id] : null, fetcher, { + refreshInterval: 1000, + }) + + // console.log(data, error, isLoading); + + const vehicles: Vehicle[] = (isLoading || error || !logged_in || !track_id) ? server_vehicles : data; + const sorted_vehicles = vehicles.sort((a, b) => a.id - b.id); + + if (logged_in && error) { + if (error instanceof RevalidateError && error.statusCode == 401) { + console.log('Invalid token'); + window.location.reload(); + } + console.log("revalidate error", error) + } + + return ( + <> +

{`Fahrzeuge der Strecke ${undefined}`}

+ + + + + + + + + + + + + {sorted_vehicles.map((v) => ( + + + + + + + + + ))} + +
Namegeog. Breitegeog. LängeRichtungBatterieladungAuf Karte anzeigen
{v.name}{coordinateFormatter.format(v.pos.lat)} N{coordinateFormatter.format(v.pos.lng)} E{v.heading ? coordinateFormatter.format(v.heading) : 'unbekannt'}{batteryLevelFormatter.format(v.batteryLevel)}Link
+ + ) + +} \ No newline at end of file diff --git a/Website/src/components/dynmap.tsx b/Website/src/app/components/dynmap.tsx similarity index 92% rename from Website/src/components/dynmap.tsx rename to Website/src/app/components/dynmap.tsx index f11d9f0d..2d475078 100644 --- a/Website/src/components/dynmap.tsx +++ b/Website/src/app/components/dynmap.tsx @@ -1,11 +1,11 @@ "use client"; import dynamic from 'next/dynamic'; import LoadMapScreen from './loadmap'; -import {Vehicle} from "@/lib/api.website"; -import {IMapRefreshConfig, RevalidateError} from '@/lib/types'; +import {Vehicle} from "@/utils/api.website"; +import {IMapRefreshConfig, RevalidateError} from '@/utils/types'; import useSWR from "swr"; -const _internal_DynamicMap = dynamic(() => import('@/components/map'), { +const _internal_DynamicMap = dynamic(() => import('@/app/components/map'), { loading: LoadMapScreen, ssr: false }); diff --git a/Website/src/app/components/form.tsx b/Website/src/app/components/form.tsx new file mode 100644 index 00000000..a977975c --- /dev/null +++ b/Website/src/app/components/form.tsx @@ -0,0 +1,21 @@ +import React from "react"; + +/** + * A component that wraps any Form, giving them a consistent appearance. + * + * @param children The actual page this layout should wrap. In JSX, these are the + * children of this element. + * @constructor + */ +export function FormWrapper({children}: { children: React.ReactNode }) { + return ( +
+
+ {children} +
+
+ ) +} + +// TODO: create a component for a form in a dialog to replace/refactor +// the LoginDialog and SelectionDialog components. \ No newline at end of file diff --git a/Website/src/components/globals.css b/Website/src/app/components/globals.css similarity index 100% rename from Website/src/components/globals.css rename to Website/src/app/components/globals.css diff --git a/Website/src/components/loadmap.tsx b/Website/src/app/components/loadmap.tsx similarity index 100% rename from Website/src/components/loadmap.tsx rename to Website/src/app/components/loadmap.tsx diff --git a/Website/src/components/login.tsx b/Website/src/app/components/login.tsx similarity index 76% rename from Website/src/components/login.tsx rename to Website/src/app/components/login.tsx index e5a1200b..ef1e3711 100644 --- a/Website/src/components/login.tsx +++ b/Website/src/app/components/login.tsx @@ -10,14 +10,14 @@ type Url = string | UrlObject; export default function Login({dst_url, signup}: {dst_url?: Url, signup?: boolean}) { const pathname = usePathname() || '/'; return ( -
+ - + - + {signup && } - +
) } @@ -33,7 +33,7 @@ export function LoginDialog({dst_url, login_callback, children}: React.PropsWith return ( { event.preventDefault(); - }} className="drop-shadow-xl shadow-black backdrop:bg-gray-200/30 backdrop:backdrop-blur" > + }} className="drop-shadow-xl shadow-black bg-white dark:bg-slate-800 p-4 rounded max-w-2xl w-full dark:text-white backdrop:bg-gray-200/30 backdrop:backdrop-blur" > {children}