"use client"; /* Approving or declining straight from the email, on whatever device opened it. * * This is the centred page shell rather than the phone column: a manager reaches it from a mail * client, as often on a desktop as on a ward phone, and dropping them into an app chrome they * never signed into would be a strange thing to meet. * * Nothing has happened when this page loads. That is the point of the design: the link renders, * the button decides. */ import { useState } from "react"; import { Err, MyShell, h1, kicker, lead, primary } from "@/components/my"; import { DECLINE_REASONS } from "@/lib/staffreq"; import type { ReqLine } from "@/lib/staffdata"; type Data = { code: string; subjectName: string; subjectMeta: string; /** The whole ask, in the order it was entered. */ lines: ReqLine[]; /** linesSummary() — the one-liner every other screen leads with. */ summary: string; reason: string; note: string; raisedByName: string; facility: string; }; const INK = "#201e1d"; const N600 = "var(--color-neutral-600)"; const N700 = "var(--color-neutral-700)"; const ACCENT_700 = "var(--color-accent-700)"; /** The garments, one row each. Deliberately drawn here rather than borrowed from the staff app's * own list: this page is the centred desktop shell, not the phone column, and its type sizes and * rules are a size up from everything in components/staffui. What it must match is the *content* — * the same order, the same strike-through on a refusal, the same reason against it. */ function Lines({ lines }: { lines: readonly ReqLine[] }) { return (
{/* "Has been told" only when an email actually left — a wearer with no account or a site with no mail hears nothing from this, and saying otherwise is how they wait a fortnight. */} {done.approved ? `${done.notified ? `${data.subjectName.split(" ")[0]} has been told, and` : `${data.subjectName.split(" ")[0]} hasn’t been emailed — it’s on their record in the app — and`} ${data.lines.length > 1 ? "all of it is" : "it’s"} with the linen room now.` : `${done.notified ? `${data.subjectName.split(" ")[0]} has been told` : `${data.subjectName.split(" ")[0]} hasn’t been emailed, so mention it to them`} — ${(done.reason || "").toLowerCase()}.`}
You can close this. Nothing else is waiting on you here.
{status === "declined" ? `This request was declined${declineReason ? ` — ${declineReason.toLowerCase()}` : ""}.` : "This request has already been approved and is with the linen room."}
{/* Which garments went and which didn't. A manager coming back to a request they settled on their phone deserves the same answer here as the wearer gets on their order — the alternative is a page that says "approved" over an ask where a third of it was refused. */}Approval links work once. Open the app if you need to look at it again.
{data.subjectMeta}
}{data.note}
} {data.raisedByName && (Raised for them by {data.raisedByName}.
)}{data.lines.length > 1 ? `This turns down all ${data.lines.length} garments. ${data.subjectName.split(" ")[0]} is told which reason you picked.` : `${data.subjectName.split(" ")[0]} is told which one you picked.`}
Nothing has been decided yet — this page just shows you the request. The link works once, and it settles {data.lines.length > 1 ? "the whole request" : "it"} one way or the other. {data.lines.length > 1 && " To approve some garments and not others, open the app."}