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; quotes: Awaited> | null; orders: Awaited> | null; shipments: 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); 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 canReadSales = hasPermission(user.permissions, permissions.salesRead); const canReadShipping = hasPermission(user.permissions, permissions.shippingRead); 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), canReadSales ? api.getQuotes(authToken) : Promise.resolve(null), canReadSales ? api.getSalesOrders(authToken) : Promise.resolve(null), canReadShipping ? api.getShipments(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, quotes: results[4].status === "fulfilled" ? results[4].value : null, orders: results[5].status === "fulfilled" ? results[5].value : null, shipments: results[6].status === "fulfilled" ? results[6].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 quotes = snapshot?.quotes ?? []; const orders = snapshot?.orders ?? []; const shipments = snapshot?.shipments ?? []; const accessibleModules = [ snapshot?.customers !== null || snapshot?.vendors !== null, snapshot?.items !== null || snapshot?.warehouses !== null, snapshot?.quotes !== null || snapshot?.orders !== null, snapshot?.shipments !== 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 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 lastActivityAt = [ ...customers.map((customer) => customer.updatedAt), ...vendors.map((vendor) => vendor.updatedAt), ...items.map((item) => item.updatedAt), ...warehouses.map((warehouse) => warehouse.updatedAt), ...quotes.map((quote) => quote.updatedAt), ...orders.map((order) => order.updatedAt), ...shipments.map((shipment) => shipment.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: "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", }, ]; 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: "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" }, ], }, ]; const futureModules = [ "Purchase-order queue and supplier receipts", "Stock transfers, allocations, and cycle counts", "Shipping labels, bills of lading, and delivery exceptions", "Manufacturing schedule, work orders, and bottleneck metrics", ]; 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, sales, and shipping data. It is intentionally modular so future purchasing, manufacturing, 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
{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"}

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"}
); }