{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "purchase-order-receiving",
  "title": "Purchase Order Receiving",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/purchase-order-receiving/PurchaseOrderReceiving.vue",
      "content": "<script setup lang=\"ts\">\nimport { ref, computed } from 'vue'\nimport { AlertTriangle, Clock, PackageCheck, Printer, ShieldCheck, Warehouse } 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 { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\nexport interface POLineItem {\n  id: string\n  sku: string\n  title: string\n  orderedQty: number\n  receivedQty: number\n  rejectedQty: number\n  rejectionReason: 'none' | 'damaged_packaging' | 'expired_lot' | 'wrong_specification' | 'temperature_excursion'\n  lotNumber: string\n  expiryDate: string\n  stagingLocation: string\n}\n\nexport interface PurchaseOrderReceivingProps {\n  poNumber?: string\n  vendorName?: string\n  deliveryDocket?: string\n}\n\nconst props = withDefaults(defineProps<PurchaseOrderReceivingProps>(), {\n  poNumber: 'PO-2026-4409',\n  vendorName: 'Apex Precision Engineering Ltd',\n  deliveryDocket: 'BOL-APX-98214',\n})\n\nconst isCompleted = ref(false)\nconst receivingDock = ref('dock-03')\nconst inspectionStatus = ref<'pending' | 'passed' | 'discrepancy'>('pending')\n\nconst lines = ref<POLineItem[]>([\n  {\n    id: 'po-1',\n    sku: 'SKU-VALVE-99',\n    title: 'High-Pressure Hydraulic Valve 3/8\"',\n    orderedQty: 100,\n    receivedQty: 100,\n    rejectedQty: 0,\n    rejectionReason: 'none',\n    lotNumber: 'LOT-HYD-998',\n    expiryDate: '2029-12-31',\n    stagingLocation: 'ZONE-A-RACK-04',\n  },\n  {\n    id: 'po-2',\n    sku: 'SKU-SEAL-04',\n    title: 'Fluorocarbon O-Ring Flange Kit (Pack of 50)',\n    orderedQty: 250,\n    receivedQty: 245,\n    rejectedQty: 5,\n    rejectionReason: 'damaged_packaging',\n    lotNumber: 'LOT-O-7712',\n    expiryDate: '2028-06-30',\n    stagingLocation: 'ZONE-A-RACK-01',\n  },\n  {\n    id: 'po-3',\n    sku: 'SKU-GAUGE-12',\n    title: 'Digital Calibration Pressure Gauge 0-600 PSI',\n    orderedQty: 40,\n    receivedQty: 40,\n    rejectedQty: 0,\n    rejectionReason: 'none',\n    lotNumber: 'LOT-CAL-002',\n    expiryDate: '2031-01-15',\n    stagingLocation: 'ZONE-B-RACK-09',\n  },\n])\n\nconst totalOrdered = computed(() => lines.value.reduce((acc, item) => acc + item.orderedQty, 0))\nconst totalAccepted = computed(() => lines.value.reduce((acc, item) => acc + item.receivedQty, 0))\nconst totalRejected = computed(() => lines.value.reduce((acc, item) => acc + item.rejectedQty, 0))\n\nfunction finalizeReceipt() {\n  if (totalRejected.value > 0 || totalAccepted.value < totalOrdered.value) {\n    inspectionStatus.value = 'discrepancy'\n  } else {\n    inspectionStatus.value = 'passed'\n  }\n  isCompleted.value = true\n}\n\nfunction resetReceipt() {\n  isCompleted.value = false\n  inspectionStatus.value = 'pending'\n}\n</script>\n\n<template>\n  <div data-slot=\"purchase-order-receiving\" class=\"w-full space-y-6\">\n    <!-- Top PO Header Info -->\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\">{{ poNumber }}</span>\n            <Badge variant=\"outline\" class=\"font-mono text-xs\">\n              {{ deliveryDocket }}\n            </Badge>\n            <Badge\n              :variant=\"\n                inspectionStatus === 'passed'\n                  ? 'default'\n                  : inspectionStatus === 'discrepancy'\n                    ? 'destructive'\n                    : 'secondary'\n              \"\n              class=\"capitalize\"\n            >\n              {{ isCompleted ? `GRN ${inspectionStatus}` : 'Receiving in Progress' }}\n            </Badge>\n          </div>\n          <CardTitle class=\"text-xl\">Inbound Goods Receipt & QA Inspection</CardTitle>\n          <CardDescription>\n            Supplier: <strong class=\"text-foreground font-medium\">{{ vendorName }}</strong> · Inbound Dock Verification\n          </CardDescription>\n        </div>\n\n        <div class=\"flex items-center gap-2\">\n          <Button variant=\"outline\" size=\"sm\" class=\"gap-1.5\">\n            <Printer class=\"size-4\" />\n            Print Putaway Labels\n          </Button>\n          <Button v-if=\"!isCompleted\" variant=\"default\" size=\"sm\" class=\"gap-1.5\" @click=\"finalizeReceipt\">\n            <PackageCheck class=\"size-4\" />\n            Generate GRN\n          </Button>\n          <Button v-else variant=\"secondary\" size=\"sm\" class=\"gap-1.5\" @click=\"resetReceipt\"> Edit Receipt </Button>\n        </div>\n      </CardHeader>\n\n      <CardContent class=\"border-border grid grid-cols-1 gap-4 border-t pt-4 sm:grid-cols-3\">\n        <!-- Receiving Dock -->\n        <div class=\"border-border space-y-1.5 rounded-lg border p-3\">\n          <div class=\"text-muted-foreground flex items-center gap-1.5 text-xs font-medium\">\n            <Warehouse class=\"size-3.5\" />\n            <span>RECEIVING BAY</span>\n          </div>\n          <Select v-model=\"receivingDock\" :disabled=\"isCompleted\">\n            <SelectTrigger class=\"w-full\">\n              <SelectValue />\n            </SelectTrigger>\n            <SelectContent>\n              <SelectItem value=\"dock-01\">Inbound Dock Bay 01 (Heavy Freight)</SelectItem>\n              <SelectItem value=\"dock-02\">Inbound Dock Bay 02 (Cross-Dock)</SelectItem>\n              <SelectItem value=\"dock-03\">Inbound Dock Bay 03 (Standard Freight)</SelectItem>\n              <SelectItem value=\"dock-04\">Inbound Cold Storage Quarantine Bay</SelectItem>\n            </SelectContent>\n          </Select>\n        </div>\n\n        <!-- Discrepancy Summary -->\n        <div class=\"border-border space-y-1 rounded-lg border p-3\">\n          <div class=\"text-muted-foreground text-xs font-medium\">RECEIPT SUMMARY</div>\n          <div class=\"flex items-baseline justify-between pt-1\">\n            <div class=\"font-mono text-xl font-semibold\">{{ totalAccepted }} / {{ totalOrdered }}</div>\n            <Badge v-if=\"totalRejected > 0\" variant=\"destructive\" class=\"font-mono text-xs\">\n              {{ totalRejected }} Rejected\n            </Badge>\n            <Badge v-else variant=\"outline\" class=\"text-muted-foreground font-mono text-xs\"> 100% Match </Badge>\n          </div>\n        </div>\n\n        <!-- QA Verification Badge -->\n        <div class=\"border-border space-y-1 rounded-lg border p-3\">\n          <div class=\"text-muted-foreground text-xs font-medium\">QA AUDIT DISPOSITION</div>\n          <div class=\"flex items-center gap-2 pt-1\">\n            <ShieldCheck v-if=\"inspectionStatus === 'passed'\" class=\"text-foreground size-5\" />\n            <AlertTriangle v-else-if=\"inspectionStatus === 'discrepancy'\" class=\"text-destructive size-5\" />\n            <Clock v-else class=\"text-muted-foreground size-5\" />\n            <span class=\"text-sm font-medium\">\n              {{\n                inspectionStatus === 'passed'\n                  ? 'All lines cleared for putaway'\n                  : inspectionStatus === 'discrepancy'\n                    ? 'Discrepancy logged for vendor credit'\n                    : 'Awaiting line verification'\n              }}\n            </span>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- PO Line Item Matching Table -->\n    <Card>\n      <CardHeader class=\"pb-3\">\n        <CardTitle class=\"text-base font-semibold\">Purchase Order Line Verification</CardTitle>\n        <CardDescription>\n          Verify quantities received against vendor packing list and assign warehouse staging zones.\n        </CardDescription>\n      </CardHeader>\n\n      <CardContent class=\"p-0\">\n        <Table>\n          <TableHeader>\n            <TableRow>\n              <TableHead class=\"w-[280px]\">Item / Description</TableHead>\n              <TableHead class=\"text-right\">Ordered</TableHead>\n              <TableHead class=\"w-[110px] text-right\">Received</TableHead>\n              <TableHead class=\"w-[110px] text-right\">Rejected</TableHead>\n              <TableHead>Rejection Reason</TableHead>\n              <TableHead>Lot Number</TableHead>\n              <TableHead>Staging Target</TableHead>\n            </TableRow>\n          </TableHeader>\n          <TableBody>\n            <TableRow v-for=\"line in lines\" :key=\"line.id\">\n              <!-- Item Details -->\n              <TableCell>\n                <div class=\"font-medium\">{{ line.title }}</div>\n                <div class=\"text-muted-foreground font-mono text-xs\">{{ line.sku }}</div>\n              </TableCell>\n\n              <!-- Ordered Qty -->\n              <TableCell class=\"text-muted-foreground text-right font-mono text-sm\">\n                {{ line.orderedQty }}\n              </TableCell>\n\n              <!-- Received Qty -->\n              <TableCell class=\"text-right\">\n                <Input\n                  v-model.number=\"line.receivedQty\"\n                  type=\"number\"\n                  min=\"0\"\n                  class=\"h-8 text-right font-mono\"\n                  :disabled=\"isCompleted\"\n                />\n              </TableCell>\n\n              <!-- Rejected Qty -->\n              <TableCell class=\"text-right\">\n                <Input\n                  v-model.number=\"line.rejectedQty\"\n                  type=\"number\"\n                  min=\"0\"\n                  class=\"h-8 text-right font-mono\"\n                  :disabled=\"isCompleted\"\n                />\n              </TableCell>\n\n              <!-- Reason -->\n              <TableCell>\n                <Select v-model=\"line.rejectionReason\" :disabled=\"isCompleted || line.rejectedQty === 0\">\n                  <SelectTrigger class=\"h-8 w-[160px] text-xs\">\n                    <SelectValue />\n                  </SelectTrigger>\n                  <SelectContent>\n                    <SelectItem value=\"none\">None (Accepted)</SelectItem>\n                    <SelectItem value=\"damaged_packaging\">Damaged Packaging</SelectItem>\n                    <SelectItem value=\"expired_lot\">Short Shelf Life</SelectItem>\n                    <SelectItem value=\"wrong_specification\">Incorrect Spec</SelectItem>\n                    <SelectItem value=\"temperature_excursion\">Temp Excursion</SelectItem>\n                  </SelectContent>\n                </Select>\n              </TableCell>\n\n              <!-- Lot Number Input -->\n              <TableCell>\n                <Input\n                  v-model=\"line.lotNumber\"\n                  placeholder=\"Lot #\"\n                  class=\"h-8 w-28 font-mono text-xs\"\n                  :disabled=\"isCompleted\"\n                />\n              </TableCell>\n\n              <!-- Staging Target -->\n              <TableCell>\n                <span class=\"bg-muted text-foreground rounded px-2 py-1 font-mono text-xs font-medium\">\n                  {{ line.stagingLocation }}\n                </span>\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>Official GRN generates supplier debit note automatically for any non-zero rejection.</div>\n        <div class=\"text-foreground font-medium\">\n          Accepted: <span class=\"font-mono font-semibold\">{{ totalAccepted }}</span> units · Rejected:{' '}\n          <span class=\"text-destructive font-mono font-semibold\">{{ totalRejected }}</span> units\n        </div>\n      </CardFooter>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/purchase-order-receiving/PurchaseOrderReceiving.vue"
    },
    {
      "path": "packages/registry-vue/blocks/purchase-order-receiving/index.ts",
      "content": "export { default as PurchaseOrderReceiving } from './PurchaseOrderReceiving.vue'\nexport type { POLineItem, PurchaseOrderReceivingProps } from './PurchaseOrderReceiving.vue'\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/purchase-order-receiving/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/select.json",
    "https://uipkge.dev/r/vue/table.json"
  ],
  "description": "Inbound dock receiving workbench with PO matching, QA discrepancy logging, lot registration, and GRN generation.",
  "categories": [
    "dashboard",
    "data-display"
  ]
}