{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "vendor-supplier-portal",
  "title": "Vendor Supplier Portal",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/vendor-supplier-portal/vendor-supplier-portal.component.ts",
      "content": "import { Component, Input, signal, ChangeDetectionStrategy } from '@angular/core'\nimport { Download, FileSpreadsheet, LucideAngularModule, ShieldCheck } from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent, type BadgeVariant } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport {\n  UiCardComponent,\n  UiCardContentComponent,\n  UiCardDescriptionComponent,\n  UiCardFooterComponent,\n  UiCardHeaderComponent,\n  UiCardTitleComponent,\n} from '@/ui/card/card.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\n\nexport interface VendorPO {\n  id: string\n  poNumber: string\n  issueDate: string\n  deliveryDeadline: string\n  linesCount: number\n  totalAmount: number\n  status: 'acknowledged' | 'in_production' | 'shipped' | 'pending_ack'\n}\n\nexport interface ContractedCatalogItem {\n  id: string\n  sku: string\n  name: string\n  moq: number\n  contractedPrice: number\n  leadTimeDays: number\n  validUntil: string\n}\n\nexport interface VendorPortalProps {\n  vendorName?: string\n  vendorId?: string\n  tier?: string\n  className?: string\n}\n\nexport type VendorPortalTab = 'orders' | 'catalog'\n\n/**\n * Angular port of the React VendorSupplierPortal block: a supplier SLA scorecard with an\n * active purchase order console (acknowledge pending POs) and a contracted catalog price list.\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-vendor-supplier-portal, [ui-vendor-supplier-portal]',\n  standalone: true,\n  host: {\n    '[attr.data-slot]': '\"vendor-supplier-portal\"',\n    '[class]': 'hostClass',\n  },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiCardDescriptionComponent,\n    UiCardFooterComponent,\n    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n  ],\n  template: `\n    <!-- Header / Supplier SLA Scorecard -->\n    <div ui-card>\n      <div ui-card-header 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\">{{ vendorId }}</span>\n            <span ui-badge variant=\"outline\">{{ tier }}</span>\n            <span ui-badge variant=\"secondary\" class=\"gap-1\">\n              <lucide-icon [img]=\"ShieldCheck\" class=\"text-foreground size-3\" />\n              ISO 9001:2015 Certified\n            </span>\n          </div>\n          <h3 ui-card-title class=\"text-xl\">{{ vendorName }}</h3>\n          <p ui-card-description>Supplier SLA Performance Scorecard &amp; Active Purchase Order Console</p>\n        </div>\n\n        <div class=\"flex items-center gap-2\">\n          <button ui-button variant=\"outline\" size=\"sm\" class=\"gap-1.5\">\n            <lucide-icon [img]=\"FileSpreadsheet\" class=\"size-3.5\" />\n            Export Statement\n          </button>\n          <button ui-button variant=\"default\" size=\"sm\" class=\"gap-1.5\">\n            <lucide-icon [img]=\"Download\" class=\"size-3.5\" />\n            Download MSA Contract\n          </button>\n        </div>\n      </div>\n\n      <div ui-card-content class=\"border-border grid grid-cols-1 gap-4 border-t pt-4 sm:grid-cols-4\">\n        <!-- On Time Delivery -->\n        <div class=\"border-border space-y-1 rounded-lg border p-3\">\n          <div class=\"text-muted-foreground text-xs font-medium\">ON-TIME DELIVERY (OTD)</div>\n          <div class=\"flex items-baseline justify-between pt-1\">\n            <div class=\"font-mono text-xl font-semibold\">98.6%</div>\n            <span class=\"text-muted-foreground font-mono text-xs\">Target: 95.0%</span>\n          </div>\n        </div>\n\n        <!-- QA Acceptance -->\n        <div class=\"border-border space-y-1 rounded-lg border p-3\">\n          <div class=\"text-muted-foreground text-xs font-medium\">QA ACCEPTANCE RATE</div>\n          <div class=\"flex items-baseline justify-between pt-1\">\n            <div class=\"font-mono text-xl font-semibold\">99.8%</div>\n            <span class=\"text-muted-foreground font-mono text-xs\">&lt; 0.2% NCR</span>\n          </div>\n        </div>\n\n        <!-- Avg Lead Time -->\n        <div class=\"border-border space-y-1 rounded-lg border p-3\">\n          <div class=\"text-muted-foreground text-xs font-medium\">AVG FULFILLMENT LEAD TIME</div>\n          <div class=\"pt-1 font-mono text-xl font-semibold\">5.4 Days</div>\n        </div>\n\n        <!-- Total YTD Volume -->\n        <div class=\"border-border space-y-1 rounded-lg border p-3\">\n          <div class=\"text-muted-foreground text-xs font-medium\">ACTIVE PURCHASE VOLUME</div>\n          <div class=\"pt-1 font-mono text-xl font-semibold\">$150,100 USD</div>\n        </div>\n      </div>\n    </div>\n\n    <!-- Navigation Tabs & Content Card -->\n    <div ui-card>\n      <div ui-card-header class=\"flex flex-col gap-3 pb-3 sm:flex-row sm:items-center sm:justify-between\">\n        <div class=\"flex items-center gap-2\">\n          <button\n            ui-button\n            [variant]=\"activeTab() === 'orders' ? 'default' : 'outline'\"\n            size=\"sm\"\n            (click)=\"activeTab.set('orders')\"\n          >\n            Active Purchase Orders ({{ orders().length }})\n          </button>\n          <button\n            ui-button\n            [variant]=\"activeTab() === 'catalog' ? 'default' : 'outline'\"\n            size=\"sm\"\n            (click)=\"activeTab.set('catalog')\"\n          >\n            Contracted Catalog Prices ({{ catalog.length }})\n          </button>\n        </div>\n\n        <div class=\"text-muted-foreground text-xs\">\n          Payment Terms: <span class=\"text-foreground font-medium\">Net-45 Direct ACH Wire</span>\n        </div>\n      </div>\n\n      <div ui-card-content class=\"p-0\">\n        <!-- Table for Orders -->\n        @if (activeTab() === 'orders') {\n          <div ui-table>\n            <thead ui-table-header>\n              <tr ui-table-row>\n                <th ui-table-head class=\"w-[180px]\">PO Reference</th>\n                <th ui-table-head>Issue Date</th>\n                <th ui-table-head>Delivery Deadline</th>\n                <th ui-table-head class=\"text-right\">Line Items</th>\n                <th ui-table-head class=\"text-right\">Total Order Value</th>\n                <th ui-table-head>Fulfillment Status</th>\n                <th ui-table-head class=\"w-[140px] text-right\">Action</th>\n              </tr>\n            </thead>\n            <tbody ui-table-body>\n              @for (order of orders(); track order.id) {\n                <tr ui-table-row>\n                  <td ui-table-cell>\n                    <div class=\"text-foreground font-mono font-semibold\">{{ order.poNumber }}</div>\n                  </td>\n\n                  <td ui-table-cell class=\"text-muted-foreground font-mono text-xs\">{{ order.issueDate }}</td>\n\n                  <td ui-table-cell class=\"text-foreground font-mono text-xs font-medium\">\n                    {{ order.deliveryDeadline }}\n                  </td>\n\n                  <td ui-table-cell class=\"text-right font-mono text-sm\">{{ order.linesCount }} SKUs</td>\n\n                  <td ui-table-cell class=\"text-foreground text-right font-mono text-sm font-semibold\">\n                    \\${{ formatAmount(order.totalAmount) }} USD\n                  </td>\n\n                  <td ui-table-cell>\n                    <span ui-badge [variant]=\"statusVariant(order.status)\" class=\"capitalize\">\n                      {{ statusLabel(order.status) }}\n                    </span>\n                  </td>\n\n                  <td ui-table-cell class=\"text-right\">\n                    @if (order.status === 'pending_ack') {\n                      <button\n                        ui-button\n                        size=\"sm\"\n                        variant=\"default\"\n                        class=\"h-7 text-xs\"\n                        (click)=\"acknowledgePO(order.id)\"\n                      >\n                        Acknowledge PO\n                      </button>\n                    } @else {\n                      <span class=\"text-muted-foreground text-xs\">Processed</span>\n                    }\n                  </td>\n                </tr>\n              }\n            </tbody>\n          </div>\n        } @else {\n          <div ui-table>\n            <thead ui-table-header>\n              <tr ui-table-row>\n                <th ui-table-head class=\"w-[280px]\">Product / Description</th>\n                <th ui-table-head>SKU Reference</th>\n                <th ui-table-head class=\"text-right\">Min Order Qty (MOQ)</th>\n                <th ui-table-head class=\"text-right\">Contracted Unit Price</th>\n                <th ui-table-head class=\"text-right\">Standard Lead Time</th>\n                <th ui-table-head>Contract Validity</th>\n              </tr>\n            </thead>\n            <tbody ui-table-body>\n              @for (item of catalog; track item.id) {\n                <tr ui-table-row>\n                  <td ui-table-cell>\n                    <div class=\"text-foreground font-medium\">{{ item.name }}</div>\n                  </td>\n\n                  <td ui-table-cell>\n                    <span class=\"font-mono text-xs font-semibold\">{{ item.sku }}</span>\n                  </td>\n\n                  <td ui-table-cell class=\"text-right font-mono text-sm\">{{ item.moq }} units</td>\n\n                  <td ui-table-cell class=\"text-foreground text-right font-mono text-sm font-semibold\">\n                    \\${{ item.contractedPrice.toFixed(2) }}\n                  </td>\n\n                  <td ui-table-cell class=\"text-muted-foreground text-right font-mono text-sm\">\n                    {{ item.leadTimeDays }} Days\n                  </td>\n\n                  <td ui-table-cell>\n                    <span class=\"text-muted-foreground font-mono text-xs\">Valid to {{ item.validUntil }}</span>\n                  </td>\n                </tr>\n              }\n            </tbody>\n          </div>\n        }\n      </div>\n\n      <div\n        ui-card-footer\n        class=\"border-border text-muted-foreground flex items-center justify-between border-t py-3 text-xs\"\n      >\n        <div>Supplier contract SLA terms audited quarterly per ISO 9001 compliance standards.</div>\n        <div class=\"text-foreground font-medium\">\n          Vendor Status: <span class=\"text-foreground\">Active &amp; In Good Standing</span>\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiVendorSupplierPortalComponent {\n  @Input() vendorName = 'Apex Precision Engineering Ltd'\n  @Input() vendorId = 'VND-2026-9901'\n  @Input() tier = 'Strategic Tier-1 Supplier'\n  @Input('class') className?: string\n\n  protected readonly Download = Download\n  protected readonly FileSpreadsheet = FileSpreadsheet\n  protected readonly ShieldCheck = ShieldCheck\n\n  readonly activeTab = signal<VendorPortalTab>('orders')\n\n  readonly orders = signal<VendorPO[]>([\n    {\n      id: 'po-1',\n      poNumber: 'PO-2026-8840',\n      issueDate: '2026-08-18',\n      deliveryDeadline: '2026-08-28',\n      linesCount: 4,\n      totalAmount: 48500,\n      status: 'in_production',\n    },\n    {\n      id: 'po-2',\n      poNumber: 'PO-2026-8855',\n      issueDate: '2026-08-22',\n      deliveryDeadline: '2026-09-02',\n      linesCount: 2,\n      totalAmount: 19200,\n      status: 'pending_ack',\n    },\n    {\n      id: 'po-3',\n      poNumber: 'PO-2026-8812',\n      issueDate: '2026-08-10',\n      deliveryDeadline: '2026-08-21',\n      linesCount: 6,\n      totalAmount: 82400,\n      status: 'shipped',\n    },\n  ])\n\n  readonly catalog: ContractedCatalogItem[] = [\n    {\n      id: 'cat-1',\n      sku: 'SKU-VALVE-99',\n      name: 'High-Pressure Hydraulic Valve 3/8\"',\n      moq: 50,\n      contractedPrice: 185.0,\n      leadTimeDays: 7,\n      validUntil: '2027-06-30',\n    },\n    {\n      id: 'cat-2',\n      sku: 'SKU-SEAL-04',\n      name: 'Fluorocarbon O-Ring Flange Kit (Pack of 50)',\n      moq: 100,\n      contractedPrice: 24.5,\n      leadTimeDays: 3,\n      validUntil: '2027-06-30',\n    },\n    {\n      id: 'cat-3',\n      sku: 'SKU-GAUGE-12',\n      name: 'Digital Calibration Pressure Gauge 0-600 PSI',\n      moq: 20,\n      contractedPrice: 420.0,\n      leadTimeDays: 14,\n      validUntil: '2027-06-30',\n    },\n  ]\n\n  get hostClass(): string {\n    return cn('block w-full space-y-6', this.className)\n  }\n\n  acknowledgePO(id: string): void {\n    this.orders.update((prev) =>\n      prev.map((order) => (order.id === id ? { ...order, status: 'acknowledged' as const } : order)),\n    )\n  }\n\n  statusVariant(status: VendorPO['status']): BadgeVariant {\n    return status === 'shipped' ? 'default' : status === 'in_production' ? 'secondary' : 'outline'\n  }\n\n  statusLabel(status: VendorPO['status']): string {\n    return status.replace('_', ' ')\n  }\n\n  formatAmount(amount: number): string {\n    return amount.toLocaleString()\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/vendor-supplier-portal/vendor-supplier-portal.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/vendor-supplier-portal/index.ts",
      "content": "export {\n  UiVendorSupplierPortalComponent,\n  type VendorPO,\n  type ContractedCatalogItem,\n  type VendorPortalProps,\n  type VendorPortalTab,\n} from './vendor-supplier-portal.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/vendor-supplier-portal/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/card.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/table.json"
  ],
  "description": "Supplier and vendor relationship workbench with SLA scorecard metrics, purchase order status, and contracted pricing catalog.",
  "categories": [
    "dashboard",
    "data-display"
  ]
}