ui cleanup

This commit is contained in:
2026-03-15 19:58:26 -05:00
parent dcac4f135d
commit e88d949a59
3 changed files with 67 additions and 263 deletions

View File

@@ -189,7 +189,7 @@ export function AppShell() {
return (
<div className="min-h-screen px-4 py-5 xl:px-6 2xl:px-8">
<div className="mx-auto flex w-full max-w-[1760px] gap-3 2xl:gap-4">
<aside className="hidden w-72 shrink-0 flex-col rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel backdrop-blur md:flex 2xl:w-80">
<aside className="hidden w-72 shrink-0 flex-col rounded-[22px] border border-line/70 bg-surface/90 p-4 shadow-panel backdrop-blur md:flex 2xl:w-80">
<div>
<div className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">MRP Codex</div>
<h1 className="mt-2 text-xl font-extrabold text-text">Manufacturing foundation</h1>
@@ -211,29 +211,28 @@ export function AppShell() {
</NavLink>
))}
</nav>
<div className="mt-auto rounded-2xl border border-line/70 bg-page/70 p-4">
<p className="text-sm font-semibold text-text">{user?.firstName} {user?.lastName}</p>
<p className="text-xs text-muted">{user?.email}</p>
<button
type="button"
onClick={() => {
void logout();
}}
className="mt-4 rounded-xl bg-text px-4 py-2 text-sm font-semibold text-page"
>
Sign out
</button>
<div className="mt-auto space-y-3">
<div className="rounded-[18px] border border-line/70 bg-page/70 p-3">
<p className="mb-2 text-xs font-semibold uppercase tracking-[0.18em] text-muted">Theme</p>
<ThemeToggle />
</div>
<div className="rounded-[18px] border border-line/70 bg-page/70 p-4">
<p className="text-sm font-semibold text-text">{user?.firstName} {user?.lastName}</p>
<p className="text-xs text-muted">{user?.email}</p>
<button
type="button"
onClick={() => {
void logout();
}}
className="mt-4 rounded-xl bg-text px-4 py-2 text-sm font-semibold text-page"
>
Sign out
</button>
</div>
</div>
</aside>
<main className="min-w-0 flex-1">
<div className="mb-4 flex items-center justify-between rounded-[28px] border border-line/70 bg-surface/90 px-2 py-2 shadow-panel backdrop-blur 2xl:px-3">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.22em] text-muted">Operations Command</p>
<h2 className="text-lg font-bold text-text">Foundation Console</h2>
</div>
<ThemeToggle />
</div>
<nav className="mb-4 flex gap-3 overflow-x-auto rounded-[24px] border border-line/70 bg-surface/85 p-3 shadow-panel backdrop-blur md:hidden">
<nav className="mb-4 flex gap-3 overflow-x-auto rounded-[20px] border border-line/70 bg-surface/85 p-3 shadow-panel backdrop-blur md:hidden">
{links.map((link) => (
<NavLink
key={link.to}
@@ -249,6 +248,9 @@ export function AppShell() {
</NavLink>
))}
</nav>
<div className="mb-4 md:hidden">
<ThemeToggle />
</div>
<Outlet />
</main>
</div>

View File

@@ -7,10 +7,9 @@ export function ThemeToggle() {
<button
type="button"
onClick={toggleMode}
className="rounded-full border border-line/70 bg-surface px-4 py-2 text-sm font-semibold text-text transition hover:border-brand/60"
className="w-full rounded-xl border border-line/70 bg-page/70 px-3 py-2 text-sm font-semibold text-text transition hover:border-brand/60"
>
{mode === "light" ? "Dark mode" : "Light mode"}
</button>
);
}

View File

