diff --git a/src/app/inventory-bay/_components/category-summary-tile.tsx b/src/app/inventory-bay/_components/category-summary-tile.tsx new file mode 100644 index 0000000..be8e59d --- /dev/null +++ b/src/app/inventory-bay/_components/category-summary-tile.tsx @@ -0,0 +1,117 @@ +import { + getAvailableToPromise, + inventoryBayBands, + type InventoryBayCategorySummary, +} from "../_data/inventory-bay-data"; + +type CategorySummaryTileProps = { + summary: InventoryBayCategorySummary; +}; + +export function CategorySummaryTile({ summary }: CategorySummaryTileProps) { + const focusBand = inventoryBayBands.find( + (band) => band.id === summary.focusItem.bandId, + ); + console.log("CategorySummaryTile", summary.id); + + return ( +
  • +
    +
    +
    +

    + {summary.zone} +

    +

    + {summary.name} +

    +
    + +
    + + {summary.skuCount} SKUs + + + {summary.lowStockCount} warnings + +
    +
    + +

    + {summary.description} +

    + +
    +
    +
    + Fill rate +
    +
    + {summary.fillRate}% +
    +
    +
    +
    + Available units +
    +
    + {summary.availableUnits} +
    +
    +
    + +
    +
    + + Focus item + + {focusBand ? ( + + {focusBand.name} + + ) : null} + {summary.criticalCount > 0 ? ( + + {summary.criticalCount} critical + + ) : null} +
    + +

    + {summary.focusItem.name} +

    +

    + {summary.focusItem.location} · {summary.focusItem.owner} +

    + +
    +
    +

    + Cover and ATP +

    +

    + {summary.focusItem.daysOfCover} days of cover +

    +

    + {getAvailableToPromise(summary.focusItem)} ATP units +

    +
    +
    +

    + Next restock window +

    +

    + {summary.restockWindow} +

    +

    + {summary.focusItem.nextDelivery} +

    +
    +
    +
    +
    +
  • + ); +} diff --git a/src/app/inventory-bay/_components/inventory-bay-card.tsx b/src/app/inventory-bay/_components/inventory-bay-card.tsx deleted file mode 100644 index f1847a1..0000000 --- a/src/app/inventory-bay/_components/inventory-bay-card.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import { - getAvailableToPromise, - getStockFillPercentage, - type InventoryBayBand, - type InventoryBayItem, -} from "../_data/inventory-bay-data"; - -type InventoryBayCardProps = { - item: InventoryBayItem; - band: InventoryBayBand; -}; - -export function InventoryBayCard({ item, band }: InventoryBayCardProps) { - const titleId = `${item.id}-title`; - const availableToPromise = getAvailableToPromise(item); - const fillPercentage = getStockFillPercentage(item); - - return ( -
    -
    -
    -
    - - {band.name} - - - {band.stateLabel} - - - {item.sku} - -
    - -

    - {item.name} -

    -

    - {item.statusDetail} -

    -
    - -
    -

    - Bay location -

    -

    - {item.location} -

    -

    {item.owner}

    -
    -
    - -
    -
    - Stock fill - {fillPercentage}% of target -
    -
    -
    -
    -
    - -
    -
    -
    - Units on hand -
    -
    - {item.unitsOnHand} units on hand -
    -
    -
    -
    - Available to promise -
    -
    - {availableToPromise} available to promise -
    -
    -
    -
    - Days of cover -
    -
    - {item.daysOfCover} days of cover -
    -
    -
    -
    - Reorder point -
    -
    - Reorder at {item.reorderPoint} -
    -
    -
    - -
    -
    -
    -

    - Next delivery -

    -

    - {item.nextDelivery} -

    -
    -
    -

    - Action now -

    -

    - {item.actionLabel} -

    -
    -
    -
    - -
    - {item.tags.map((tag) => ( - - {tag} - - ))} -
    -
    - ); -} diff --git a/src/app/inventory-bay/_components/inventory-bay-category-section.tsx b/src/app/inventory-bay/_components/inventory-bay-category-section.tsx deleted file mode 100644 index 1446299..0000000 --- a/src/app/inventory-bay/_components/inventory-bay-category-section.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { - inventoryBayBands, - type InventoryBaySection, -} from "../_data/inventory-bay-data"; -import { InventoryBayCard } from "./inventory-bay-card"; - -type InventoryBayCategorySectionProps = { - section: InventoryBaySection; -}; - -export function InventoryBayCategorySection({ - section, -}: InventoryBayCategorySectionProps) { - const titleId = `${section.id}-title`; - - return ( -
    -
    -
    -

    - {section.bay} -

    -

    - {section.name} -

    -

    - {section.description} -

    -
    - -
    - - {section.items.length} SKUs - - - {section.availableToPromise} ATP units - - {inventoryBayBands - .filter((band) => section.bandCounts[band.id] > 0) - .map((band) => ( - - {section.bandCounts[band.id]} {band.stateLabel} - - ))} -
    -
    - -
    - {section.items.map((item) => { - const band = inventoryBayBands.find((entry) => entry.id === item.bandId); - - if (!band) { - return null; - } - - return ; - })} -
    -
    - ); -} diff --git a/src/app/inventory-bay/_components/inventory-bay-shell.tsx b/src/app/inventory-bay/_components/inventory-bay-shell.tsx index 8237491..4c95a67 100644 --- a/src/app/inventory-bay/_components/inventory-bay-shell.tsx +++ b/src/app/inventory-bay/_components/inventory-bay-shell.tsx @@ -1,46 +1,25 @@ -import Link from "next/link"; - import type { InventoryBayBandSummary, - InventoryBayMetrics, - InventoryBayRecommendationView, - InventoryBaySection, + InventoryBayCategorySummary, + InventoryBayLowStockView, + InventoryBayOverviewMetric, } from "../_data/inventory-bay-data"; -import { InventoryBayCategorySection } from "./inventory-bay-category-section"; -import { RestockRecommendationPanel } from "./restock-recommendation-panel"; +import { CategorySummaryTile } from "./category-summary-tile"; +import { LowStockPanel } from "./low-stock-panel"; import { StockBandSummaryCard } from "./stock-band-summary-card"; type InventoryBayShellProps = { bandSummaries: InventoryBayBandSummary[]; - metrics: InventoryBayMetrics; - recommendations: InventoryBayRecommendationView[]; - sections: InventoryBaySection[]; + categorySummaries: InventoryBayCategorySummary[]; + lowStockAlerts: InventoryBayLowStockView[]; + overviewMetrics: InventoryBayOverviewMetric[]; }; -const metricCards = [ - { - id: "trackedSkus", - label: "Tracked SKUs", - }, - { - id: "atRiskSkus", - label: "At-risk stock", - }, - { - id: "availableToPromise", - label: "Available to promise", - }, - { - id: "recommendationCount", - label: "Recommended moves", - }, -] as const; - export function InventoryBayShell({ bandSummaries, - metrics, - recommendations, - sections, + categorySummaries, + lowStockAlerts, + overviewMetrics, }: InventoryBayShellProps) { return (
    @@ -50,48 +29,45 @@ export function InventoryBayShell({

    Inventory Bay

    - - Back to overview - +

    + Standalone mock route +

    - Scan stock bands, bay sections, and next restock moves from one route. + See stock bands, category pressure, and low-stock warnings in one bay scan.

    - The inventory bay route keeps stock pressure visible without a backend: - band summaries show where attention is rising, category sections keep - each bay readable, and the recommendation panel stays focused on the - next move to protect throughput. + This standalone route keeps the inventory story compact: band cards + show the overall stock mix, category tiles summarize each bay zone, + and the low-stock panel surfaces the items that still need action + before the next replenishment window.

    - Local mock stock, band, and recommendation data + Local mock stock, band, category, and alert data - Sections grouped by bay category + Summary tiles grouped by bay category - Available, low-stock, and depleted visual states + Healthy, watch, and critical stock states - Recommendation panel stays visible beside the stock grid + Compact warning panel stays visible beside the category grid
    - {metricCards.map((metricCard) => ( + {overviewMetrics.map((metricCard) => (

    - {metrics[metricCard.id]} + {metricCard.value} +

    +

    + {metricCard.detail}

    ))} @@ -119,53 +98,57 @@ export function InventoryBayShell({ id="inventory-bands-heading" className="mt-2 text-3xl font-semibold tracking-tight text-slate-950" > - Band-level stock pressure + Stock bands at a glance

    - Each band condenses the same mock inventory into a quick scan so the - route immediately shows where bay pressure is stable, tightening, or - already below the safe reorder line. + Each stock band compresses the bay mix into a readable summary so it + is obvious where supply is stable, slipping, or already below the + safe reorder line.

    -