ThreadCount Community edition

Uniform stock management for healthcare linen rooms. Licensed under the GNU AGPL v3.
This commit is contained in:
ThreadCount
2026-09-13 08:45:19 +10:00
commit 1bc2de655a
505 changed files with 56223 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
import Link from "next/link";
import { Band, CtaBand, SPLIT_PAD, SiteNav, body, h2, h3, kicker, small, wrap } from "@/components/site";
export const metadata = {
title: "Reporting",
description: "Cost centre spend, a journal laid out for upload, valuation, shrinkage, exceptions and supplier spend — each prints or exports as CSV.",
alternates: { canonical: "/reporting" },
};
// One entry per tab on the Reports screen, in the order they appear there. The month-end pack is
// not one of them — it is a button that gathers six of these into one printed document — so it is
// named under the list rather than counted as a tab.
const REPORTS = [
["01", "Cost centre spend", "What each department wore, at unit cost, for any month."],
["02", "Journal export", "One debit per cost centre, formatted for upload."],
["03", "Top stock", "The fifteen most-issued garments of the month, each with its share and its year-to-date count."],
["04", "Stock valuation", "On-hand value by garment, at unit cost, dated."],
["05", "Shrinkage", "Every stocktake this financial year, and what each one cost or found."],
["06", "Exceptions", "Anyone over their operational limit, or over the monthly threshold you set."],
["07", "Supplier spend", "Orders placed, what they came to, and the invoice numbers against them."],
["08", "Approvals", "Manager approvals still outstanding: sets approved, collected and remaining."],
["09", "Pre-loved", "Free reissues and what they saved, hand-ins, and what is in the pool."],
];
const TABLE: [string, string, string, string][] = [
["Willow Ward · RGH-3010", "14", "$412.60", "+$96"],
["ICU · RGH-4010", "9", "$268.20", "$31"],
["Operational Support", "11", "$343.75", "+$12"],
];
export default function Reporting() {
return (
<>
<SiteNav current="reporting" />
{/* Split header: type on the ground, a fixed accent column at the right. */}
<section style={{ borderBottom: "2px solid var(--color-text)" }}>
<div style={{ ...wrap, padding: 0, display: "grid", gridTemplateColumns: "1fr 320px" }} className="tcm-split">
<div className={SPLIT_PAD} style={{ paddingTop: "clamp(56px,7vw,88px)", paddingRight: 40, paddingBottom: "clamp(52px,6vw,76px)" }}>
<div style={kicker}>Reporting</div>
<h1 style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "clamp(38px,5.2vw,78px)", lineHeight: 0.98, letterSpacing: "-0.035em", margin: "18px 0 0" }}>When finance asks, it&rsquo;s already done.</h1>
<p style={{ ...body, fontSize: 17, maxWidth: "52ch", margin: "22px 0 0" }}>Every issue lands on the wearer&rsquo;s cost centre at the price you actually paid, so the month-end numbers are already written by the time anyone asks for them.</p>
</div>
<div style={{ background: "var(--color-accent-600)", color: "#fff", padding: "44px 32px", display: "flex", flexDirection: "column", justifyContent: "flex-end" }}>
<div style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: 64, lineHeight: 1 }}>9</div>
<div style={{ ...kicker, color: "#fff", marginTop: 6 }}>Report tabs</div>
<div style={{ width: 60, height: 4, background: "#fff", marginTop: 16 }} />
<div style={{ fontSize: 13.5, lineHeight: 1.6, marginTop: 16 }}>Each one prints or exports as CSV, and six of them gather into the one-click month-end pack.</div>
</div>
</div>
</section>
<Band tone="surface">
<div className="tcm-split" style={{ display: "grid", gridTemplateColumns: "1.15fr 1fr", gap: 56, alignItems: "center" }}>
<div className="table-wrap">
<div style={{ border: "2px solid var(--color-text)", background: "var(--color-bg)", minWidth: 420 }}>
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "10px 16px", borderBottom: "2px solid var(--color-text)" }}>
<b style={{ fontSize: 13 }}>Cost centre report August</b>
<span style={{ display: "flex", gap: 6 }}><span className="tag tag-outline">Print</span><span className="tag tag-accent">CSV</span></span>
</div>
<div style={{ padding: "8px 16px 14px", fontSize: 13 }}>
<div style={{ display: "grid", gridTemplateColumns: "2fr 1fr 1fr 1fr", gap: 10, padding: "6px 0", borderBottom: "2px solid var(--color-text)", ...kicker, color: "var(--color-neutral-700)", fontSize: 10 }}>
<span>Cost centre</span><span style={{ textAlign: "right" }}>Items</span><span style={{ textAlign: "right" }}>Spend</span><span style={{ textAlign: "right" }}>Δ</span>
</div>
{TABLE.map(([cc, n, sp, d]) => (
<div key={cc} style={{ display: "grid", gridTemplateColumns: "2fr 1fr 1fr 1fr", gap: 10, padding: "7px 0", borderBottom: "1px solid var(--color-divider)" }}>
<span>{cc}</span><span style={{ textAlign: "right" }}>{n}</span><span style={{ textAlign: "right" }}><b>{sp}</b></span>
<span style={{ textAlign: "right", color: d.startsWith("+") ? "var(--color-accent-700)" : "var(--color-neutral-700)" }}>{d}</span>
</div>
))}
<div style={{ display: "grid", gridTemplateColumns: "2fr 1fr 1fr 1fr", gap: 10, padding: "8px 0 0", fontWeight: 800 }}>
<span>TOTAL</span><span style={{ textAlign: "right" }}>34</span><span style={{ textAlign: "right" }}>$1,024.55</span><span />
</div>
</div>
<div style={{ padding: "10px 16px", borderTop: "2px solid var(--color-text)", fontSize: 12, color: "var(--color-neutral-700)" }}>Journal: one debit per cost centre, GL 631020, ready for upload</div>
</div>
</div>
<div>
<h2 style={h2}>The journal comes out formatted.</h2>
<p style={{ ...body, marginTop: 18, maxWidth: "44ch" }}>One debit line per cost centre against your GL account, in the layout your finance system expects. No workbook, no pivot table, no retyping.</p>
</div>
</div>
</Band>
<Band>
<div style={kicker}>What you can pull</div>
<div className="tcm-2col" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0 56px", marginTop: 24 }}>
{REPORTS.map(([n, t, b]) => (
<div key={n} style={{ display: "grid", gridTemplateColumns: "44px 1fr", gap: 16, padding: "18px 0", borderBottom: "1px solid var(--color-divider)" }}>
<div style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: 15, color: "var(--color-neutral-600)" }}>{n}</div>
<div>
<div style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: 17 }}>{t}</div>
<div style={{ fontSize: 14.5, lineHeight: 1.6, color: "var(--color-neutral-800)", marginTop: 4 }}>{b}</div>
</div>
</div>
))}
</div>
</Band>
<Band tone="ink">
<h2 style={{ ...h2, color: "#fff" }}>One click at month end.</h2>
<p style={{ fontSize: 16.5, lineHeight: 1.7, color: "var(--color-neutral-200)", maxWidth: "52ch", marginTop: 18 }}>The month-end pack prints one dated document: cost centre spend, the journal, top stock, shrinkage, and anything still outstanding over a summary carrying the month&rsquo;s supplier spend and the value of the stock on the shelf.</p>
<div style={{ display: "flex", gap: 12, marginTop: 28, flexWrap: "wrap" }}>
<Link href="/demo" data-umami-event="open-demo" data-umami-event-placement="reporting" className="btn" style={{ background: "#fff", color: "var(--color-accent-700)", border: "2px solid #fff", fontWeight: 700 }}>See the reports in the demo</Link>
</div>
<div style={{ ...small, color: "var(--color-neutral-300)", marginTop: 14 }}>Nothing is re-priced after the fact, so a report you ran in August still says in December what it said in August.</div>
</Band>
<CtaBand />
</>
);
}