Files
kita-planer/src/app/alert/[token]/page.tsx
T

115 lines
4.8 KiB
TypeScript

import { notFound } from "next/navigation";
import { BellRing, CheckCircle2 } from "lucide-react";
import { getPublicAlarm } from "@/lib/alarms/service";
import {
alarmLabel,
dateKey,
durationLabel,
instantLabel,
} from "@/lib/alarms/format";
import { AlertConfirmForm } from "./alert-confirm-form";
export const metadata = {
title: "Notdienstalarm · Kita-Planer",
robots: { index: false, follow: false },
referrer: "no-referrer" as const,
};
export const dynamic = "force-dynamic";
export default async function AlertPage({
params,
}: {
params: Promise<{ token: string }>;
}) {
const { token } = await params;
const alarm = await getPublicAlarm(token);
if (!alarm) notFound();
const now = new Date(),
expired = alarm.expiresAt <= now;
const canRespond = alarm.status === "PENDING" && !expired;
const overdue = alarm.deadline <= now;
return (
<main className="flex min-h-screen items-center justify-center bg-[var(--bg)] px-5 py-12">
<section className="w-full max-w-xl overflow-hidden rounded-2xl border border-[var(--hairline)] bg-[var(--surface)] shadow-sm">
<header
className={`border-b border-[var(--hairline)] p-6 sm:p-8 ${alarm.status === "CONFIRMED" ? "bg-[var(--accent-soft)]" : "bg-[var(--surface-2)]"}`}
>
<p className="text-xs font-semibold uppercase tracking-widest text-[var(--accent-deep)]">
Kita-Planer · {alarm.kitaName}
</p>
{alarm.status === "CONFIRMED" ? (
<CheckCircle2 className="mt-6 h-7 w-7 text-[var(--accent-deep)]" />
) : (
<BellRing className="mt-6 h-7 w-7 text-[var(--danger)]" />
)}
<h1 className="mt-3 text-3xl text-[var(--ink)]">
{alarm.status === "PENDING"
? "Könnt ihr den Notdienst übernehmen?"
: alarmLabel(alarm)}
</h1>
<p className="mt-3 text-sm leading-6 text-[var(--ink-soft)]">
Hallo {alarm.firstName}, diese Rückmeldung gilt für euren gesamten
Haushalt.
</p>
</header>
<div className="grid gap-6 p-6 sm:p-8">
<dl className="grid grid-cols-2 gap-5 text-sm">
<div>
<dt className="text-[var(--ink-muted)]">Datum</dt>
<dd className="mt-1 font-semibold">
{dateKey(alarm.date).split("-").reverse().join(".")}
</dd>
</div>
<div>
<dt className="text-[var(--ink-muted)]">Einsatz</dt>
<dd className="mt-1 font-semibold">{durationLabel(alarm)}</dd>
</div>
<div>
<dt className="text-[var(--ink-muted)]">Haushalt</dt>
<dd className="mt-1 font-semibold">{alarm.familyName}</dd>
</div>
<div>
<dt className="text-[var(--ink-muted)]">Antwortfrist</dt>
<dd className="mt-1 font-semibold">
{instantLabel(alarm.deadline)} Uhr
</dd>
</div>
</dl>
{canRespond ? (
<>
{overdue && (
<p className="rounded-lg bg-[var(--surface-2)] p-4 text-sm leading-6">
Die Antwortfrist ist abgelaufen. Ihr könnt noch antworten.
Eine verspätete Zusage muss die Koordination freigeben, da
möglicherweise bereits Ersatz organisiert wird.
</p>
)}
<AlertConfirmForm token={token} />
</>
) : (
<div
role="status"
className="rounded-xl border border-[var(--hairline)] p-4 text-sm leading-6"
>
{alarm.status === "CANCELLED"
? "Der Einsatz wurde storniert. Ihr müsst für diesen Alarm nicht einspringen."
: alarm.status === "CONFIRMED"
? "Euer Haushalt hat zugesagt. Die Kita rechnet mit euch. Bei einer Änderung kontaktiert bitte die Koordination."
: alarm.status === "LATE_CONFIRMATION"
? "Eure verspätete Zusage ist gespeichert. Wartet bitte auf die Freigabe durch die Koordination."
: alarm.status === "DECLINED"
? "Die Absage eures Haushalts ist gespeichert. Die Koordination kümmert sich um Ersatz."
: alarm.status === "REVIEW_REQUIRED"
? "Die bisherigen Rückmeldungen müssen von der Koordination geprüft werden. Bitte kontaktiert die Kita."
: "Der Einsatz ist beendet. Dieser Rückmeldelink ist abgelaufen."}
</div>
)}
<p className="text-xs leading-5 text-[var(--ink-muted)]">
Den persönlichen Link bitte innerhalb eures Haushalts behalten.
Änderungen einer gespeicherten Antwort klärt ihr mit der Kita.
</p>
</div>
</section>
</main>
);
}