"use client"; /* Report damage. Two jobs on one screen: tell the linen room, and start the replacement. * * The two are deliberately separate acts. Reporting damage does not issue anything and does not * silently remove the garment — it comes off the record when it is handed in at the counter. A * screen that wrote off a garment on somebody's say-so would be a screen the linen room stops * trusting, and a screen that quietly issued a replacement would route around the manager. * * `Contaminated` is not in the list. Clinically it is a different pathway — red bag, no return to * the counter — and telling someone to carry a contaminated garment to the linen room would be * worse than saying nothing. Wards use the route they already have. */ import { useState } from "react"; import { MBar, MBody, MChipRow, MError, MRule, MSwitchRow, MTop } from "@/components/m"; import { DarkCard, N600, N700, NumberedField, OptionList } from "@/components/staffui"; import Sent from "@/components/screens/Sent"; import { useStaff } from "@/lib/staffclient"; import { DAMAGE_KINDS } from "@/lib/staffreq"; type Holding = { issueId: string; itemId: string; item: string; size: string; si: number; qty: number; labelId: string; issued: string; replacement: string; }; export default function DamageScreen({ holdings, managerName, notifyWays }: { holdings: Holding[]; managerName: string; notifyWays: { email: boolean; push: boolean }; }) { const { mutate, busy } = useStaff(); const [issueId, setIssueId] = useState(null); const [kind, setKind] = useState(null); const [note, setNote] = useState(""); /* The switch defaults on, because asking for a replacement is what almost everybody reporting a * torn tunic actually wants — but only when there is somebody to ask. With no manager recorded * the request half cannot be raised at all, so defaulting it on left people tapping "Report and * request" and getting an error they could do nothing about. */ const canRequest = !!managerName; const [replace, setReplace] = useState(canRequest); const [err, setErr] = useState(""); /* The server's sentence for a report it saved without a replacement behind it — almost always a * garment whose range has been withdrawn, which cannot be ordered but is still on somebody's * back. Nothing failed, so it is not an error; but the screen used to go straight to the kit * list on a plain success and the nurse walked away expecting a replacement nobody had ordered. */ const [noReplacement, setNoReplacement] = useState(""); /* Where a finished report lands. A replacement was raised, so this is the request screen's own * Sent — same approver, same "what happens next" — or, with no replacement asked for, the same * screen saying the one thing that is still true: it comes off the record at the counter. */ const [done, setDone] = useState<{ what: string; order: { id: string; code: string; manager: string; notified: boolean } | null } | null>(null); const held = holdings.find((h) => h.issueId === issueId) || null; const ready = !!held && !!kind; if (noReplacement) { return ( <>
); } if (done) { const o = done.order; const who = o?.manager || managerName || "your manager"; return o ? ( ) : ( ); } return ( <> {holdings.length === 0 ? (

Nothing on your record to report.

) : ( { setIssueId(k); setErr(""); }} options={holdings.map((h) => ({ key: h.issueId, label: `${h.item} — ${h.size}`, // The label id is what the linen room reads off the garment in their hand, so a // row here can be matched to a physical thing. meta: `${h.labelId} · issued ${h.issued}`, }))} /> )}
{/* Both steps stay on screen from the start, as the mockup draws them. Revealing "what happened" only after a garment is chosen hid half the job from somebody deciding whether this screen was the one they wanted. */} { setKind(k); setErr(""); }} options={DAMAGE_KINDS.map((d) => ({ value: d, label: d }))} />