Files
threadcount-community/app/app/help/page.tsx
T
ThreadCount 46a1911c1c ThreadCount Community edition
Uniform stock management for healthcare linen rooms: the coordinator app, the phone counter and the staff app, for your own server. Built from 5470a36 on 2026-09-13. Licensed under the Functional Source License (FSL-1.1-ALv2).
2026-09-13 11:35:40 +10:00

117 lines
7.6 KiB
TypeScript

"use client";
/* Help: the rules and routines a coordinator needs to know once, written down in one place so the
* working screens don't have to carry them. The owner took the explanations off every screen and
* asked for anything worth keeping to live here instead.
*
* Every figure is read from this facility's own settings rather than written in, so the page can't
* quote a number the facility has changed. The import rules are the templates' own notes, so they
* can't drift from what the importer accepts. */
import { useSnap } from "@/lib/client";
import { PageHead } from "@/components/ui";
import { CSV_TEMPLATES } from "@/lib/csv";
import { FTE_SETS, SLIP_DAYS } from "@/lib/compute";
import { SET_GARMENTS, setsCap, setsOnStart } from "@/lib/sets";
function Section({ title, children }: { title: string; children: React.ReactNode }) {
return (
<div className="tc-panel" style={{ marginBottom: "var(--space-4)" }}>
<div className="tc-panel-head"><span>{title}</span></div>
<div className="tc-panel-body" style={{ fontSize: 14, lineHeight: 1.6 }}>{children}</div>
</div>
);
}
const list = { margin: 0, paddingLeft: "1.2em", display: "grid", gap: "var(--space-1)" } as const;
export default function Help() {
const { s } = useSnap();
const cap = setsCap(s.settings.capSets);
const start = Math.min(cap, setsOnStart(s.settings.initialSets));
// The table as the form lists it: a full-timer's figure first, down to the smallest.
const table = Object.entries(FTE_SETS).filter(([, n]) => n !== null) as [string, number][];
return (
<>
<PageHead eyebrow="Help" title="How ThreadCount works" sub="The rules behind the screens, with this facility's own figures." />
<Section title="What anyone may hold">
<ul style={list}>
<li>Up to <b>{cap} sets</b> at any time {cap} tops and {cap} pairs of trousers. The same for every staff group, nursing included.</li>
<li>It counts everything issued and not handed in or returned, plus anything on order for them, waiting at the counter, or approved and not yet collected. Pre-loved garments count.</li>
<li>Garments that aren&apos;t part of a set fleeces, jackets, maternity wear have their own ceiling of {cap}.</li>
<li>It isn&apos;t a yearly allowance and nothing resets in July. At the ceiling, the next garment comes by handing one in first, or on a coordinator&apos;s override, which is recorded.</li>
<li>Change the figure under Settings General.</li>
</ul>
</Section>
<Section title="The three routes">
<p style={{ margin: "0 0 var(--space-2)" }}>Each staff group is on one route, chosen under Settings Staff groups. All three stop at the same {cap} sets.</p>
<ul style={list}>
<li><b>FTE table</b> the hours someone works propose their starting kit: {table.map(([fte, n]) => `${fte} FTE ${n}`).join(", ")} sets; a casual is at the manager&apos;s discretion. A manager may sign for more.</li>
<li><b>Starting kit</b> {start} sets on the first day ({start * SET_GARMENTS} garments), then more as needed. Nothing has to be handed back first.</li>
<li><b>Manager approval</b> no starting kit; the manager approves each set.</li>
<li>A group can&apos;t be on two routes, and a group with people in it can&apos;t be removed rename it instead.</li>
</ul>
</Section>
<Section title="The yearly figure">
<p style={{ margin: 0 }}>&ldquo;Items (FY)&rdquo; on Reports and &ldquo;drawn since July&rdquo; on Issue Stock count what someone has drawn since 1 July. They feed the reports and the monthly exceptions list, and never limit what the counter issues. Groups on the FTE table aren&apos;t measured against one.</p>
</Section>
<Section title="Hand-ins">
<ul style={list}>
<li>Handing a garment in frees room at the counter straight away, whether or not the credit box is ticked.</li>
<li>The credit tick adds the good garments back to the yearly figure and to the manager&apos;s approval. Pre-loved garments earn neither.</li>
<li>Good garments join the pre-loved pool and are reissued free; rags are counted for disposal.</li>
</ul>
</Section>
<Section title="Garment types">
<p style={{ margin: 0 }}>A garment&apos;s type decides how it counts. Tops and trousers are each half a set; every other type counts toward the separate ceiling. A type typed in by hand that isn&apos;t on the list counts toward no set, so pick from the list.</p>
<p style={{ margin: "var(--space-2) 0 0" }}>Each garment is tagged for the staff groups that wear it, or for all groups. Staff can only request their own groups&apos; garments, and the counter needs a coordinator&apos;s override, which is recorded, to issue anyone a garment outside their group.</p>
<p style={{ margin: "var(--space-2) 0 0" }}>A garment is also men&apos;s, women&apos;s or unisex. Somebody is offered the cut set as their Uniform style plus everything unisex; blank means every style until a coordinator sets it, and the counter needs the same override, also recorded, to issue anyone another cut.</p>
</Section>
<Section title="The staff app">
<ul style={list}>
<li>Generate a code on the staff record and hand them the slip. A code works once and expires after {SLIP_DAYS} days.</li>
<li>Record their manager first, under Manager&apos;s approval on the staff record nobody can raise a request without one.</li>
</ul>
</Section>
<Section title="Requests and approvals">
<ul style={list}>
<li>A request goes to the person&apos;s manager the same person who signs their paper order form.</li>
<li>A manager can raise requests for the people who report to them; those go to the manager above. With nobody above, the request waits under Ward Requests Needs an approver.</li>
<li>Nobody approves a request they raised for somebody else.</li>
<li>Anyone can be set as their own manager; what they approve for themselves is marked Self-approved.</li>
</ul>
</Section>
<Section title="Stock takes">
<p style={{ margin: 0 }}>A count in progress is saved in this browser only, under your sign-in. It survives a reload, but not a move to another computer or the phone finish a count where you started it.</p>
</Section>
<Section title="Importing and exporting">
<p style={{ margin: "0 0 var(--space-2)" }}>Settings Data imports each list from a CSV file. The rules for each:</p>
<ul style={list}>
{Object.entries(CSV_TEMPLATES).map(([k, t]) => <li key={k}><b>{t.name}</b> {t.note}</li>)}
</ul>
<p style={{ margin: "var(--space-2) 0 0" }}>The Staff Register&apos;s Export writes the same columns, so a ward&apos;s list can go to its manager, come back with Manager number filled in, and be imported again. The Approver name column is only for checking and is ignored on import.</p>
</Section>
<Section title="Month-end journal">
<p style={{ margin: 0 }}>One debit line per cost centre, priced at each garment&apos;s cost on the day it was issued. Finance posts the balancing credit.</p>
</Section>
<Section title="Who ThreadCount emails">
<ul style={list}>
<li>You password resets, and updates you&apos;ve subscribed to.</li>
<li>Staff only about their own requests, once they&apos;ve set up the staff app.</li>
<li>Managers the link to approve or decline a request.</li>
</ul>
</Section>
</>
);
}