@@ -33,19 +33,6 @@ function formatCurrency(value: number) {
}).format(value);
}
function formatDateTime(value: string | null) {
if (!value) {
return "No recent activity";
}
return new Intl.DateTimeFormat("en-US", {
month: "short",
day: "numeric",
hour: "numeric",
minute: "2-digit",
}).format(new Date(value));
}
function sumNumber(values: number[]) {
return values.reduce((total, value) => total + value, 0);
}
@@ -148,17 +135,6 @@ export function DashboardPage() {
const projects = snapshot?.projects ?? [];
const planningRollup = snapshot?.planningRollup;
const accessibleModules = [
snapshot?.customers !== null || snapshot?.vendors !== null,
snapshot?.items !== null || snapshot?.warehouses !== null,
snapshot?.purchaseOrders !== null,
snapshot?.workOrders !== null,
snapshot?.quotes !== null || snapshot?.orders !== null,
snapshot?.shipments !== null,
snapshot?.projects !== null,
canReadPlanning,
].filter(Boolean).length;
const customerCount = customers.length;
const resellerCount = customers.filter((customer) => customer.isReseller).length;
const activeCustomerCount = customers.filter((customer) => customer.lifecycleStage === "ACTIVE").length;
@@ -209,91 +185,45 @@ export function DashboardPage() {
const buildRecommendationCount = planningRollup?.summary.buildRecommendationCount ?? 0;
const totalUncoveredQuantity = planningRollup?.summary.totalUncoveredQuantity ?? 0;
const lastActivityAt = [
...customers.map((customer) => customer.updatedAt),
...vendors.map((vendor) => vendor.updatedAt),
...items.map((item) => item.updatedAt),
...warehouses.map((warehouse) => warehouse.updatedAt),
...purchaseOrders.map((order) => order.updatedAt),
...workOrders.map((workOrder) => workOrder.updatedAt),
...quotes.map((quote) => quote.updatedAt),
...orders.map((order) => order.updatedAt),
...shipments.map((shipment) => shipment.updatedAt),
...projects.map((project) => project.updatedAt),
]
.sort()
.at(-1) ?? null;
const metricCards = [
{
label: "CRM Accounts",
value: snapshot?.customers !== null ? `${customerCount}` : "No access",
detail:
snapshot?.customers !== null
? `${vendorCount} vendors, ${resellerCount} resellers, ${activeCustomerCount} active`
: "CRM metrics are permission-gated.",
tone: "border-emerald-400/30 bg-emerald-500/12 text-emerald-700 dark:text-emerald-300",
},
{
label: "Inventory Footprint",
value: snapshot?.items !== null ? `${itemCount}` : "No access",
detail:
snapshot?.items !== null
? `${assemblyCount} buildable items across ${warehouseCount} warehouses`
: "Inventory metrics are permission-gated.",
tone: "border-sky-400/30 bg-sky-500/12 text-sky-700 dark:text-sky-300",
},
{
label: "Purchasing Queue",
value: snapshot?.purchaseOrders !== null ? `${openPurchaseOrderCount}` : "No access",
detail:
snapshot?.purchaseOrders !== null
? `${issuedPurchaseOrderCount} issued/approved and ${formatCurrency(purchaseOrderValue)} committed`
: "Purchasing metrics are permission-gated.",
tone: "border-teal-400/30 bg-teal-500/12 text-teal-700 dark:text-teal-300",
},
{
label: "Manufacturing Load",
value: snapshot?.workOrders !== null ? `${activeWorkOrderCount}` : "No access",
detail:
snapshot?.workOrders !== null
? `${releasedWorkOrderCount} released and ${overdueWorkOrderCount} overdue`
: "Manufacturing metrics are permission-gated.",
tone: "border-indigo-400/30 bg-indigo-500/12 text-indigo-700 dark:text-indigo-300",
},
{
label: "Commercial Value",
value: snapshot?.quotes !== null || snapshot?.orders !== null ? formatCurrency(quoteValue + orderValue) : "No access",
detail:
snapshot?.quotes !== null || snapshot?.orders !== null
? `${quoteCount} quotes and ${orderCount} orders in the pipeline`
: "Sales metrics are permission-gated.",
tone: "border-amber-400/30 bg-amber-500/12 text-amber-700 dark:text-amber-300",
},
{
label: "Shipping Queue",
value: snapshot?.shipments !== null ? `${activeShipmentCount}` : "No access",
detail:
snapshot?.shipments !== null
? `${inTransitCount} in transit, ${deliveredCount} delivered`
: "Shipping metrics are permission-gated.",
tone: "border-brand/30 bg-brand/10 text-brand",
},
{
label: "Project Load",
value: snapshot?.projects !== null ? `${activeProjectCount}` : "No access",
detail:
snapshot?.projects !== null
? `${atRiskProjectCount} at risk and ${overdueProjectCount} overdue`
: "Project metrics are permission-gated.",
tone: "border-violet-400/30 bg-violet-500/12 text-violet-700 dark:text-violet-300",
},
{
label: "Material Readiness",
value: planningRollup ? `${shortageItemCount}` : "No access",
detail: planningRollup
? `${buildRecommendationCount} build and ${buyRecommendationCount} buy recommendations`
: "Sales read permission is required to surface shortage rollups.",
tone: "border-rose-400/30 bg-rose-500/12 text-rose-700 dark:text-rose-300",
},
];
@@ -301,11 +231,6 @@ export function DashboardPage() {
const modulePanels = [
{
title: "CRM",
eyebrow: "Account Health",
summary:
snapshot?.customers !== null
? "Live account counts, reseller coverage, and strategic-account concentration from the current CRM records."
: "CRM read permission is required to surface customer and vendor metrics here.",
metrics: [
{ label: "Customers", value: snapshot?.customers !== null ? `${customerCount}` : "No access" },
{ label: "Strategic", value: snapshot?.customers !== null ? `${strategicCustomerCount}` : "No access" },
@@ -318,11 +243,6 @@ export function DashboardPage() {
},
{
title: "Inventory",
eyebrow: "Master + Stock",
summary:
snapshot?.items !== null
? "Item master, BOM-capable parts, and warehouse footprint are now feeding the dashboard directly."
: "Inventory read permission is required to surface item and warehouse metrics here.",
metrics: [
{ label: "Active items", value: snapshot?.items !== null ? `${activeItemCount}` : "No access" },
{ label: "Assemblies", value: snapshot?.items !== null ? `${assemblyCount}` : "No access" },
@@ -335,11 +255,6 @@ export function DashboardPage() {
},
{
title: "Purchasing",
eyebrow: "Inbound Supply",
summary:
snapshot?.purchaseOrders !== null
? "Purchase orders, open commitments, and current inbound procurement load are now visible from the dashboard."
: "Purchasing read permission is required to surface procurement metrics here.",
metrics: [
{ label: "Open POs", value: snapshot?.purchaseOrders !== null ? `${openPurchaseOrderCount}` : "No access" },
{ label: "Issued", value: snapshot?.purchaseOrders !== null ? `${issuedPurchaseOrderCount}` : "No access" },
@@ -351,11 +266,6 @@ export function DashboardPage() {
},
{
title: "Manufacturing",
eyebrow: "Execution Load",
summary:
snapshot?.workOrders !== null
? "Work orders, released load, and overdue build pressure are now visible from the dashboard."
: "Manufacturing read permission is required to surface work-order metrics here.",
metrics: [
{ label: "Open work", value: snapshot?.workOrders !== null ? `${activeWorkOrderCount}` : "No access" },
{ label: "Released", value: snapshot?.workOrders !== null ? `${releasedWorkOrderCount}` : "No access" },
@@ -368,11 +278,6 @@ export function DashboardPage() {
},
{
title: "Sales",
eyebrow: "Revenue Flow",
summary:
snapshot?.quotes !== null || snapshot?.orders !== null
? "Quotes and sales orders now contribute real commercial value, open-document counts, and pipeline visibility."
: "Sales read permission is required to surface commercial metrics here.",
metrics: [
{ label: "Quote value", value: snapshot?.quotes !== null ? formatCurrency(quoteValue) : "No access" },
{ label: "Order value", value: snapshot?.orders !== null ? formatCurrency(orderValue) : "No access" },
@@ -385,11 +290,6 @@ export function DashboardPage() {
},
{
title: "Shipping",
eyebrow: "Execution Queue",
summary:
snapshot?.shipments !== null
? "Shipment records, in-transit volume, and completed deliveries are now visible from the landing page."
: "Shipping read permission is required to surface shipment metrics here.",
metrics: [
{ label: "Open shipments", value: snapshot?.shipments !== null ? `${activeShipmentCount}` : "No access" },
{ label: "In transit", value: snapshot?.shipments !== null ? `${inTransitCount}` : "No access" },
@@ -402,11 +302,6 @@ export function DashboardPage() {
},
{
title: "Projects",
eyebrow: "Program Control",
summary:
snapshot?.projects !== null
? "Project records now tie customers, commercial documents, shipment context, and delivery ownership into one operational surface."
: "Project read permission is required to surface program metrics here.",
metrics: [
{ label: "Active", value: snapshot?.projects !== null ? `${activeProjectCount}` : "No access" },
{ label: "At risk", value: snapshot?.projects !== null ? `${atRiskProjectCount}` : "No access" },
@@ -419,10 +314,6 @@ export function DashboardPage() {
},
{
title: "Planning",
eyebrow: "Schedule Visibility",
summary: canReadPlanning
? "Live gantt planning now pulls directly from active projects and open manufacturing work orders, with shared shortage/readiness rollups alongside schedule pressure."
: "Planning read permission is required to surface the live gantt schedule.",
metrics: [
{ label: "At risk projects", value: canReadPlanning ? `${atRiskProjectCount}` : "No access" },
{ label: "Shortage items", value: canReadPlanning && planningRollup ? `${shortageItemCount}` : "No access" },
@@ -432,108 +323,27 @@ export function DashboardPage() {
},
];
const futureModules = [
"Stock transfers, allocations, and cycle counts",
"Revision comparison and document restore tooling",
"Audit trails, diagnostics, and system health checks",
];
return (
<div className="space-y-4">
<section className="overflow-hidden rounded-[30px] border border-line/70 bg-surface/90 shadow-panel backdrop-blur">
<div className="grid gap-0 xl:grid-cols-[1.35fr_0.65fr]">
<div className="relative overflow-hidden p-5 2xl:p-6">
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,_rgba(24,90,219,0.16),_transparent_44%),linear-gradient(135deg,rgba(255,255,255,0.06),transparent)]" />
<div className="relative">
<div className="flex flex-wrap items-center justify-between gap-3">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">Dashboard</p>
<h3 className="mt-2 max-w-3xl text-2xl font-extrabold text-text">Operational command surface for metrics, movement, and next actions.</h3>
</div>
<div className="rounded-2xl border border-line/70 bg-surface/80 px-2 py-2 text-right">
<p className="text-[11px] font-semibold uppercase tracking-[0.22em] text-muted">Last Refresh</p>
<p className="mt-1 text-sm font-semibold text-text">{snapshot ? formatDateTime(snapshot.refreshedAt) : "Waiting"}</p>
</div>
</div>
<p className="mt-3 max-w-3xl text-sm leading-6 text-muted">
This landing page now reads directly from live CRM, inventory, purchasing, manufacturing, sales, shipping, and project data. It is
intentionally modular so future planning, approvals, and audit slices can slot into the same command surface without a redesign.
</p>
<div className="mt-5 grid gap-2 sm:grid-cols-3">
<div className="rounded-2xl border border-line/70 bg-surface/80 px-2 py-2">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted">Modules Live</p>
<p className="mt-1 text-lg font-extrabold text-text">{accessibleModules}</p>
</div>
<div className="rounded-2xl border border-line/70 bg-surface/80 px-2 py-2">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted">Recent Activity</p>
<p className="mt-1 text-sm font-semibold text-text">{formatDateTime(lastActivityAt)}</p>
</div>
<div className="rounded-2xl border border-line/70 bg-surface/80 px-2 py-2">
<p className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted">Loading State</p>
<p className="mt-1 text-sm font-semibold text-text">{isLoading ? "Refreshing data" : "Live snapshot loaded"}</p>
</div>
</div>
<div className="mt-5 flex flex-wrap gap-3">
<Link className="rounded-2xl bg-brand px-3 py-2 text-sm font-semibold text-white" to="/sales/orders">
Open sales orders
</Link>
<Link className="rounded-2xl border border-line/70 px-3 py-2 text-sm font-semibold text-text" to="/shipping/shipments">
Open shipments
</Link>
<Link className="rounded-2xl border border-line/70 px-3 py-2 text-sm font-semibold text-text" to="/inventory/items">
Open inventory
</Link>
<Link className="rounded-2xl border border-line/70 px-3 py-2 text-sm font-semibold text-text" to="/purchasing/orders">
Open purchasing
</Link>
<Link className="rounded-2xl border border-line/70 px-3 py-2 text-sm font-semibold text-text" to="/projects">
Open projects
</Link>
<Link className="rounded-2xl border border-line/70 px-3 py-2 text-sm font-semibold text-text" to="/manufacturing/work-orders">
Open manufacturing
</Link>
{canReadPlanning ? (
<Link className="rounded-2xl border border-line/70 px-3 py-2 text-sm font-semibold text-text" to="/planning/gantt">
Open planning
</Link>
) : null}
</div>
{error ? <div className="mt-4 rounded-2xl border border-amber-400/30 bg-amber-500/12 px-2 py-2 text-sm text-amber-700 dark:text-amber-300">{error}</div> : null}
</div>
</div>
<div className="border-l border-line/70 bg-page/40 p-5 2xl:p-6">
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">Upgrade Path</p>
<div className="mt-4 space-y-3">
{futureModules.map((item) => (
<div key={item} className="rounded-2xl border border-line/70 bg-surface/80 px-2 py-2 text-sm text-text">
{item}
</div>
))}
</div>
</div>
</div>
</section>
{error ? <div className="rounded-[18px] border border-amber-400/30 bg-amber-500/12 px-3 py-3 text-sm text-amber-700 dark:text-amber-300">{error}</div> : null}
<section className="grid gap-3 xl:grid-cols-7">
{metricCards.map((card) => (
<article key={card.label} className="rounded-[24px] border border-line/70 bg-surface/90 px-3 py-3 shadow-panel">
<article key={card.label} className="rounded-[18px] border border-line/70 bg-surface/90 px-3 py-3 shadow-panel">
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-muted">{card.label}</p>
<div className="mt-2 flex items-center justify-between gap-3">
<div className="text-xl font-extrabold text-text">{card.value}</div>
<span className={`rounded-full px-2 py-1 text-xs font-semibold ${card.tone}`}>Live</span>
<span className={`rounded-lg px-2 py-1 text-xs font-semibold ${card.tone}`}>Live</span>
</div>
<p className="mt-2 text-sm text-muted">{card.detail}</p>
</article>
))}
</section>
<section className="grid gap-3 xl:grid-cols-2 2xl:grid-cols-7">
{modulePanels.map((panel) => (
<article key={panel.title} className="rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">{panel.eyebrow}</p>
<h4 className="mt-2 text-lg font-bold text-text">{panel.title}</h4>
<p className="mt-3 text-sm leading-6 text-muted">{panel.summary}</p>
<div className="mt-5 grid gap-2">
<article key={panel.title} className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<h4 className="text-lg font-bold text-text">{panel.title}</h4>
<div className="mt-4 grid gap-2">
{panel.metrics.map((metric) => (
<div key={metric.label} className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div key={metric.label} className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">{metric.label}</span>
<span className="font-semibold text-text">{metric.value}</span>
</div>
@@ -550,131 +360,124 @@ export function DashboardPage() {
))}
</section>
<section className="grid gap-3 xl:grid-cols-6">
<article className="rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">Planning Watch</p>
<h4 className="mt-2 text-lg font-bold text-text">Shared shortage and readiness</h4>
<article className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<h4 className="text-lg font-bold text-text">Planning</h4>
<div className="mt-4 grid gap-2">
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Shortage items</span>
<span className="font-semibold text-text">{planningRollup ? `${shortageItemCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Build recommendations</span>
<span className="font-semibold text-text">{planningRollup ? `${buildRecommendationCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Buy recommendations</span>
<span className="font-semibold text-text">{planningRollup ? `${buyRecommendationCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Uncovered qty</span>
<span className="font-semibold text-text">{planningRollup ? `${totalUncoveredQuantity}` : "No access"}</span>
</div>
</div>
</article>
<article className="rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">Inventory Watch</p>
<h4 className="mt-2 text-lg font-bold text-text">Master data pressure points</h4>
<article className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<h4 className="text-lg font-bold text-text">Inventory</h4>
<div className="mt-4 grid gap-2">
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Obsolete items</span>
<span className="font-semibold text-text">{snapshot?.items !== null ? `${obsoleteItemCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Warehouse count</span>
<span className="font-semibold text-text">{snapshot?.warehouses !== null ? `${warehouseCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Stock locations</span>
<span className="font-semibold text-text">{snapshot?.warehouses !== null ? `${locationCount}` : "No access"}</span>
</div>
</div>
</article>
<article className="rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">Sales Watch</p>
<h4 className="mt-2 text-lg font-bold text-text">Commercial flow snapshot</h4>
<article className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<h4 className="text-lg font-bold text-text">Sales</h4>
<div className="mt-4 grid gap-2">
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Issued orders</span>
<span className="font-semibold text-text">{snapshot?.orders !== null ? `${issuedOrderCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Draft quotes</span>
<span className="font-semibold text-text">{snapshot?.quotes !== null ? `${draftQuoteCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Order backlog</span>
<span className="font-semibold text-text">{snapshot?.orders !== null ? formatCurrency(orderValue) : "No access"}</span>
</div>
</div>
</article>
<article className="rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">Purchasing Watch</p>
<h4 className="mt-2 text-lg font-bold text-text">Inbound supply and commitment load</h4>
<article className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<h4 className="text-lg font-bold text-text">Purchasing</h4>
<div className="mt-4 grid gap-2">
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Total purchase orders</span>
<span className="font-semibold text-text">{snapshot?.purchaseOrders !== null ? `${purchaseOrderCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Open queue</span>
<span className="font-semibold text-text">{snapshot?.purchaseOrders !== null ? `${openPurchaseOrderCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Committed value</span>
<span className="font-semibold text-text">{snapshot?.purchaseOrders !== null ? formatCurrency(purchaseOrderValue) : "No access"}</span>
</div>
</div>
</article>
<article className="rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">Manufacturing Watch</p>
<h4 className="mt-2 text-lg font-bold text-text">Build execution and due-date pressure</h4>
<article className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<h4 className="text-lg font-bold text-text">Manufacturing</h4>
<div className="mt-4 grid gap-2">
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Total work orders</span>
<span className="font-semibold text-text">{snapshot?.workOrders !== null ? `${workOrderCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Active queue</span>
<span className="font-semibold text-text">{snapshot?.workOrders !== null ? `${activeWorkOrderCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Overdue</span>
<span className="font-semibold text-text">{snapshot?.workOrders !== null ? `${overdueWorkOrderCount}` : "No access"}</span>
</div>
</div>
</article>
<article className="rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">Project Watch</p>
<h4 className="mt-2 text-lg font-bold text-text">Program status and delivery pressure</h4>
<article className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<h4 className="text-lg font-bold text-text">Projects</h4>
<div className="mt-4 grid gap-2">
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Total projects</span>
<span className="font-semibold text-text">{snapshot?.projects !== null ? `${projectCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">At risk</span>
<span className="font-semibold text-text">{snapshot?.projects !== null ? `${atRiskProjectCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Overdue</span>
<span className="font-semibold text-text">{snapshot?.projects !== null ? `${overdueProjectCount}` : "No access"}</span>
</div>
</div>
</article>
<article className="rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">Shipping Watch</p>
<h4 className="mt-2 text-lg font-bold text-text">Execution and delivery status</h4>
<article className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
<h4 className="text-lg font-bold text-text">Shipping</h4>
<div className="mt-4 grid gap-2">
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Total shipments</span>
<span className="font-semibold text-text">{snapshot?.shipments !== null ? `${shipmentCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Open queue</span>
<span className="font-semibold text-text">{snapshot?.shipments !== null ? `${activeShipmentCount}` : "No access"}</span>
</div>
<div className="flex items-center justify-between rounded-2xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<div className="flex items-center justify-between rounded-xl border border-line/70 bg-page/60 px-2 py-2 text-sm">
<span className="text-muted">Delivered</span>
<span className="font-semibold text-text">{snapshot?.shipments !== null ? `${deliveredCount}` : "No access"}</span>
</div>