{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "wave-picking-console",
  "title": "Wave Picking Console",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/wave-picking-console/WavePickingConsole.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport { Barcode, Check, MapPin } from 'lucide-react'\nimport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Badge } from '@/components/ui/badge'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\nexport interface PickItem {\n  id: string\n  sequence: number\n  location: string\n  sku: string\n  name: string\n  barcode: string\n  requiredQty: number\n  pickedQty: number\n  toteNumber: string\n  orderNumber: string\n  status: 'pending' | 'picking' | 'picked' | 'shortage'\n}\n\nexport interface WavePickingConsoleProps {\n  waveId?: string\n  zoneName?: string\n  pickerName?: string\n  className?: string\n}\n\nexport function WavePickingConsole({\n  waveId = 'WAVE-B2C-904',\n  zoneName = 'Zone 02 · Fast Mover Aisle',\n  pickerName = 'Alex Mercer (ID: PK-41)',\n  className,\n}: WavePickingConsoleProps) {\n  const [activeBarcode, setActiveBarcode] = React.useState('')\n\n  const [pickItems, setPickItems] = React.useState<PickItem[]>([\n    {\n      id: 'pk-1',\n      sequence: 1,\n      location: 'A02-S1-B04',\n      sku: 'SKU-AUDIO-ANC',\n      name: 'Active Noise Canceling Headphones Matte Black',\n      barcode: '079357319901',\n      requiredQty: 2,\n      pickedQty: 2,\n      toteNumber: 'TOTE-01',\n      orderNumber: 'ORD-99120',\n      status: 'picked',\n    },\n    {\n      id: 'pk-2',\n      sequence: 2,\n      location: 'A02-S3-B11',\n      sku: 'SKU-CABLE-BRAID',\n      name: 'Braided Type-C Thunderbolt 4 Cable (2m)',\n      barcode: '079357319902',\n      requiredQty: 4,\n      pickedQty: 1,\n      toteNumber: 'TOTE-02',\n      orderNumber: 'ORD-99124',\n      status: 'picking',\n    },\n    {\n      id: 'pk-3',\n      sequence: 3,\n      location: 'A03-S2-B08',\n      sku: 'SKU-DESK-PAD',\n      name: 'Top-Grain Leather Desk Mat Midnight Gray',\n      barcode: '079357319903',\n      requiredQty: 1,\n      pickedQty: 0,\n      toteNumber: 'TOTE-01',\n      orderNumber: 'ORD-99120',\n      status: 'pending',\n    },\n    {\n      id: 'pk-4',\n      sequence: 4,\n      location: 'A04-S1-B02',\n      sku: 'SKU-HUB-10IN1',\n      name: 'USB-C Aluminum Desktop Docking Station',\n      barcode: '079357319904',\n      requiredQty: 3,\n      pickedQty: 0,\n      toteNumber: 'TOTE-03',\n      orderNumber: 'ORD-99131',\n      status: 'pending',\n    },\n  ])\n\n  const totalUnitsToPick = pickItems.reduce((acc, i) => acc + i.requiredQty, 0)\n  const totalUnitsPicked = pickItems.reduce((acc, i) => acc + i.pickedQty, 0)\n  const progressPercentage = Math.round((totalUnitsPicked / totalUnitsToPick) * 100)\n\n  const activeItem = pickItems.find((i) => i.status === 'picking') || pickItems.find((i) => i.status === 'pending')\n\n  function scanItem() {\n    if (!activeItem) return\n    setPickItems((prev) => {\n      let movedToNext = false\n      return prev\n        .map((item) => {\n          if (item.id === activeItem.id && item.pickedQty < item.requiredQty) {\n            const nextQty = item.pickedQty + 1\n            const isDone = nextQty === item.requiredQty\n            if (isDone) movedToNext = true\n            return {\n              ...item,\n              pickedQty: nextQty,\n              status: (isDone ? 'picked' : 'picking') as PickItem['status'],\n            }\n          }\n          return item\n        })\n        .map((item, idx, arr) => {\n          if (movedToNext && item.status === 'pending') {\n            // make the first pending active\n            const firstPending = arr.find((x) => x.status === 'pending')\n            if (item.id === firstPending?.id) {\n              return { ...item, status: 'picking' as const }\n            }\n          }\n          return item\n        })\n    })\n    setActiveBarcode('')\n  }\n\n  function flagShortage(id: string) {\n    setPickItems((prev) => {\n      let foundNext = false\n      return prev.map((item) => {\n        if (item.id === id) {\n          foundNext = true\n          return { ...item, status: 'shortage' as const }\n        }\n        if (foundNext && item.status === 'pending') {\n          foundNext = false\n          return { ...item, status: 'picking' as const }\n        }\n        return item\n      })\n    })\n  }\n\n  return (\n    <div data-slot=\"wave-picking-console\" className={`w-full space-y-6 ${className ?? ''}`}>\n      {/* Top Wave Header Card */}\n      <Card>\n        <CardHeader className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n          <div className=\"space-y-1\">\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-foreground font-mono text-sm font-semibold\">{waveId}</span>\n              <Badge variant=\"outline\" className=\"font-mono text-xs\">\n                {zoneName}\n              </Badge>\n              <Badge variant={progressPercentage === 100 ? 'default' : 'secondary'}>{progressPercentage}% Picked</Badge>\n            </div>\n            <CardTitle className=\"text-xl\">Batch Order Wave Picking Console</CardTitle>\n            <CardDescription>\n              Assigned Picker: <span className=\"text-foreground font-medium\">{pickerName}</span> · Route Optimized\n            </CardDescription>\n          </div>\n\n          <div className=\"flex items-center gap-3\">\n            <div className=\"text-right\">\n              <div className=\"text-muted-foreground text-xs\">Pick Completion</div>\n              <div className=\"font-mono text-lg font-bold\">\n                {totalUnitsPicked} / {totalUnitsToPick} Units\n              </div>\n            </div>\n          </div>\n        </CardHeader>\n\n        {/* Active Pick Target Banner */}\n        {activeItem && (\n          <CardContent className=\"border-border border-t pt-4\">\n            <div className=\"border-border bg-muted/40 rounded-lg border p-4\">\n              <div className=\"flex flex-col gap-3 md:flex-row md:items-center md:justify-between\">\n                <div className=\"space-y-1\">\n                  <div className=\"flex items-center gap-2\">\n                    <span className=\"bg-foreground text-background rounded px-2 py-0.5 font-mono text-xs font-semibold\">\n                      NEXT TARGET: {activeItem.location}\n                    </span>\n                    <span className=\"text-muted-foreground font-mono text-xs\">TOTE: {activeItem.toteNumber}</span>\n                    <span className=\"text-muted-foreground font-mono text-xs\">({activeItem.orderNumber})</span>\n                  </div>\n                  <div className=\"text-foreground text-lg font-semibold\">{activeItem.name}</div>\n                  <div className=\"text-muted-foreground font-mono text-xs\">\n                    SKU: {activeItem.sku} · Scan Barcode: {activeItem.barcode}\n                  </div>\n                </div>\n\n                {/* Fast Scan & Action Button Group */}\n                <div className=\"flex items-center gap-2\">\n                  <div className=\"relative w-48\">\n                    <Barcode className=\"text-muted-foreground pointer-events-none absolute top-2.5 left-2.5 size-4\" />\n                    <Input\n                      value={activeBarcode}\n                      onChange={(e) => setActiveBarcode(e.target.value)}\n                      placeholder=\"Scan SKU barcode...\"\n                      className=\"h-9 pl-8\"\n                      onKeyDown={(e) => e.key === 'Enter' && scanItem()}\n                    />\n                  </div>\n                  <Button size=\"sm\" className=\"gap-1.5\" onClick={scanItem}>\n                    <Check className=\"size-4\" />\n                    Confirm Pick\n                  </Button>\n                  <Button\n                    variant=\"outline\"\n                    size=\"sm\"\n                    className=\"text-destructive hover:bg-destructive/10\"\n                    onClick={() => flagShortage(activeItem.id)}\n                  >\n                    Flag Shortage\n                  </Button>\n                </div>\n              </div>\n            </div>\n          </CardContent>\n        )}\n      </Card>\n\n      {/* Optimized Route Table */}\n      <Card>\n        <CardHeader className=\"pb-3\">\n          <CardTitle className=\"text-base font-semibold\">Optimized Pick Route Sequence</CardTitle>\n          <CardDescription>\n            Pick items strictly in sequence to minimize travel distance across fulfillment aisles.\n          </CardDescription>\n        </CardHeader>\n\n        <CardContent className=\"p-0\">\n          <Table>\n            <TableHeader>\n              <TableRow>\n                <TableHead className=\"w-[60px]\">Seq</TableHead>\n                <TableHead>Location Bin</TableHead>\n                <TableHead className=\"w-[300px]\">Product / SKU</TableHead>\n                <TableHead>Tote & Order</TableHead>\n                <TableHead className=\"text-right\">Qty</TableHead>\n                <TableHead>Status</TableHead>\n              </TableRow>\n            </TableHeader>\n            <TableBody>\n              {pickItems.map((item) => (\n                <TableRow key={item.id} className={item.status === 'picking' ? 'bg-muted/50 font-medium' : ''}>\n                  {/* Sequence Number */}\n                  <TableCell className=\"text-muted-foreground font-mono text-xs\">#{item.sequence}</TableCell>\n\n                  {/* Location Bin */}\n                  <TableCell>\n                    <div className=\"text-foreground flex items-center gap-1.5 font-mono text-xs font-semibold\">\n                      <MapPin className=\"text-muted-foreground size-3.5\" />\n                      <span>{item.location}</span>\n                    </div>\n                  </TableCell>\n\n                  {/* Product */}\n                  <TableCell>\n                    <div className=\"font-medium\">{item.name}</div>\n                    <div className=\"text-muted-foreground font-mono text-xs\">{item.sku}</div>\n                  </TableCell>\n\n                  {/* Tote & Order */}\n                  <TableCell>\n                    <div className=\"flex items-center gap-1.5 font-mono text-xs\">\n                      <Badge variant=\"outline\">{item.toteNumber}</Badge>\n                      <span className=\"text-muted-foreground\">{item.orderNumber}</span>\n                    </div>\n                  </TableCell>\n\n                  {/* Qty Progress */}\n                  <TableCell className=\"text-right font-mono text-sm\">\n                    {item.pickedQty} / {item.requiredQty}\n                  </TableCell>\n\n                  {/* Status Badge */}\n                  <TableCell>\n                    <Badge\n                      variant={\n                        item.status === 'picked'\n                          ? 'default'\n                          : item.status === 'picking'\n                            ? 'secondary'\n                            : item.status === 'shortage'\n                              ? 'destructive'\n                              : 'outline'\n                      }\n                      className=\"capitalize\"\n                    >\n                      {item.status}\n                    </Badge>\n                  </TableCell>\n                </TableRow>\n              ))}\n            </TableBody>\n          </Table>\n        </CardContent>\n\n        <CardFooter className=\"border-border text-muted-foreground flex items-center justify-between border-t py-3 text-xs\">\n          <div>Completed totes are automatically routed to Conveyor Pack Station 04.</div>\n          <div className=\"text-foreground font-medium\">\n            Wave Target: <span className=\"font-mono\">{pickItems.length}</span> pick positions\n          </div>\n        </CardFooter>\n      </Card>\n    </div>\n  )\n}\n",
      "type": "registry:block",
      "target": "~/components/blocks/wave-picking-console/WavePickingConsole.tsx"
    },
    {
      "path": "packages/registry-react/blocks/wave-picking-console/index.ts",
      "content": "export { WavePickingConsole } from './WavePickingConsole'\nexport type { PickItem, WavePickingConsoleProps } from './WavePickingConsole'\n",
      "type": "registry:block",
      "target": "~/components/blocks/wave-picking-console/index.ts"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/card.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/input.json",
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/table.json"
  ],
  "description": "Batch wave picking console with multi-order tote assignment, optimized pick route, and barcode verification.",
  "categories": [
    "dashboard",
    "data-display"
  ]
}