From 128ee97525651eb2d7929b85a225816e686af592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=A4ckelmann?= <6890706+n1kPLV@users.noreply.github.com> Date: Tue, 19 Sep 2023 23:36:54 +0200 Subject: [PATCH] Added smart-ish links to the header --- Website/src/app/components/dynlist.tsx | 14 ++++--- Website/src/app/components/dynmap.tsx | 5 +++ .../src/app/components/dynmap_with_list.tsx | 2 +- Website/src/app/components/form.tsx | 16 ++++---- Website/src/app/components/layout/header.tsx | 17 +++++--- .../components/layout/smart_navigation.tsx | 39 +++++++++++++++++++ .../src/app/components/selectTrackButton.tsx | 14 +++++++ .../src/app/components/track_selection.tsx | 32 +++++++++++---- Website/src/app/components/tracker.tsx | 8 ++-- Website/src/app/list/page.tsx | 2 +- Website/src/app/management/layout.tsx | 20 +++++++++- Website/src/utils/helpers.ts | 10 +++-- 12 files changed, 141 insertions(+), 38 deletions(-) create mode 100644 Website/src/app/components/layout/smart_navigation.tsx create mode 100644 Website/src/app/components/selectTrackButton.tsx diff --git a/Website/src/app/components/dynlist.tsx b/Website/src/app/components/dynlist.tsx index c41a2ec0..d7d21139 100644 --- a/Website/src/app/components/dynlist.tsx +++ b/Website/src/app/components/dynlist.tsx @@ -9,6 +9,7 @@ import TrackerCharge from "@/app/components/tracker"; import { FunctionComponent } from "react"; import { getFetcher } from "@/utils/fetcher"; import { useRouter } from "next/navigation"; +import { SelectTrackButton } from "@/app/components/selectTrackButton"; /** * A component to focus a vehicle. A link to the map view with the respective search parameter @@ -77,7 +78,7 @@ export function VehicleList({ )} -
+
{v.trackerIds.map(trackerId => ( ))} @@ -127,7 +128,7 @@ export default function DynamicList({ const sorted_vehicles = vehicles?.sort((a, b) => a.id - b.id); // obtain the NextJS router - const router = useRouter() + const router = useRouter(); if (logged_in && error) { if (error instanceof UnauthorizedError || (error instanceof RevalidateError && error.statusCode === 401)) { @@ -139,9 +140,12 @@ export default function DynamicList({ return ( <> -

- Fahrzeuge der Strecke {track_data?.start} - {track_data?.end} -

+
+

+ Fahrzeuge der Strecke {track_data?.start} - {track_data?.end} +

+ +
); diff --git a/Website/src/app/components/dynmap.tsx b/Website/src/app/components/dynmap.tsx index b403f645..3386b58f 100644 --- a/Website/src/app/components/dynmap.tsx +++ b/Website/src/app/components/dynmap.tsx @@ -6,6 +6,7 @@ import useSWR from "swr"; import { useRouter } from "next/navigation"; import { useState } from "react"; import { getFetcher } from "@/utils/fetcher"; +import { SelectTrackButton } from "@/app/components/selectTrackButton"; // This complicated thing with `dynamic` is necessary to disable server side rendering // for the actual map, which does not work with leaflet. @@ -76,6 +77,10 @@ export default function DynamicMap({ setFocus }} /> + {/* This will stack over the map, if all map layers have a z-index < 1100 (which should be the default) */} +
+ +
); } diff --git a/Website/src/app/components/dynmap_with_list.tsx b/Website/src/app/components/dynmap_with_list.tsx index 07118955..8ce6c848 100644 --- a/Website/src/app/components/dynmap_with_list.tsx +++ b/Website/src/app/components/dynmap_with_list.tsx @@ -84,7 +84,7 @@ export default function DynamicMapList({ }} />
-
+
-
- {children} -
- - ) +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 +// the LoginDialog and SelectionDialog components. diff --git a/Website/src/app/components/layout/header.tsx b/Website/src/app/components/layout/header.tsx index babaec65..3b55a5ef 100644 --- a/Website/src/app/components/layout/header.tsx +++ b/Website/src/app/components/layout/header.tsx @@ -1,5 +1,6 @@ import Link from "next/link"; import { CurrentUser } from "@/app/components/layout/currentUser"; +import SmartNavigation from "@/app/components/layout/smart_navigation"; /** * The header for the web page @@ -8,18 +9,22 @@ export default function Header() { return (
RailTrail Verwaltung
- + {/* Force a line break for small devices */} -
+
-
Foo
-
Bar
-
Baz
+ Karte + Liste + + + Datenverwaltung
); } diff --git a/Website/src/app/components/layout/smart_navigation.tsx b/Website/src/app/components/layout/smart_navigation.tsx new file mode 100644 index 00000000..7b287e57 --- /dev/null +++ b/Website/src/app/components/layout/smart_navigation.tsx @@ -0,0 +1,39 @@ +"use client"; + +import Link, { LinkProps } from "next/link"; +import { usePathname } from "next/navigation"; +import { PropsWithChildren } from "react"; + +/** + * A navigation link that has a different style when the user is on the page it links to, or on a sub-page + * @param href The URL to navigate to + * @param className CSS classes for the enclosing div + * @param activeClassName Additional CSS classes for the enclosing div, when active + * @param linkClassName The CSS classes for the anchor tag + * @param children The contents in the anchor tag + * @param props Other options applicable to + * @constructor + */ +export default function SmartNavigation({ + href, + className = "px-2 border-2 border-transparent", + linkClassName, + children, + ...props +}: PropsWithChildren) { + // get the path of the currently open page + const currentPath = usePathname(); + + // and determine if we are currently on that path + const active = (currentPath === href || currentPath?.startsWith(href + "/")) ?? false; + + const activeClassName = "bg-neutral-500/20 !border-gray-500 rounded"; + + return ( +
+ + {children} + +
+ ); +} diff --git a/Website/src/app/components/selectTrackButton.tsx b/Website/src/app/components/selectTrackButton.tsx new file mode 100644 index 00000000..0e2e5b48 --- /dev/null +++ b/Website/src/app/components/selectTrackButton.tsx @@ -0,0 +1,14 @@ +import Link from "next/link"; + +/** + * A link that somewhat resembles a button to select a different track. + */ +export function SelectTrackButton() { + return ( + + Andere Strecke wählen + + ); +} diff --git a/Website/src/app/components/track_selection.tsx b/Website/src/app/components/track_selection.tsx index dc9b60cd..12e8c6a4 100644 --- a/Website/src/app/components/track_selection.tsx +++ b/Website/src/app/components/track_selection.tsx @@ -1,10 +1,8 @@ -"use client"; - import { Dispatch, FormEventHandler, PropsWithChildren, useEffect, useRef, useState } from "react"; import Footer from "@/app/components/layout/footer"; import useSWR from "swr"; -import { setCookie } from "cookies-next"; +import { getCookie, setCookie } from "cookies-next"; import { inter } from "@/utils/common"; import { getFetcher } from "@/utils/fetcher"; import { useRouter } from "next/navigation"; @@ -24,6 +22,7 @@ export default function Selection({ const { data, error, isLoading } = useSWR("/webapi/tracks/list", getFetcher<"/webapi/tracks/list">); // get the next page router const router = useRouter(); + const selectedTrack = getCookie("track_id")?.toString(); const selectTrack: FormEventHandler = e => { e.preventDefault(); @@ -41,7 +40,7 @@ export default function Selection({ }; return ( -
+ {isLoading ? (
@@ -52,14 +51,18 @@ export default function Selection({ ) : completed ? (
-
Wird gepeichert...
+
Wird gespeichert...
) : ( <> - {data?.map(({ id, start, end }) => (