"use client"; /* The catalogue on the phone. * * This used to be one of the rows under "On the desktop" — listed, greyed out, untappable, with * the note that adding garments is a sit-down job. It genuinely is, for a bulk import of two * hundred lines. It is not for the thing that actually happens in a linen room: a new garment * turns up at the counter and needs to exist before it can be scanned in. * * So this is the whole catalogue, not just what's on the shelf — /m/stock deliberately shows only * variants with history, which means a garment created five minutes ago wouldn't appear there. */ import Link from "next/link"; import { useMemo, useState } from "react"; import { useDerived, useSnap } from "@/lib/client"; import { label, type Item } from "@/lib/compute"; import { INK, IconPlus, MBody, MEmpty, MNav, MNote, MRow, MRule, MSection, MTop, inputStyle } from "@/components/m"; export default function MCatalogue() { const { s, isAdmin } = useSnap(); const { byId } = useDerived(); const [q, setQ] = useState(""); const [showArchived, setShowArchived] = useState(false); const rows = useMemo(() => { const needle = q.trim().toLowerCase(); return s.catalog .filter((i: Item) => (showArchived ? i.archived : !i.archived)) .map((i: Item) => ({ ...i, name: label(byId[i.id] ?? i), sub: [i.sizes.length ? `${i.sizes.length} size${i.sizes.length === 1 ? "" : "s"}` : "No sizes yet", i.supplier || "No supplier", i.sku].filter(Boolean).join(" · "), })) .filter((i) => !needle || `${i.name} ${i.sku} ${i.supplier} ${i.type} ${i.group}`.toLowerCase().includes(needle)) .sort((a, b) => a.name.localeCompare(b.name)); }, [s.catalog, byId, q, showArchived]); const archivedCount = s.catalog.filter((i: Item) => i.archived).length; const addLink: React.CSSProperties = { display: "flex", alignItems: "center", gap: 12, minHeight: 64, padding: "0 20px", border: "2px solid " + INK, color: INK, textDecoration: "none", fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: 14, letterSpacing: "0.08em", textTransform: "uppercase", }; return ( <>
setQ(e.target.value)} placeholder="Garment, code, supplier" aria-label="Filter the catalogue" style={inputStyle} />
{isAdmin && (
New garment
)} {rows.length === 0 ? : rows.slice(0, 300).map((i) => ( {i.cost ? `$${i.cost.toFixed(2)}` : ""}} /> ))} {archivedCount > 0 && (
)} {!isAdmin && Only an admin can change the catalogue. You can still see what exists.}
); }