From 0d2c5eb2b4434003a511dfc50747828881ad447d Mon Sep 17 00:00:00 2001 From: Kasper Date: Fri, 9 Oct 2026 11:27:39 +0200 Subject: [PATCH 1/2] feat: add map page mockup with search panel and place pins Add a stylized SVG map of Trondheim that can be panned and zoomed, with a pin for each place. Add a left-hand panel with search and a fixed-size detail view with a back arrow. Add hash-based routing, make Utforsk in the main navigation open the map, and add coordinates to Place. --- client/src/App.tsx | 85 +--- client/src/components/HelpButton.tsx | 34 ++ client/src/components/MainNav.tsx | 13 +- client/src/components/MenuButton.tsx | 16 + client/src/components/SiteHeader.tsx | 59 +-- client/src/components/map/MapPanel.tsx | 62 +++ client/src/components/map/MapViewport.tsx | 411 +++++++++++++++++ client/src/components/map/PlaceDetails.tsx | 89 ++++ client/src/components/map/PlacePin.tsx | 63 +++ client/src/components/map/PlaceSearch.tsx | 82 ++++ client/src/components/map/StylizedMap.tsx | 132 ++++++ client/src/data/mockPlaces.ts | 38 +- client/src/hooks/useRoute.ts | 20 + client/src/pages/HomePage.tsx | 84 ++++ client/src/pages/MapPage.css | 485 +++++++++++++++++++++ client/src/pages/MapPage.tsx | 158 +++++++ client/src/types/place.ts | 2 + client/src/utils/mapProjection.ts | 27 ++ 18 files changed, 1727 insertions(+), 133 deletions(-) create mode 100644 client/src/components/HelpButton.tsx create mode 100644 client/src/components/MenuButton.tsx create mode 100644 client/src/components/map/MapPanel.tsx create mode 100644 client/src/components/map/MapViewport.tsx create mode 100644 client/src/components/map/PlaceDetails.tsx create mode 100644 client/src/components/map/PlacePin.tsx create mode 100644 client/src/components/map/PlaceSearch.tsx create mode 100644 client/src/components/map/StylizedMap.tsx create mode 100644 client/src/hooks/useRoute.ts create mode 100644 client/src/pages/HomePage.tsx create mode 100644 client/src/pages/MapPage.css create mode 100644 client/src/pages/MapPage.tsx create mode 100644 client/src/utils/mapProjection.ts diff --git a/client/src/App.tsx b/client/src/App.tsx index 922cfb1..cf31d54 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,87 +1,12 @@ -import { useState } from 'react' import './App.css' -import { FeaturedPlace } from './components/FeaturedPlace' -import { PlaceList } from './components/PlaceList' -import { SiteHeader } from './components/SiteHeader' -import { useNow } from './hooks/useNow' -import { PAGE_SIZE, usePlaces } from './hooks/usePlaces' -import type { Place } from './types/place' +import { useRoute } from './hooks/useRoute' +import { HomePage } from './pages/HomePage' +import { MapPage } from './pages/MapPage' function App() { - const now = useNow() - const { - places, - totalCount, - status, - hasMore, - canShowLess, - loadMore, - showLess, - } = usePlaces() + const route = useRoute() - // Trekkes én gang per sidelasting, slik at det fremhevede stedet er tilfeldig. - const [startFraction] = useState(Math.random) - // Lagrer hele stedet, så det blir stående selv om «Vis mindre» fjerner det - // fra listen. - const [selected, setSelected] = useState(null) - - const featured: Place | undefined = - selected ?? - places[Math.floor(startFraction * Math.min(places.length, PAGE_SIZE))] - - /** Blar til forrige (-1) eller neste (1) sted, og starter om i endene. */ - const step = (direction: -1 | 1) => { - if (!featured) return - const index = places.findIndex((place) => place.id === featured.id) - - // Er stedet skjult av «Vis mindre», starter vi i enden av listen. - const next = - index === -1 - ? direction === 1 - ? 0 - : places.length - 1 - : (index + direction + places.length) % places.length - - setSelected(places[next]) - } - - return ( - <> - -
- {status === 'loading' &&

Laster steder …

} - {status === 'error' && ( -

- Kunne ikke hente steder. Prøv å laste siden på nytt. -

- )} - - {featured && ( - <> - step(-1)} - onNext={() => step(1)} - /> - - - )} -
- - ) + return route === 'map' ? : } export default App diff --git a/client/src/components/HelpButton.tsx b/client/src/components/HelpButton.tsx new file mode 100644 index 0000000..8602e03 --- /dev/null +++ b/client/src/components/HelpButton.tsx @@ -0,0 +1,34 @@ +import type { ReactNode } from 'react' + +type HelpButtonProps = { + id: string + title: string + children: ReactNode +} + +/** «?»-knappen øverst til høyre, som åpner en forklaring i en tekstboble. */ +export function HelpButton({ id, title, children }: HelpButtonProps) { + return ( + <> + + + {/* Åpnes og lukkes av nettleserens innebygde popover-støtte. */} + + + ) +} diff --git a/client/src/components/MainNav.tsx b/client/src/components/MainNav.tsx index 5194486..5db9044 100644 --- a/client/src/components/MainNav.tsx +++ b/client/src/components/MainNav.tsx @@ -20,9 +20,15 @@ function Icon({ children }: { children: ReactNode }) { } /** Foreløpige lenker. «Hjem» er siden vi står på. */ -const links: { label: string; icon: ReactNode; current?: boolean }[] = [ +const links: { + label: string + icon: ReactNode + href?: string + current?: boolean +}[] = [ { label: 'Utforsk', + href: '#/kart', // Kompass icon: ( @@ -44,6 +50,7 @@ const links: { label: string; icon: ReactNode; current?: boolean }[] = [ }, { label: 'Hjem', + href: '#/', current: true, // Anker icon: ( @@ -78,9 +85,9 @@ export function MainNav() { return (