import { permissions } from "@mrp/shared"; import { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import { useAuth } from "../../auth/AuthProvider"; import { ApiError, api } from "../../lib/api"; interface DashboardSnapshot { customers: Awaited> | null; vendors: Awaited> | null; items: Awaited> | null; warehouses: Awaited> | null; workOrders: Awaited> | null; quotes: Awaited> | null; orders: Awaited> | null; shipments: Awaited> | null; projects: Awaited> | null; refreshedAt: string; } function hasPermission(userPermissions: string[] | undefined, permission: string) { return Boolean(userPermissions?.includes(permission)); } function formatCurrency(value: number) { return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", maximumFractionDigits: 0, }).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); } export function DashboardPage() { const { token, user } = useAuth(); const [snapshot, setSnapshot] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const canWriteManufacturing = hasPermission(user?.permissions, permissions.manufacturingWrite); const canWriteProjects = hasPermission(user?.permissions, permissions.projectsWrite); useEffect(() => { if (!token || !user) { setSnapshot(null); setIsLoading(false); return; } const authToken = token; let isMounted = true; setIsLoading(true); setError(null); const canReadCrm = hasPermission(user.permissions, permissions.crmRead); const canReadInventory = hasPermission(user.permissions, permissions.inventoryRead); const canReadManufacturing = hasPermission(user.permissions, permissions.manufacturingRead); const canReadSales = hasPermission(user.permissions, permissions.salesRead); const canReadShipping = hasPermission(user.permissions, permissions.shippingRead); const canReadProjects = hasPermission(user.permissions, permissions.projectsRead); async function loadSnapshot() { const results = await Promise.allSettled([ canReadCrm ? api.getCustomers(authToken) : Promise.resolve(null), canReadCrm ? api.getVendors(authToken) : Promise.resolve(null), canReadInventory ? api.getInventoryItems(authToken) : Promise.resolve(null), canReadInventory ? api.getWarehouses(authToken) : Promise.resolve(null), canReadManufacturing ? api.getWorkOrders(authToken) : Promise.resolve(null), canReadSales ? api.getQuotes(authToken) : Promise.resolve(null), canReadSales ? api.getSalesOrders(authToken) : Promise.resolve(null), canReadShipping ? api.getShipments(authToken) : Promise.resolve(null), canReadProjects ? api.getProjects(authToken) : Promise.resolve(null), ]); if (!isMounted) { return; } const firstRejected = results.find((result) => result.status === "rejected"); if (firstRejected?.status === "rejected") { const reason = firstRejected.reason; setError(reason instanceof ApiError ? reason.message : "Unable to load dashboard data."); } setSnapshot({ customers: results[0].status === "fulfilled" ? results[0].value : null, vendors: results[1].status === "fulfilled" ? results[1].value : null, items: results[2].status === "fulfilled" ? results[2].value : null, warehouses: results[3].status === "fulfilled" ? results[3].value : null, workOrders: results[4].status === "fulfilled" ? results[4].value : null, quotes: results[5].status === "fulfilled" ? results[5].value : null, orders: results[6].status === "fulfilled" ? results[6].value : null, shipments: results[7].status === "fulfilled" ? results[7].value : null, projects: results[8].status === "fulfilled" ? results[8].value : null, refreshedAt: new Date().toISOString(), }); setIsLoading(false); } loadSnapshot().catch((loadError) => { if (!isMounted) { return; } setError(loadError instanceof ApiError ? loadError.message : "Unable to load dashboard data."); setSnapshot(null); setIsLoading(false); }); return () => { isMounted = false; }; }, [token, user]); const customers = snapshot?.customers ?? []; const vendors = snapshot?.vendors ?? []; const items = snapshot?.items ?? []; const warehouses = snapshot?.warehouses ?? []; const workOrders = snapshot?.workOrders ?? []; const quotes = snapshot?.quotes ?? []; const orders = snapshot?.orders ?? []; const shipments = snapshot?.shipments ?? []; const projects = snapshot?.projects ?? []; const accessibleModules = [ snapshot?.customers !== null || snapshot?.vendors !== null, snapshot?.items !== null || snapshot?.warehouses !== null, snapshot?.workOrders !== null, snapshot?.quotes !== null || snapshot?.orders !== null, snapshot?.shipments !== null, snapshot?.projects !== null, ].filter(Boolean).length; const customerCount = customers.length; const resellerCount = customers.filter((customer) => customer.isReseller).length; const activeCustomerCount = customers.filter((customer) => customer.lifecycleStage === "ACTIVE").length; const strategicCustomerCount = customers.filter((customer) => customer.strategicAccount).length; const vendorCount = vendors.length; const itemCount = items.length; const assemblyCount = items.filter((item) => item.type === "ASSEMBLY" || item.type === "MANUFACTURED").length; const activeItemCount = items.filter((item) => item.status === "ACTIVE").length; const obsoleteItemCount = items.filter((item) => item.status === "OBSOLETE").length; const warehouseCount = warehouses.length; const locationCount = sumNumber(warehouses.map((warehouse) => warehouse.locationCount)); const workOrderCount = workOrders.length; const activeWorkOrderCount = workOrders.filter((workOrder) => workOrder.status === "RELEASED" || workOrder.status === "IN_PROGRESS" || workOrder.status === "ON_HOLD").length; const releasedWorkOrderCount = workOrders.filter((workOrder) => workOrder.status === "RELEASED").length; const overdueWorkOrderCount = workOrders.filter((workOrder) => workOrder.dueDate && workOrder.status !== "COMPLETE" && workOrder.status !== "CANCELLED" && new Date(workOrder.dueDate).getTime() < Date.now()).length; const quoteCount = quotes.length; const orderCount = orders.length; const draftQuoteCount = quotes.filter((quote) => quote.status === "DRAFT").length; const issuedOrderCount = orders.filter((order) => order.status === "ISSUED" || order.status === "APPROVED").length; const quoteValue = sumNumber(quotes.map((quote) => quote.total)); const orderValue = sumNumber(orders.map((order) => order.total)); const shipmentCount = shipments.length; const activeShipmentCount = shipments.filter((shipment) => shipment.status !== "DELIVERED").length; const inTransitCount = shipments.filter((shipment) => shipment.status === "SHIPPED").length; const deliveredCount = shipments.filter((shipment) => shipment.status === "DELIVERED").length; const projectCount = projects.length; const activeProjectCount = projects.filter((project) => project.status === "ACTIVE").length; const atRiskProjectCount = projects.filter((project) => project.status === "AT_RISK").length; const overdueProjectCount = projects.filter((project) => { if (!project.dueDate || project.status === "COMPLETE") { return false; } return new Date(project.dueDate).getTime() < Date.now(); }).length; const lastActivityAt = [ ...customers.map((customer) => customer.updatedAt), ...vendors.map((vendor) => vendor.updatedAt), ...items.map((item) => item.updatedAt), ...warehouses.map((warehouse) => warehouse.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: "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", }, ]; 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" }, { label: "Vendors", value: snapshot?.vendors !== null ? `${vendorCount}` : "No access" }, ], links: [ { label: "Open customers", to: "/crm/customers" }, { label: "Open vendors", to: "/crm/vendors" }, ], }, { 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" }, { label: "Locations", value: snapshot?.warehouses !== null ? `${locationCount}` : "No access" }, ], links: [ { label: "Open inventory", to: "/inventory/items" }, { label: "Open warehouses", to: "/inventory/warehouses" }, ], }, { 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" }, { label: "Overdue", value: snapshot?.workOrders !== null ? `${overdueWorkOrderCount}` : "No access" }, ], links: [ { label: "Open work orders", to: "/manufacturing/work-orders" }, ...(canWriteManufacturing ? [{ label: "New work order", to: "/manufacturing/work-orders/new" }] : []), ], }, { 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" }, { label: "Draft quotes", value: snapshot?.quotes !== null ? `${draftQuoteCount}` : "No access" }, ], links: [ { label: "Open quotes", to: "/sales/quotes" }, { label: "Open sales orders", to: "/sales/orders" }, ], }, { 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" }, { label: "Delivered", value: snapshot?.shipments !== null ? `${deliveredCount}` : "No access" }, ], links: [ { label: "Open shipments", to: "/shipping/shipments" }, { label: "Open packing flow", to: "/sales/orders" }, ], }, { 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" }, { label: "Overdue", value: snapshot?.projects !== null ? `${overdueProjectCount}` : "No access" }, ], links: [ { label: "Open projects", to: "/projects" }, ...(canWriteProjects ? [{ label: "New project", to: "/projects/new" }] : []), ], }, ]; const futureModules = [ "Vendor invoice attachments and supplier exception queues", "Stock transfers, allocations, and cycle counts", "Planning timeline, milestones, and dependency views", "Audit trails, diagnostics, and system health checks", ]; return (

Dashboard

Operational command surface for metrics, movement, and next actions.

Last Refresh

{snapshot ? formatDateTime(snapshot.refreshedAt) : "Waiting"}

This landing page now reads directly from live CRM, inventory, manufacturing, sales, shipping, and project data. It is intentionally modular so future purchasing, planning, and audit slices can slot into the same command surface without a redesign.

Modules Live

{accessibleModules}

Recent Activity

{formatDateTime(lastActivityAt)}

Loading State

{isLoading ? "Refreshing data" : "Live snapshot loaded"}

Open sales orders Open shipments Open inventory Open projects Open manufacturing
{error ?
{error}
: null}

Upgrade Path

{futureModules.map((item) => (
{item}
))}
{metricCards.map((card) => (

{card.label}

{card.value}
Live

{card.detail}

))}
{modulePanels.map((panel) => (

{panel.eyebrow}

{panel.title}

{panel.summary}

{panel.metrics.map((metric) => (
{metric.label} {metric.value}
))}
{panel.links.map((link) => ( {link.label} ))}
))}

Inventory Watch

Master data pressure points

Obsolete items {snapshot?.items !== null ? `${obsoleteItemCount}` : "No access"}
Warehouse count {snapshot?.warehouses !== null ? `${warehouseCount}` : "No access"}
Stock locations {snapshot?.warehouses !== null ? `${locationCount}` : "No access"}

Sales Watch

Commercial flow snapshot

Issued orders {snapshot?.orders !== null ? `${issuedOrderCount}` : "No access"}
Draft quotes {snapshot?.quotes !== null ? `${draftQuoteCount}` : "No access"}
Order backlog {snapshot?.orders !== null ? formatCurrency(orderValue) : "No access"}

Manufacturing Watch

Build execution and due-date pressure

Total work orders {snapshot?.workOrders !== null ? `${workOrderCount}` : "No access"}
Active queue {snapshot?.workOrders !== null ? `${activeWorkOrderCount}` : "No access"}
Overdue {snapshot?.workOrders !== null ? `${overdueWorkOrderCount}` : "No access"}

Project Watch

Program status and delivery pressure

Total projects {snapshot?.projects !== null ? `${projectCount}` : "No access"}
At risk {snapshot?.projects !== null ? `${atRiskProjectCount}` : "No access"}
Overdue {snapshot?.projects !== null ? `${overdueProjectCount}` : "No access"}

Shipping Watch

Execution and delivery status

Total shipments {snapshot?.shipments !== null ? `${shipmentCount}` : "No access"}
Open queue {snapshot?.shipments !== null ? `${activeShipmentCount}` : "No access"}
Delivered {snapshot?.shipments !== null ? `${deliveredCount}` : "No access"}
); }