Opretter en ny, rigtig rute ("Fælles Vinindkøb (test)", id 9,
test.vinindkoeb.dk, afsender "Test - Fælles Vinindkøb"
<test@vinindkoeb.dk>) direkte i databasen, så brugeren kan teste hele
flowet — inkl. rigtig mail-udsendelse via Postal — uden at røre de
308 rigtige deltagere. Mere robust end de midlertidige isolerede
sandboxes brugt til verifikation indtil nu.
Med to ruter under samme organisation kan admin-UI'et ikke længere
antage "der er kun én rute": RouteContext.tsx (samme mønster som
AuthContext) henter ruterne én gang efter login og holder det valgte
rute-id (persisteret i localStorage). Layout.tsx får en rute-vælger i
navbaren (kun vist når der er mere end én rute). ParticipantsPage,
RoundsPage og TemplatesPage havde hver deres egen "GET /routes, brug
routes[0]"-logik — omskrevet til at læse fra useRoute() i stedet, så
de automatisk genindlæser når man skifter rute.
DNS-post og reverse proxy-indgang for test.vinindkoeb.dk skal
stadig sættes op manuelt uden for denne kodebase, samme mønster som
vinindkoeb.dk/admin.vinindkoeb.dk.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'
|
|
import { apiFetch, ApiError } from './api'
|
|
|
|
export interface Route {
|
|
id: number
|
|
name: string
|
|
}
|
|
|
|
const ROUTE_STORAGE_KEY = 'vinindkoeb_admin_route_id'
|
|
|
|
interface RouteState {
|
|
routes: Route[]
|
|
selectedRouteId: number | null
|
|
selectRoute: (id: number) => void
|
|
loading: boolean
|
|
error: string | null
|
|
}
|
|
|
|
const RouteContext = createContext<RouteState | null>(null)
|
|
|
|
export function RouteProvider({ children }: { children: ReactNode }) {
|
|
const [routes, setRoutes] = useState<Route[]>([])
|
|
const [selectedRouteId, setSelectedRouteId] = useState<number | null>(null)
|
|
const [loading, setLoading] = useState(true)
|
|
const [error, setError] = useState<string | null>(null)
|
|
|
|
useEffect(() => {
|
|
apiFetch<Route[]>('/routes')
|
|
.then((data) => {
|
|
setRoutes(data)
|
|
if (data.length === 0) return
|
|
const stored = localStorage.getItem(ROUTE_STORAGE_KEY)
|
|
const storedId = stored ? Number(stored) : null
|
|
const validStoredId = storedId !== null && data.some((r) => r.id === storedId) ? storedId : null
|
|
setSelectedRouteId(validStoredId ?? data[0].id)
|
|
})
|
|
.catch((err) => {
|
|
setError(err instanceof ApiError ? err.message : 'Kunne ikke hente ruter')
|
|
})
|
|
.finally(() => setLoading(false))
|
|
}, [])
|
|
|
|
function selectRoute(id: number) {
|
|
setSelectedRouteId(id)
|
|
localStorage.setItem(ROUTE_STORAGE_KEY, String(id))
|
|
}
|
|
|
|
return (
|
|
<RouteContext.Provider value={{ routes, selectedRouteId, selectRoute, loading, error }}>
|
|
{children}
|
|
</RouteContext.Provider>
|
|
)
|
|
}
|
|
|
|
export function useRoute(): RouteState {
|
|
const context = useContext(RouteContext)
|
|
if (!context) throw new Error('useRoute skal bruges inden i RouteProvider')
|
|
return context
|
|
}
|