115 lines
4.8 KiB
TypeScript
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>
|
|
);
|
|
}
|