UIPackage
Menu

Framework

Change language

Boilerplate repo

Vendor Supplier Portal

blockdashboard

Supplier and vendor relationship workbench with SLA scorecard metrics, purchase order status, and contracted pricing catalog.

Also available for Vue ->

Installation

$npx shadcn@latest add https://uipkge.dev/r/react/vendor-supplier-portal.json
Named registry:npx shadcn@latest add @uipkge-react/vendor-supplier-portalInstalls to:components/blocks/vendor-supplier-portal/

Variants

Loading interactive previews…

Props

NameType / ValuesDefaultRequired
vendorNamestringoptional
vendorIdstringoptional
tierstringoptional
classNamestringoptional

Schema

Type aliases exported from this item's source. Use these to shape the data you pass in.

VendorPO
interface VendorPO {
  id: string
  poNumber: string
  issueDate: string
  deliveryDeadline: string
  linesCount: number
  totalAmount: number
  status: 'acknowledged' | 'in_production' | 'shipped' | 'pending_ack'
}
ContractedCatalogItem
interface ContractedCatalogItem {
  id: string
  sku: string
  name: string
  moq: number
  contractedPrice: number
  leadTimeDays: number
  validUntil: string
}

npm dependencies

Files installed (2)

  • components/blocks/vendor-supplier-portal/VendorSupplierPortal.tsx11.7 kB
    'use client'
    
    import * as React from 'react'
    import { Download, FileSpreadsheet, ShieldCheck } from 'lucide-react'
    import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
    import { Button } from '@/components/ui/button'
    import { Badge } from '@/components/ui/badge'
    import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
    
    export interface VendorPO {
      id: string
      poNumber: string
      issueDate: string
      deliveryDeadline: string
      linesCount: number
      totalAmount: number
      status: 'acknowledged' | 'in_production' | 'shipped' | 'pending_ack'
    }
    
    export interface ContractedCatalogItem {
      id: string
      sku: string
      name: string
      moq: number
      contractedPrice: number
      leadTimeDays: number
      validUntil: string
    }
    
    export interface VendorPortalProps {
      vendorName?: string
      vendorId?: string
      tier?: string
      className?: string
    }
    
    export function VendorSupplierPortal({
      vendorName = 'Apex Precision Engineering Ltd',
      vendorId = 'VND-2026-9901',
      tier = 'Strategic Tier-1 Supplier',
      className,
    }: VendorPortalProps) {
      const [activeTab, setActiveTab] = React.useState<'orders' | 'catalog'>('orders')
    
      const [orders, setOrders] = React.useState<VendorPO[]>([
        {
          id: 'po-1',
          poNumber: 'PO-2026-8840',
          issueDate: '2026-08-18',
          deliveryDeadline: '2026-08-28',
          linesCount: 4,
          totalAmount: 48500,
          status: 'in_production',
        },
        {
          id: 'po-2',
          poNumber: 'PO-2026-8855',
          issueDate: '2026-08-22',
          deliveryDeadline: '2026-09-02',
          linesCount: 2,
          totalAmount: 19200,
          status: 'pending_ack',
        },
        {
          id: 'po-3',
          poNumber: 'PO-2026-8812',
          issueDate: '2026-08-10',
          deliveryDeadline: '2026-08-21',
          linesCount: 6,
          totalAmount: 82400,
          status: 'shipped',
        },
      ])
    
      const [catalog] = React.useState<ContractedCatalogItem[]>([
        {
          id: 'cat-1',
          sku: 'SKU-VALVE-99',
          name: 'High-Pressure Hydraulic Valve 3/8"',
          moq: 50,
          contractedPrice: 185.0,
          leadTimeDays: 7,
          validUntil: '2027-06-30',
        },
        {
          id: 'cat-2',
          sku: 'SKU-SEAL-04',
          name: 'Fluorocarbon O-Ring Flange Kit (Pack of 50)',
          moq: 100,
          contractedPrice: 24.5,
          leadTimeDays: 3,
          validUntil: '2027-06-30',
        },
        {
          id: 'cat-3',
          sku: 'SKU-GAUGE-12',
          name: 'Digital Calibration Pressure Gauge 0-600 PSI',
          moq: 20,
          contractedPrice: 420.0,
          leadTimeDays: 14,
          validUntil: '2027-06-30',
        },
      ])
    
      function acknowledgePO(id: string) {
        setOrders((prev) => prev.map((order) => (order.id === id ? { ...order, status: 'acknowledged' as const } : order)))
      }
    
      return (
        <div data-slot="vendor-supplier-portal" className={`w-full space-y-6 ${className ?? ''}`}>
          {/* Header / Supplier SLA Scorecard */}
          <Card>
            <CardHeader className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
              <div className="space-y-1">
                <div className="flex items-center gap-2">
                  <span className="text-foreground font-mono text-sm font-semibold">{vendorId}</span>
                  <Badge variant="outline">{tier}</Badge>
                  <Badge variant="secondary" className="gap-1">
                    <ShieldCheck className="text-foreground size-3" />
                    ISO 9001:2015 Certified
                  </Badge>
                </div>
                <CardTitle className="text-xl">{vendorName}</CardTitle>
                <CardDescription>Supplier SLA Performance Scorecard & Active Purchase Order Console</CardDescription>
              </div>
    
              <div className="flex items-center gap-2">
                <Button variant="outline" size="sm" className="gap-1.5">
                  <FileSpreadsheet className="size-3.5" />
                  Export Statement
                </Button>
                <Button variant="default" size="sm" className="gap-1.5">
                  <Download className="size-3.5" />
                  Download MSA Contract
                </Button>
              </div>
            </CardHeader>
    
            <CardContent className="border-border grid grid-cols-1 gap-4 border-t pt-4 sm:grid-cols-4">
              {/* On Time Delivery */}
              <div className="border-border space-y-1 rounded-lg border p-3">
                <div className="text-muted-foreground text-xs font-medium">ON-TIME DELIVERY (OTD)</div>
                <div className="flex items-baseline justify-between pt-1">
                  <div className="font-mono text-xl font-semibold">98.6%</div>
                  <span className="text-muted-foreground font-mono text-xs">Target: 95.0%</span>
                </div>
              </div>
    
              {/* QA Acceptance */}
              <div className="border-border space-y-1 rounded-lg border p-3">
                <div className="text-muted-foreground text-xs font-medium">QA ACCEPTANCE RATE</div>
                <div className="flex items-baseline justify-between pt-1">
                  <div className="font-mono text-xl font-semibold">99.8%</div>
                  <span className="text-muted-foreground font-mono text-xs">&lt; 0.2% NCR</span>
                </div>
              </div>
    
              {/* Avg Lead Time */}
              <div className="border-border space-y-1 rounded-lg border p-3">
                <div className="text-muted-foreground text-xs font-medium">AVG FULFILLMENT LEAD TIME</div>
                <div className="pt-1 font-mono text-xl font-semibold">5.4 Days</div>
              </div>
    
              {/* Total YTD Volume */}
              <div className="border-border space-y-1 rounded-lg border p-3">
                <div className="text-muted-foreground text-xs font-medium">ACTIVE PURCHASE VOLUME</div>
                <div className="pt-1 font-mono text-xl font-semibold">$150,100 USD</div>
              </div>
            </CardContent>
          </Card>
    
          {/* Navigation Tabs & Content Card */}
          <Card>
            <CardHeader className="flex flex-col gap-3 pb-3 sm:flex-row sm:items-center sm:justify-between">
              <div className="flex items-center gap-2">
                <Button
                  variant={activeTab === 'orders' ? 'default' : 'outline'}
                  size="sm"
                  onClick={() => setActiveTab('orders')}
                >
                  Active Purchase Orders ({orders.length})
                </Button>
                <Button
                  variant={activeTab === 'catalog' ? 'default' : 'outline'}
                  size="sm"
                  onClick={() => setActiveTab('catalog')}
                >
                  Contracted Catalog Prices ({catalog.length})
                </Button>
              </div>
    
              <div className="text-muted-foreground text-xs">
                Payment Terms: <span className="text-foreground font-medium">Net-45 Direct ACH Wire</span>
              </div>
            </CardHeader>
    
            <CardContent className="p-0">
              {/* Table for Orders */}
              {activeTab === 'orders' ? (
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead className="w-[180px]">PO Reference</TableHead>
                      <TableHead>Issue Date</TableHead>
                      <TableHead>Delivery Deadline</TableHead>
                      <TableHead className="text-right">Line Items</TableHead>
                      <TableHead className="text-right">Total Order Value</TableHead>
                      <TableHead>Fulfillment Status</TableHead>
                      <TableHead className="w-[140px] text-right">Action</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {orders.map((order) => (
                      <TableRow key={order.id}>
                        <TableCell>
                          <div className="text-foreground font-mono font-semibold">{order.poNumber}</div>
                        </TableCell>
    
                        <TableCell className="text-muted-foreground font-mono text-xs">{order.issueDate}</TableCell>
    
                        <TableCell className="text-foreground font-mono text-xs font-medium">
                          {order.deliveryDeadline}
                        </TableCell>
    
                        <TableCell className="text-right font-mono text-sm">{order.linesCount} SKUs</TableCell>
    
                        <TableCell className="text-foreground text-right font-mono text-sm font-semibold">
                          ${order.totalAmount.toLocaleString()} USD
                        </TableCell>
    
                        <TableCell>
                          <Badge
                            variant={
                              order.status === 'shipped'
                                ? 'default'
                                : order.status === 'in_production'
                                  ? 'secondary'
                                  : 'outline'
                            }
                            className="capitalize"
                          >
                            {order.status.replace('_', ' ')}
                          </Badge>
                        </TableCell>
    
                        <TableCell className="text-right">
                          {order.status === 'pending_ack' ? (
                            <Button
                              size="sm"
                              variant="default"
                              className="h-7 text-xs"
                              onClick={() => acknowledgePO(order.id)}
                            >
                              Acknowledge PO
                            </Button>
                          ) : (
                            <span className="text-muted-foreground text-xs">Processed</span>
                          )}
                        </TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              ) : (
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead className="w-[280px]">Product / Description</TableHead>
                      <TableHead>SKU Reference</TableHead>
                      <TableHead className="text-right">Min Order Qty (MOQ)</TableHead>
                      <TableHead className="text-right">Contracted Unit Price</TableHead>
                      <TableHead className="text-right">Standard Lead Time</TableHead>
                      <TableHead>Contract Validity</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {catalog.map((item) => (
                      <TableRow key={item.id}>
                        <TableCell>
                          <div className="text-foreground font-medium">{item.name}</div>
                        </TableCell>
    
                        <TableCell>
                          <span className="font-mono text-xs font-semibold">{item.sku}</span>
                        </TableCell>
    
                        <TableCell className="text-right font-mono text-sm">{item.moq} units</TableCell>
    
                        <TableCell className="text-foreground text-right font-mono text-sm font-semibold">
                          ${item.contractedPrice.toFixed(2)}
                        </TableCell>
    
                        <TableCell className="text-muted-foreground text-right font-mono text-sm">
                          {item.leadTimeDays} Days
                        </TableCell>
    
                        <TableCell>
                          <span className="text-muted-foreground font-mono text-xs">Valid to {item.validUntil}</span>
                        </TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              )}
            </CardContent>
    
            <CardFooter className="border-border text-muted-foreground flex items-center justify-between border-t py-3 text-xs">
              <div>Supplier contract SLA terms audited quarterly per ISO 9001 compliance standards.</div>
              <div className="text-foreground font-medium">
                Vendor Status: <span className="text-foreground">Active & In Good Standing</span>
              </div>
            </CardFooter>
          </Card>
        </div>
      )
    }
    
  • components/blocks/vendor-supplier-portal/index.ts0.2 kB

Raw manifest:https://uipkge.dev/r/react/vendor-supplier-portal.json