{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "wave-picking-console",
  "title": "Wave Picking Console",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/wave-picking-console/WavePickingConsole.vue",
      "content": "<script setup lang=\"ts\">\nimport { ref, computed } from 'vue'\nimport { Barcode, Check, MapPin } from 'lucide-vue-next'\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}\n\nconst props = withDefaults(defineProps<WavePickingConsoleProps>(), {\n  waveId: 'WAVE-B2C-904',\n  zoneName: 'Zone 02 · Fast Mover Aisle',\n  pickerName: 'Alex Mercer (ID: PK-41)',\n})\n\nconst activeBarcode = ref('')\n\nconst pickItems = ref<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\nconst totalUnitsToPick = computed(() => pickItems.value.reduce((acc, i) => acc + i.requiredQty, 0))\nconst totalUnitsPicked = computed(() => pickItems.value.reduce((acc, i) => acc + i.pickedQty, 0))\nconst progressPercentage = computed(() => Math.round((totalUnitsPicked.value / totalUnitsToPick.value) * 100))\n\nconst activeItem = computed(\n  () => pickItems.value.find((i) => i.status === 'picking') || pickItems.value.find((i) => i.status === 'pending'),\n)\n\nfunction scanItem() {\n  if (!activeItem.value) return\n  if (activeItem.value.pickedQty < activeItem.value.requiredQty) {\n    activeItem.value.pickedQty += 1\n    if (activeItem.value.pickedQty === activeItem.value.requiredQty) {\n      activeItem.value.status = 'picked'\n      // Move to next pending\n      const nextPending = pickItems.value.find((i) => i.status === 'pending')\n      if (nextPending) nextPending.status = 'picking'\n    }\n  }\n  activeBarcode.value = ''\n}\n\nfunction flagShortage(id: string) {\n  const target = pickItems.value.find((i) => i.id === id)\n  if (target) {\n    target.status = 'shortage'\n    const nextPending = pickItems.value.find((i) => i.status === 'pending')\n    if (nextPending) nextPending.status = 'picking'\n  }\n}\n</script>\n\n<template>\n  <div data-slot=\"wave-picking-console\" class=\"w-full space-y-6\">\n    <!-- Top Wave Header Card -->\n    <Card>\n      <CardHeader class=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n        <div class=\"space-y-1\">\n          <div class=\"flex items-center gap-2\">\n            <span class=\"text-foreground font-mono text-sm font-semibold\">{{ waveId }}</span>\n            <Badge variant=\"outline\" class=\"font-mono text-xs\">\n              {{ zoneName }}\n            </Badge>\n            <Badge :variant=\"progressPercentage === 100 ? 'default' : 'secondary'\">\n              {{ progressPercentage }}% Picked\n            </Badge>\n          </div>\n          <CardTitle class=\"text-xl\">Batch Order Wave Picking Console</CardTitle>\n          <CardDescription>\n            Assigned Picker: <span class=\"text-foreground font-medium\">{{ pickerName }}</span> · Route Optimized\n          </CardDescription>\n        </div>\n\n        <div class=\"flex items-center gap-3\">\n          <div class=\"text-right\">\n            <div class=\"text-muted-foreground text-xs\">Pick Completion</div>\n            <div class=\"font-mono text-lg font-bold\">{{ totalUnitsPicked }} / {{ totalUnitsToPick }} Units</div>\n          </div>\n        </div>\n      </CardHeader>\n\n      <!-- Active Pick Target Banner -->\n      <CardContent v-if=\"activeItem\" class=\"border-border border-t pt-4\">\n        <div class=\"border-border bg-muted/40 rounded-lg border p-4\">\n          <div class=\"flex flex-col gap-3 md:flex-row md:items-center md:justify-between\">\n            <div class=\"space-y-1\">\n              <div class=\"flex items-center gap-2\">\n                <span class=\"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 class=\"text-muted-foreground font-mono text-xs\">TOTE: {{ activeItem.toteNumber }}</span>\n                <span class=\"text-muted-foreground font-mono text-xs\">({{ activeItem.orderNumber }})</span>\n              </div>\n              <div class=\"text-foreground text-lg font-semibold\">{{ activeItem.name }}</div>\n              <div class=\"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 class=\"flex items-center gap-2\">\n              <div class=\"relative w-48\">\n                <Barcode class=\"text-muted-foreground pointer-events-none absolute top-2.5 left-2.5 size-4\" />\n                <Input\n                  v-model=\"activeBarcode\"\n                  placeholder=\"Scan SKU barcode...\"\n                  class=\"h-9 pl-8\"\n                  @keydown.enter.prevent=\"scanItem\"\n                />\n              </div>\n              <Button size=\"sm\" class=\"gap-1.5\" @click=\"scanItem\">\n                <Check class=\"size-4\" />\n                Confirm Pick\n              </Button>\n              <Button\n                variant=\"outline\"\n                size=\"sm\"\n                class=\"text-destructive hover:bg-destructive/10\"\n                @click=\"flagShortage(activeItem.id)\"\n              >\n                Flag Shortage\n              </Button>\n            </div>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- Optimized Route Table -->\n    <Card>\n      <CardHeader class=\"pb-3\">\n        <CardTitle class=\"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 class=\"p-0\">\n        <Table>\n          <TableHeader>\n            <TableRow>\n              <TableHead class=\"w-[60px]\">Seq</TableHead>\n              <TableHead>Location Bin</TableHead>\n              <TableHead class=\"w-[300px]\">Product / SKU</TableHead>\n              <TableHead>Tote & Order</TableHead>\n              <TableHead class=\"text-right\">Qty</TableHead>\n              <TableHead>Status</TableHead>\n            </TableRow>\n          </TableHeader>\n          <TableBody>\n            <TableRow\n              v-for=\"item in pickItems\"\n              :key=\"item.id\"\n              :class=\"item.status === 'picking' ? 'bg-muted/50 font-medium' : ''\"\n            >\n              <!-- Sequence Number -->\n              <TableCell class=\"text-muted-foreground font-mono text-xs\"> #{{ item.sequence }} </TableCell>\n\n              <!-- Location Bin -->\n              <TableCell>\n                <div class=\"text-foreground flex items-center gap-1.5 font-mono text-xs font-semibold\">\n                  <MapPin class=\"text-muted-foreground size-3.5\" />\n                  <span>{{ item.location }}</span>\n                </div>\n              </TableCell>\n\n              <!-- Product -->\n              <TableCell>\n                <div class=\"font-medium\">{{ item.name }}</div>\n                <div class=\"text-muted-foreground font-mono text-xs\">{{ item.sku }}</div>\n              </TableCell>\n\n              <!-- Tote & Order -->\n              <TableCell>\n                <div class=\"flex items-center gap-1.5 font-mono text-xs\">\n                  <Badge variant=\"outline\">{{ item.toteNumber }}</Badge>\n                  <span class=\"text-muted-foreground\">{{ item.orderNumber }}</span>\n                </div>\n              </TableCell>\n\n              <!-- Qty Progress -->\n              <TableCell class=\"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                  class=\"capitalize\"\n                >\n                  {{ item.status }}\n                </Badge>\n              </TableCell>\n            </TableRow>\n          </TableBody>\n        </Table>\n      </CardContent>\n\n      <CardFooter class=\"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 class=\"text-foreground font-medium\">\n          Wave Target: <span class=\"font-mono\">{{ pickItems.length }}</span> pick positions\n        </div>\n      </CardFooter>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/wave-picking-console/WavePickingConsole.vue"
    },
    {
      "path": "packages/registry-vue/blocks/wave-picking-console/index.ts",
      "content": "export { default as WavePickingConsole } from './WavePickingConsole.vue'\nexport type { PickItem, WavePickingConsoleProps } from './WavePickingConsole.vue'\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/wave-picking-console/index.ts"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/input.json",
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/table.json"
  ],
  "description": "Batch wave picking console with multi-order tote assignment, optimized pick route, and barcode verification.",
  "categories": [
    "dashboard",
    "data-display"
  ]
}