teecup/frontend/components/ny-runde/wizard-shell.tsx

143 lines
5.1 KiB
TypeScript
Raw Permalink Normal View History

"use client"
import Link from "next/link"
import { useRouter } from "next/navigation"
import { Flag } from "lucide-react"
import { WizardProvider, useWizard } from "./wizard-context"
import { ProgressSteps } from "./progress"
import { FooterBar } from "./footer-bar"
import { Step1CourseTime } from "./step1-course-time"
import { Step2Format } from "./step2-format"
import { Step3Players } from "./step3-players"
import { Step4Teams } from "./step4-teams"
import { Step5Sharing } from "./step5-sharing"
function StepBody() {
const { state } = useWizard()
switch (state.step) {
case 1:
return <Step1CourseTime />
case 2:
return <Step2Format />
case 3:
return <Step3Players />
case 4:
return <Step4Teams />
case 5:
return <Step5Sharing />
default:
return null
}
}
function WizardInner() {
const { state, goNext, goBack, canProceedStep1, submit, isAdditionalFlight } = useWizard()
const isStep1Sub = state.step === 1 && state.s1Sub !== "fields"
const isStep1Fields = state.step === 1 && state.s1Sub === "fields"
const isLastStep = state.step === 5
function handleNext() {
if (state.submitting) return
if (isLastStep) {
void submit()
return
}
goNext()
}
const nextDisabled = isStep1Fields ? !canProceedStep1 : false
if (state.loadingMe) {
return (
<div className="flex min-h-dvh items-center justify-center bg-[var(--nr-bg)]">
<div aria-hidden="true" className="h-10 w-10 animate-spin rounded-full border-4 border-[var(--nr-accent-ring)] border-t-[var(--nr-accent)]" />
</div>
)
}
if (!state.ownGender) {
return (
<div className="flex min-h-dvh flex-col items-center justify-center gap-4 bg-[var(--nr-bg)] px-5 text-center">
<p className="max-w-prose text-[15px] text-[var(--nr-ink)]">
Profilen din mangler registrert kjønn, som trengs for å beregne banehandicap riktig.{" "}
<Link href="/account" className="font-semibold text-[var(--nr-accent)] underline underline-offset-2">
til kontoinnstillinger
</Link>
.
</p>
</div>
)
}
return (
<div className="nr flex min-h-dvh flex-col bg-[var(--nr-bg)]">
<header className="sticky top-0 z-10 border-b border-[var(--nr-border)] bg-[var(--nr-surface)]/90 backdrop-blur">
<div className="mx-auto flex max-w-2xl flex-col gap-3 px-4 py-3">
<div className="flex items-center gap-2">
<span className="flex h-7 w-7 items-center justify-center rounded-md bg-[var(--nr-accent)] text-[var(--nr-accent-ink)]">
<Flag className="h-4 w-4" aria-hidden="true" />
</span>
<span className="text-sm font-semibold tracking-tight text-[var(--nr-ink)]">Ny runde</span>
</div>
<ProgressSteps />
</div>
</header>
{isAdditionalFlight ? (
<div className="mx-auto mt-3 w-full max-w-2xl px-4">
<p className="rounded-lg border border-[var(--nr-accent-ring)] bg-[var(--nr-accent-soft)] px-3 py-2 text-[13px] text-[var(--nr-ink)]">
Legger til en ny flight i samme rundegruppe -- dato, starthull, antall hull og spilleform er
forhåndsutfylt fra den første flighten, men kan endres.
</p>
</div>
) : null}
{state.submitError ? (
<div className="mx-auto mt-3 w-full max-w-2xl px-4">
<p role="alert" className="rounded-lg border border-[var(--nr-danger)]/30 bg-[var(--nr-danger-soft)] px-3 py-2 text-[13px] text-[var(--nr-danger)]">
{state.submitError}
</p>
</div>
) : null}
{/* pb-28 er reservert klaring for FooterBar (sticky bottom-0) --
ALDRI en py-/sm:py-klasse her (Tailwind emitterer sm-varianter i
en egen media-blokk etter grunnklassene, en slik klasse ville
slått padding-bottom tilbake ned uansett rekkefølge i selve
className-strengen). Reell, browser-verifisert bug denne runden:
uten denne klaringen overlapper FooterBar innhold nederst
lengre steg (f.eks. "Legg til gjest"-knappen i steg 3), og sluker
klikk stille -- samme feilklasse som er dokumentert i
ARCHITECTURE_DECISIONS.md/CHANGELOG.md fra 2026-08-02. En
pt-klasse er trygt, den påvirker aldri padding-bottom. */}
<main className="mx-auto w-full max-w-2xl flex-1 px-4 pb-28 pt-5">
<StepBody />
</main>
{!isStep1Sub ? (
<FooterBar
onBack={goBack}
onNext={handleNext}
nextDisabled={nextDisabled}
backDisabled={state.submitting}
submitting={state.submitting}
isSubmitStep={isLastStep}
nextLabel={isLastStep ? (state.submitting ? "Oppretter…" : "Start runden") : "Neste"}
/>
) : null}
</div>
)
}
export function NewRoundWizard() {
const router = useRouter()
const exit = () => router.push("/my-rounds")
const created = (roundId: string) => router.replace(`/my-rounds/${roundId}`)
return (
<WizardProvider onExit={exit} onCreated={created}>
<WizardInner />
</WizardProvider>
)
}