vinindkoeb/admin-ui/src/Layout.tsx
carsten 588888cd9e Opgave 11b (del 2): Runder + vinliste
RoundsPage (liste + opret) og RoundDetailPage (/runder/:roundId —
redigér, status-overgange, slet, "kopiér denne runde", nestet
vinliste-CRUD). Ingen backend-ændringer nødvendige, al CRUD fandtes
allerede (opgave 6). 409-fejl fra rundens dato-constraint vises
direkte som API'ets fejlbesked i stedet for at duplikere reglen i
frontend.

To fund fra brugertest, begge rettet:
1. Åbningsdato og bestillingsfrist krævede et tidspunkt
   (datetime-local) uden reelt behov — skiftet til rene datofelter
   (dateUtils.ts). Afhentningstidspunktet beholder klokkeslæt.
2. Kun kladde-runder kunne slettes fra UI'et. Lukkede runder kan nu
   også slettes, når eleveret — samme elevations-mønster som
   deltager-hård-sletning i del 1 (elevatedToken fra AuthContext).
   Åbne runder kan fortsat aldrig slettes (håndhævet server-side).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 01:59:46 +02:00

52 lines
1.6 KiB
TypeScript

import { useState } from 'react'
import { NavLink, Outlet } from 'react-router-dom'
import { ApiError } from './api'
import { useAuth } from './AuthContext'
export function Layout() {
const { currentUser, logout, isElevated, requestElevation } = useAuth()
const [elevationError, setElevationError] = useState<string | null>(null)
async function handleElevate() {
setElevationError(null)
try {
await requestElevation()
} catch (err) {
setElevationError(err instanceof ApiError ? err.message : 'Kunne ikke forhøje rettigheder')
}
}
return (
<div>
<nav className="navbar">
<span className="navbar-brand">Fælles Vinindkøb — Admin</span>
<div className="navbar-links">
<NavLink to="/deltagere">Deltagere</NavLink>
<NavLink to="/runder">Runder</NavLink>
{currentUser?.is_superadmin &&
(isElevated ? (
<span className="elevated-badge" title="Udløber automatisk efter 5 minutter">
Rettigheder forhøjet ✓
</span>
) : (
<button className="link-button" onClick={handleElevate}>
Forhøj rettigheder
</button>
))}
{currentUser && (
<>
<span className="navbar-user">{currentUser.name}</span>
<button className="link-button" onClick={logout}>
Log ud
</button>
</>
)}
</div>
</nav>
{elevationError && <p className="content error">{elevationError}</p>}
<main className="content">
<Outlet />
</main>
</div>
)
}