ThreadCount Community edition
Uniform stock management for healthcare linen rooms. Licensed under the GNU AGPL v3.
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import Link from "next/link";
|
||||
import { DEMO_FACILITY, DEMO_RESET_MINUTES } from "@/lib/demo";
|
||||
import { CtaBand, SiteNav } from "@/components/site";
|
||||
import { switches } from "@/lib/switches";
|
||||
|
||||
/* Rendered per request, unlike the rest of the site: the demo switch lives in the database now
|
||||
* and can be flipped from the console, and a page cached for a day would keep offering "Enter as
|
||||
* Admin" long after the entry endpoint had started answering 404. */
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata = {
|
||||
title: "Try the working demo",
|
||||
description: "Open a stocked, fictional hospital linen room and use ThreadCount as an Admin or an Issuer. The same screens run an aged-care home’s store or a clinic’s cupboard. No sign-up.",
|
||||
alternates: { canonical: "/demo" },
|
||||
};
|
||||
|
||||
const CARDS = [
|
||||
{ as: "admin", role: "Admin", who: "Alex Demo · Uniform Coordinator", body: "The coordinator’s view. Settings, the catalogue and prices, the staff register, suppliers, reorder levels, every report and the month-end pack." },
|
||||
{ as: "issuer", role: "Issuer", who: "Sam Demo · Linen Room Assistant", body: "The counter view. Issue stock, record a manager’s approval, run a stocktake, receive a delivery and work through the pickup call list." },
|
||||
];
|
||||
|
||||
export default async function DemoPage({ searchParams }: { searchParams: Promise<{ signedin?: string }> }) {
|
||||
const sp = await searchParams;
|
||||
/* The same switch the entry endpoint honours (app/api/auth/demo/route.ts), read here too.
|
||||
*
|
||||
* With the demo out of service that endpoint answers a bare JSON 404, so a page that still
|
||||
* offers "Enter as Admin" walks somebody weighing the product onto a white screen of raw JSON
|
||||
* with no nav and no way back. Sign-ups are handled the same way — /auth hides the create-account
|
||||
* form when sign-ups are closed rather than letting the button fail — and the demo has to go
|
||||
* quiet at the same moment its endpoint does. */
|
||||
const { demoOpen } = await switches();
|
||||
return (
|
||||
<>
|
||||
<SiteNav />
|
||||
<div style={{ maxWidth: 980, margin: "0 auto", padding: "56px 32px 80px" }}>
|
||||
<div style={{ fontSize: 12, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--color-accent-700)", fontWeight: 700 }}>Working demo</div>
|
||||
<h1 style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "clamp(32px, 4vw, 52px)", letterSpacing: "-0.025em", lineHeight: 1.02, margin: "14px 0 0", textWrap: "balance" as never }}>{demoOpen ? <>Have a look around {DEMO_FACILITY}’s linen room.</> : <>The demo is closed for the moment.</>}</h1>
|
||||
<p style={{ fontSize: 16, lineHeight: 1.6, color: "var(--color-neutral-800)", maxWidth: 620, margin: "18px 0 0" }}>{demoOpen
|
||||
? "It is a made-up hospital, but everything in it is real: a stocked shelf, staff on the register, orders still open with the supplier, people waiting on a pickup, and three months of issues behind it. It could as easily be an aged-care home or a day surgery — the shelf, the counter and the screens are the same. Pick a role and have a look around. Nothing to sign up for."
|
||||
: `${DEMO_FACILITY} is a made-up hospital anyone can walk into, and it has been taken out of service for a while. Nothing is wrong with ThreadCount itself, and a facility of your own is unaffected.`}</p>
|
||||
{sp.signedin === "1" && <div style={{ border: "2px solid var(--color-accent)", padding: "10px 14px", marginTop: 24, fontSize: 13, fontWeight: 600, color: "var(--color-accent-700)" }}>You’re signed in to your own facility. <Link href="/app">Go to your app</Link>, or sign out first to open the demo.</div>}
|
||||
{demoOpen ? <>
|
||||
<div className="tc-grid" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 0, marginTop: 36, border: "2px solid var(--color-text)" }}>
|
||||
{CARDS.map((c, i) => (
|
||||
<div key={c.as} style={{ padding: "28px 28px 32px", borderRight: i === 0 ? "1px solid var(--color-divider)" : undefined, display: "flex", flexDirection: "column" }}>
|
||||
<div style={{ fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--color-neutral-700)", fontWeight: 700 }}>{c.who}</div>
|
||||
<div style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: 26, marginTop: 8, borderTop: "4px solid var(--color-accent)", paddingTop: 10, display: "inline-block", alignSelf: "flex-start" }}>Enter as {c.role}</div>
|
||||
<p style={{ fontSize: 14, lineHeight: 1.65, color: "var(--color-neutral-800)", margin: "10px 0 0", flex: 1 }}>{c.body}</p>
|
||||
<a href={`/api/auth/demo?as=${c.as}`} className={"btn " + (i === 0 ? "btn-primary" : "btn-secondary")} style={{ marginTop: 22, alignSelf: "flex-start" }}>Open the {c.role} view</a>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div style={{ marginTop: 28, border: "2px solid var(--color-text)", padding: "18px 22px", fontSize: 13.5, lineHeight: 1.65, color: "var(--color-neutral-800)" }}>
|
||||
<b style={{ color: "var(--color-text)" }}>How the demo works.</b> Everyone shares the one demo facility, so you might spot someone else’s changes while you are in there. It goes back to the same starting point every {DEMO_RESET_MINUTES} minutes, so feel free to break things. Demo accounts can’t change passwords or users, or wipe the data. Everything else — issuing, ordering, receiving, stocktakes, reports, printing — behaves exactly as it would in your own facility. None of it is real hospital data.
|
||||
</div>
|
||||
</> : (
|
||||
<div style={{ marginTop: 36, border: "2px solid var(--color-text)", padding: "18px 22px", fontSize: 13.5, lineHeight: 1.65, color: "var(--color-neutral-800)" }}>
|
||||
<b style={{ color: "var(--color-text)" }}>There is nothing to open just now.</b> The shared demo facility is off, so the two role buttons that normally sit here would only lead to a closed door. Until it is back, <Link href="/how-it-works" style={{ fontWeight: 700 }}>how it works</Link> walks through the same day at the counter, and <Link href="/features" style={{ fontWeight: 700 }}>the feature list</Link> covers what is in it. If you would rather be shown around, <Link href="/contact" style={{ fontWeight: 700 }}>ask for a look</Link>.
|
||||
</div>
|
||||
)}
|
||||
<div style={{ marginTop: 28, fontSize: 14 }}>Want one of your own? <Link href="/auth?mode=signup" data-umami-event="signup-cta" data-umami-event-placement="demo-page" style={{ fontWeight: 700 }}>Set up your facility</Link> — it takes about a minute, and your catalogue and staff register come in from CSV.</div>
|
||||
</div>
|
||||
<CtaBand />
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user