Files
threadcount-community/app/(site)/demo/page.tsx
T
ThreadCount 344b1701dd ThreadCount Community edition
Uniform stock management for healthcare linen rooms. Licensed under the GNU AGPL v3.
2026-09-13 08:54:35 +10:00

67 lines
6.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 homes store or a clinics cupboard. No sign-up.",
alternates: { canonical: "/demo" },
};
const CARDS = [
{ as: "admin", role: "Admin", who: "Alex Demo · Uniform Coordinator", body: "The coordinators 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 managers 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}&rsquo;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&rsquo;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&rsquo;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&rsquo;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 />
</>
);
}