
3D Extruded Buildings & Urban Footprints
Real-world 3D building extrusions with dynamic sunlight shadows, terrain DEM elevations, and pitch/bearing camera controls.
Enterprise IT hardware, peripherals, and software license provisioning portal for new hires with primary workstation selection, display and peripheral bundles, security keys, cloud SaaS seats, and courier tracking.
Also available for React ->$pnpm dlx shadcn-vue@latest add https://uipkge.dev/r/vue/onboarding-equipment-provisioning.json$npx shadcn-vue@latest add https://uipkge.dev/r/vue/onboarding-equipment-provisioning.json$yarn dlx shadcn-vue@latest add https://uipkge.dev/r/vue/onboarding-equipment-provisioning.json$bunx shadcn-vue@latest add https://uipkge.dev/r/vue/onboarding-equipment-provisioning.jsonnpx shadcn-vue@latest add @uipkge/onboarding-equipment-provisioningInstalls to:app/components/blocks/| Name | Type / Values | Default | Required |
|---|---|---|---|
class | HTMLAttributes['class'] | — | optional |
initialWorkstation | 'macbook''thinkpad' | 'macbook' | optional |
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { computed, ref } from 'vue'
import {
Boxes,
Calendar,
Check,
CheckCircle2,
Circle,
Copy,
DollarSign,
Download,
Laptop,
Layers,
Lock,
Monitor,
Plus,
Send,
ShieldCheck,
Truck,
X,
} from 'lucide-vue-next'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
import { Checkbox } from '@/components/ui/checkbox'
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
import { Separator } from '@/components/ui/separator'
import { cn } from '@/lib/utils'
export type WorkstationChoice = 'macbook' | 'thinkpad'
interface Props {
class?: HTMLAttributes['class']
initialWorkstation?: WorkstationChoice
}
const props = withDefaults(defineProps<Props>(), {
initialWorkstation: 'macbook',
})
const emit = defineEmits<{
(e: 'order-custom'): void
(e: 'export-manifest'): void
}>()
// State
const selectedWorkstation = ref<WorkstationChoice>(props.initialWorkstation)
const includeDisplay = ref(true)
const includeInputBundle = ref(true)
const includeDeskMat = ref(true)
const includeYubikey = ref(true)
const includeHardwareToken = ref(true)
const copiedTracking = ref(false)
const copiedEmpId = ref(false)
const showCustomOrderModal = ref(false)
const customRequestSubmitted = ref(false)
const customItemName = ref('')
const customItemJustification = ref('')
// Costs (Choice A MacBook $3,499 + Studio Display $1,499 + Input Bundle $249 + Desk Mat $49 + YubiKey $75 + Token $49 = $5,420.00)
const WORKSTATION_PRICES: Record<WorkstationChoice, number> = {
macbook: 3499,
thinkpad: 2850,
}
const workstationCost = computed(() => WORKSTATION_PRICES[selectedWorkstation.value])
const displayCost = computed(() => (includeDisplay.value ? 1499 : 0))
const inputBundleCost = computed(() => (includeInputBundle.value ? 249 : 0))
const deskMatCost = computed(() => (includeDeskMat.value ? 49 : 0))
const yubikeyCost = computed(() => (includeYubikey.value ? 75 : 0))
const hardwareTokenCost = computed(() => (includeHardwareToken.value ? 49 : 0))
const peripheralsTotal = computed(() => displayCost.value + inputBundleCost.value + deskMatCost.value)
const securityTotal = computed(() => yubikeyCost.value + hardwareTokenCost.value)
const totalInvestment = computed(() => {
return workstationCost.value + peripheralsTotal.value + securityTotal.value
})
const softwareLicenses = [
{
name: 'GitHub Enterprise',
tier: 'Copilot Enterprise + CodeQL',
seatId: 'GH-ENG-8402',
category: 'Engineering',
status: 'Provisioned',
sso: 'Okta SCIM',
},
{
name: 'Figma Professional',
tier: 'Design System Editor + Dev Mode',
seatId: 'FG-DS-1940',
category: 'Design & UI',
status: 'Provisioned',
sso: 'Okta SCIM',
},
{
name: '1Password Business',
tier: 'Enterprise Vault + Infra Keys',
seatId: '1P-CORP-9921',
category: 'Security',
status: 'Provisioned',
sso: 'MDM Enrolled',
},
{
name: 'Slack Pro',
tier: 'Enterprise Grid (acme-eng)',
seatId: 'SLK-88301',
category: 'Comms',
status: 'Provisioned',
sso: 'SAML 2.0',
},
{
name: 'Datadog APM',
tier: 'Staff Observability & Traces',
seatId: 'DD-APM-4109',
category: 'DevOps',
status: 'Provisioned',
sso: 'Okta SCIM',
},
{
name: 'JetBrains All Products',
tier: 'Ultimate Suite (IntelliJ/CLion/GoLand)',
seatId: 'JB-ALL-7740',
category: 'Engineering',
status: 'Provisioned',
sso: 'Corp Pool',
},
]
const trackingSteps = [
{
title: 'Order Approved',
date: 'Aug 24, 2026',
time: '09:00 AM',
completed: true,
current: false,
},
{
title: 'IT Staged & Imaged',
date: 'Aug 25, 2026',
time: '02:30 PM',
completed: true,
current: false,
},
{
title: 'Shipped via FedEx',
date: 'Aug 26, 2026',
time: '06:15 PM',
completed: true,
current: true,
},
{
title: 'Out for Delivery',
date: 'Aug 28, 2026',
time: 'Est. 08:00 AM',
completed: false,
current: false,
},
{
title: 'Delivered to Home',
date: 'Aug 28, 2026',
time: 'Est. 10:30 AM',
completed: false,
current: false,
},
]
function copyTrackingNumber() {
if (typeof navigator !== 'undefined' && navigator.clipboard) {
navigator.clipboard.writeText('TRK-8492019')
copiedTracking.value = true
setTimeout(() => {
copiedTracking.value = false
}, 2000)
}
}
function copyEmployeeId() {
if (typeof navigator !== 'undefined' && navigator.clipboard) {
navigator.clipboard.writeText('EMP-88291')
copiedEmpId.value = true
setTimeout(() => {
copiedEmpId.value = false
}, 2000)
}
}
function handleExportManifest() {
emit('export-manifest')
}
function handleOpenCustomOrder() {
showCustomOrderModal.value = true
emit('order-custom')
}
function handleCloseCustomOrder() {
showCustomOrderModal.value = false
customRequestSubmitted.value = false
customItemName.value = ''
customItemJustification.value = ''
}
function submitCustomRequest() {
if (customItemName.value.trim()) {
customRequestSubmitted.value = true
setTimeout(() => {
handleCloseCustomOrder()
}, 2000)
}
}
</script>
<template>
<div data-slot="onboarding-equipment-provisioning" :class="cn('w-full space-y-6', props.class)">
<!-- Header Section -->
<div class="border-border bg-card flex flex-col gap-4 rounded-xl border p-5 shadow-xs sm:p-6">
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<!-- Title & Hire Info -->
<div class="space-y-1.5">
<div class="flex flex-wrap items-center gap-2">
<Badge variant="outline" class="gap-1.5 font-mono text-xs">
<Boxes class="text-primary size-3.5" aria-hidden="true" />
IT Asset Provisioning
</Badge>
<!-- Emerald Status Badge -->
<div
class="border-success/20 bg-success/10 text-success inline-flex items-center gap-1.5 rounded-full border px-2.5 py-0.5 text-xs font-medium"
>
<span class="relative flex size-1.5">
<span class="bg-success absolute inline-flex h-full w-full rounded-full opacity-75" />
<span class="bg-success relative inline-flex size-1.5 rounded-full" />
</span>
Hardware Assigned · Shipped via FedEx
</div>
</div>
<h1 class="text-foreground text-xl font-bold tracking-tight sm:text-2xl">
New Hire Hardware & IT Provisioning
</h1>
<!-- New Hire Metadata Line -->
<div class="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs sm:text-sm">
<span class="text-foreground font-semibold">Elena Rostova</span>
<span class="text-muted-foreground hidden sm:inline">•</span>
<span class="text-muted-foreground">Senior Staff Engineer</span>
<span class="text-muted-foreground hidden sm:inline">•</span>
<span class="text-muted-foreground flex items-center gap-1">
<Calendar class="size-3.5" aria-hidden="true" />
Start Date: <strong class="text-foreground font-medium">Sep 01, 2026</strong>
</span>
<span class="text-muted-foreground hidden sm:inline">•</span>
<button
type="button"
class="hover:bg-muted focus-visible:ring-ring border-border bg-muted/40 text-foreground inline-flex min-h-6 items-center gap-1 rounded border px-1.5 py-0.5 font-mono text-xs font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none"
title="Click to copy employee ID"
@click="copyEmployeeId"
>
EMP-88291
<Check v-if="copiedEmpId" class="text-success size-3" aria-hidden="true" />
<Copy v-else class="text-muted-foreground size-3" aria-hidden="true" />
</button>
</div>
</div>
<!-- Action Buttons -->
<div class="flex flex-wrap items-center gap-2 pt-1 lg:pt-0">
<Button
aria-label="Download attachment"
variant="outline"
size="sm"
class="gap-1.5 text-xs shadow-xs"
@click="handleExportManifest"
>
<Download class="size-3.5" aria-hidden="true" />
<span>Export Manifest</span>
</Button>
<Button size="sm" class="gap-1.5 text-xs shadow-xs" @click="handleOpenCustomOrder">
<Plus class="size-3.5" aria-hidden="true" />
<span>Order Custom Hardware</span>
</Button>
</div>
</div>
<!-- Financial & Overview Summary Band -->
<Separator />
<div class="grid grid-cols-2 gap-4 pt-1 sm:grid-cols-4">
<div class="border-border/60 bg-muted/20 rounded-lg border p-3">
<div class="text-muted-foreground flex items-center gap-1.5 text-xs">
<DollarSign class="text-primary size-3.5" aria-hidden="true" />
<span>Total IT Investment</span>
</div>
<p class="text-foreground mt-1 font-mono text-lg font-bold tabular-nums sm:text-xl">
${{ totalInvestment.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) }}
</p>
<p class="text-muted-foreground text-xs">Total Assigned Value</p>
</div>
<div class="border-border/60 bg-muted/20 rounded-lg border p-3">
<div class="text-muted-foreground flex items-center gap-1.5 text-xs">
<Laptop class="text-primary size-3.5" aria-hidden="true" />
<span>Primary Workstation</span>
</div>
<p class="text-foreground mt-1 truncate text-xs font-semibold sm:text-sm">
{{ selectedWorkstation === 'macbook' ? 'MacBook Pro 16" M3 Max' : 'ThinkPad P1 Gen 6 i9' }}
</p>
<p class="text-muted-foreground font-mono text-xs tabular-nums">${{ workstationCost.toFixed(2) }}</p>
</div>
<div class="border-border/60 bg-muted/20 rounded-lg border p-3">
<div class="text-muted-foreground flex items-center gap-1.5 text-xs">
<Layers class="text-primary size-3.5" aria-hidden="true" />
<span>Cloud SaaS Seats</span>
</div>
<p class="text-foreground mt-1 text-xs font-semibold sm:text-sm">6 Enterprise Licenses</p>
<p class="text-success text-xs font-medium">All Provisioned</p>
</div>
<div class="border-border/60 bg-muted/20 rounded-lg border p-3">
<div class="text-muted-foreground flex items-center gap-1.5 text-xs">
<Truck class="text-primary size-3.5" aria-hidden="true" />
<span>FedEx Priority</span>
</div>
<p class="text-foreground mt-1 text-xs font-semibold sm:text-sm">Est. Aug 28, 2026</p>
<p class="text-muted-foreground font-mono text-xs">#TRK-8492019</p>
</div>
</div>
</div>
<!-- 4 IT Provisioning Pillar Cards Grid -->
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
<!-- Pillar 1: Primary Workstation Selection -->
<Card class="border shadow-xs">
<CardHeader class="pb-3">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<div class="bg-primary/10 text-primary rounded-lg p-2">
<Laptop class="size-4" aria-hidden="true" />
</div>
<div>
<CardTitle class="text-base font-semibold">1. Primary Workstation</CardTitle>
<CardDescription>Select standard issue macOS or Linux developer laptop</CardDescription>
</div>
</div>
<Badge variant="outline" class="font-mono text-xs">Pillar 01</Badge>
</div>
</CardHeader>
<CardContent class="space-y-3">
<RadioGroup v-model="selectedWorkstation" class="grid grid-cols-1 gap-3">
<!-- Choice A: MacBook Pro 16" -->
<label
:class="
cn(
'relative flex cursor-pointer flex-col justify-between rounded-lg border p-4 transition-colors',
selectedWorkstation === 'macbook'
? 'border-primary bg-primary/5 ring-primary shadow-xs ring-1'
: 'border-border bg-card hover:bg-muted/40',
)
"
>
<div class="flex flex-wrap items-start justify-between gap-3">
<div class="flex min-w-0 items-start gap-3">
<RadioGroupItem id="ws-macbook" value="macbook" class="mt-1" />
<div class="min-w-0 space-y-1">
<div class="flex flex-wrap items-center gap-2">
<span class="text-foreground text-sm font-bold">
MacBook Pro 16" (M3 Max · 64GB RAM · 1TB SSD)
</span>
<Badge variant="default" class="text-xs">Selected Spec</Badge>
</div>
<p class="text-muted-foreground text-xs leading-relaxed">
Apple M3 Max (16-core CPU, 40-core GPU) • 64GB Unified Memory • 1TB Fast NVMe •
Liquid Retina XDR (Space Black)
</p>
<div class="flex flex-wrap items-center gap-2 pt-1">
<Badge wrap variant="secondary" class="font-mono text-xs">
<ShieldCheck class="text-success mr-1 size-3" aria-hidden="true" />
AppleCare+ Enterprise (3-Year Full Accidental Damage)
</Badge>
</div>
</div>
</div>
<div class="text-right">
<span class="text-foreground font-mono text-sm font-bold tabular-nums">$3,499.00</span>
</div>
</div>
</label>
<!-- Choice B: ThinkPad P1 Gen 6 -->
<label
:class="
cn(
'relative flex cursor-pointer flex-col justify-between rounded-lg border p-4 transition-colors',
selectedWorkstation === 'thinkpad'
? 'border-primary bg-primary/5 ring-primary shadow-xs ring-1'
: 'border-border bg-card hover:bg-muted/40',
)
"
>
<div class="flex flex-wrap items-start justify-between gap-3">
<div class="flex min-w-0 items-start gap-3">
<RadioGroupItem id="ws-thinkpad" value="thinkpad" class="mt-1" />
<div class="min-w-0 space-y-1">
<div class="flex flex-wrap items-center gap-2">
<span class="text-foreground text-sm font-bold">
ThinkPad P1 Gen 6 (Intel i9 · 64GB RAM · Ubuntu Linux)
</span>
<Badge variant="outline" class="text-xs">Linux Spec</Badge>
</div>
<p class="text-muted-foreground text-xs leading-relaxed">
Intel Core i9-13900H • NVIDIA RTX 4080 (12GB) • 64GB DDR5 • 1TB NVMe • 16"
WQXGA OLED • Ubuntu 24.04 LTS
</p>
<div class="flex flex-wrap items-center gap-2 pt-1">
<Badge wrap variant="secondary" class="font-mono text-xs">
<ShieldCheck class="text-success mr-1 size-3" aria-hidden="true" />
Lenovo Premier Support (3-Year Next-Day Onsite)
</Badge>
</div>
</div>
</div>
<div class="text-right">
<span class="text-foreground font-mono text-sm font-bold tabular-nums">$2,850.00</span>
</div>
</div>
</label>
</RadioGroup>
</CardContent>
<CardFooter class="border-border/60 bg-muted/20 flex items-center justify-between border-t py-2.5 text-xs">
<span class="text-muted-foreground">Workstation Subtotal:</span>
<span class="text-foreground font-mono font-bold tabular-nums">${{ workstationCost.toFixed(2) }}</span>
</CardFooter>
</Card>
<!-- Pillar 2: Display & Peripherals -->
<Card class="border shadow-xs">
<CardHeader class="pb-3">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<div class="bg-primary/10 text-primary rounded-lg p-2">
<Monitor class="size-4" aria-hidden="true" />
</div>
<div>
<CardTitle class="text-base font-semibold">2. Display & Peripherals</CardTitle>
<CardDescription>High-resolution retina display and ergonomic peripherals</CardDescription>
</div>
</div>
<Badge variant="outline" class="font-mono text-xs">Pillar 02</Badge>
</div>
</CardHeader>
<CardContent class="space-y-3">
<!-- Item 1: Studio Display -->
<div
:class="
cn(
'border-border flex flex-wrap items-start justify-between gap-3 rounded-lg border p-3.5 transition-colors',
includeDisplay ? 'bg-card' : 'bg-muted/30 opacity-70',
)
"
>
<div class="flex items-start gap-3">
<Checkbox id="periph-display" v-model="includeDisplay" class="mt-0.5" />
<div class="space-y-0.5">
<label for="periph-display" class="text-foreground cursor-pointer text-sm font-semibold">
Studio Display 27" 5K Retina
</label>
<p class="text-muted-foreground text-xs">
5120×2880 Retina • 600 nits • 12MP Center Stage Camera • Studio Mics •
Tilt-adjustable Stand
</p>
<div class="pt-1">
<Badge variant="secondary" class="text-xs">Thunderbolt 3 Host Pass-Through</Badge>
</div>
</div>
</div>
<span class="text-foreground font-mono text-sm font-bold tabular-nums">$1,499.00</span>
</div>
<!-- Item 2: Magic Keyboard & Trackpad -->
<div
:class="
cn(
'border-border flex flex-wrap items-start justify-between gap-3 rounded-lg border p-3.5 transition-colors',
includeInputBundle ? 'bg-card' : 'bg-muted/30 opacity-70',
)
"
>
<div class="flex items-start gap-3">
<Checkbox id="periph-inputs" v-model="includeInputBundle" class="mt-0.5" />
<div class="space-y-0.5">
<label for="periph-inputs" class="text-foreground cursor-pointer text-sm font-semibold">
Magic Keyboard & Trackpad Bundle
</label>
<p class="text-muted-foreground text-xs">
Touch ID Wireless Keyboard • Force Touch Multi-Touch Glass Trackpad • Space Black finish
</p>
<div class="pt-1">
<Badge variant="secondary" class="text-xs">USB-C Braided Woven Cable</Badge>
</div>
</div>
</div>
<span class="text-foreground font-mono text-sm font-bold tabular-nums">$249.00</span>
</div>
<!-- Item 3: Ergonomic Desk Mat -->
<div
:class="
cn(
'border-border flex flex-wrap items-start justify-between gap-3 rounded-lg border p-3.5 transition-colors',
includeDeskMat ? 'bg-card' : 'bg-muted/30 opacity-70',
)
"
>
<div class="flex items-start gap-3">
<Checkbox id="periph-mat" v-model="includeDeskMat" class="mt-0.5" />
<div class="space-y-0.5">
<label for="periph-mat" class="text-foreground cursor-pointer text-sm font-semibold">
Ergonomic Standing Desk Mat
</label>
<p class="text-muted-foreground text-xs">
24" × 36" Anti-fatigue high-density polyurethane core • Contoured active standing terrain
</p>
</div>
</div>
<span class="text-foreground font-mono text-sm font-bold tabular-nums">$49.00</span>
</div>
</CardContent>
<CardFooter class="border-border/60 bg-muted/20 flex items-center justify-between border-t py-2.5 text-xs">
<span class="text-muted-foreground">Peripherals Subtotal:</span>
<span class="text-foreground font-mono font-bold tabular-nums">${{ peripheralsTotal.toFixed(2) }}</span>
</CardFooter>
</Card>
<!-- Pillar 3: Security & Authentication Hardware -->
<Card class="border shadow-xs">
<CardHeader class="pb-3">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<div class="bg-primary/10 text-primary rounded-lg p-2">
<ShieldCheck class="size-4" aria-hidden="true" />
</div>
<div>
<CardTitle class="text-base font-semibold">3. Security & Authentication Hardware</CardTitle>
<CardDescription>Zero-trust physical tokens and cryptographic hardware keys</CardDescription>
</div>
</div>
<Badge variant="outline" class="font-mono text-xs">Pillar 03</Badge>
</div>
</CardHeader>
<CardContent class="space-y-3">
<!-- Item 1: YubiKey 5C NFC -->
<div
:class="
cn(
'border-border flex flex-wrap items-start justify-between gap-3 rounded-lg border p-3.5 transition-colors',
includeYubikey ? 'bg-card' : 'bg-muted/30 opacity-70',
)
"
>
<div class="flex items-start gap-3">
<Checkbox id="sec-yubikey" v-model="includeYubikey" class="mt-0.5" />
<div class="space-y-0.5">
<div class="flex flex-wrap items-center gap-2">
<label for="sec-yubikey" class="text-foreground cursor-pointer text-sm font-semibold">
YubiKey 5C NFC (2-Pack · Primary & Backup)
</label>
<Badge variant="outline" class="font-mono text-xs">FIDO2 / WebAuthn</Badge>
</div>
<p class="text-muted-foreground text-xs">
Dual-key pair for primary keychain and secure home backup • USB-C • Contactless NFC •
IP68 water resistant
</p>
<p class="text-muted-foreground pt-0.5 font-mono text-xs">
Pre-enrolled Serials: <span class="text-foreground font-medium">#YB-90281-A / #YB-90281-B</span>
</p>
</div>
</div>
<span class="text-foreground font-mono text-sm font-bold tabular-nums">$75.00</span>
</div>
<!-- Item 2: Encrypted Hardware Token -->
<div
:class="
cn(
'border-border flex flex-wrap items-start justify-between gap-3 rounded-lg border p-3.5 transition-colors',
includeHardwareToken ? 'bg-card' : 'bg-muted/30 opacity-70',
)
"
>
<div class="flex items-start gap-3">
<Checkbox id="sec-token" v-model="includeHardwareToken" class="mt-0.5" />
<div class="space-y-0.5">
<div class="flex flex-wrap items-center gap-2">
<label for="sec-token" class="text-foreground cursor-pointer text-sm font-semibold">
Encrypted Hardware Token
</label>
<Badge variant="outline" class="font-mono text-xs">FIPS 140-3 Level 3</Badge>
</div>
<p class="text-muted-foreground text-xs">
AES-256 hardware cryptographic security token with PIN pad • Corporate Root CA Certificate
pre-loaded
</p>
<p class="text-muted-foreground pt-0.5 font-mono text-xs">
Device Serial: <span class="text-foreground font-medium">#ET-78392-X</span>
</p>
</div>
</div>
<span class="text-foreground font-mono text-sm font-bold tabular-nums">$49.00</span>
</div>
<!-- Compliance Strip -->
<div
class="border-border/60 bg-muted/20 flex items-center justify-between rounded-lg border px-3 py-2 text-xs"
>
<div class="text-muted-foreground flex items-center gap-1.5">
<Lock class="text-success size-3.5" aria-hidden="true" />
<span>SOC 2 Type II & FedRAMP High compliant hardware assignment</span>
</div>
<span class="text-success font-medium">Enforced</span>
</div>
</CardContent>
<CardFooter class="border-border/60 bg-muted/20 flex items-center justify-between border-t py-2.5 text-xs">
<span class="text-muted-foreground">Security Hardware Subtotal:</span>
<span class="text-foreground font-mono font-bold tabular-nums">${{ securityTotal.toFixed(2) }}</span>
</CardFooter>
</Card>
<!-- Pillar 4: Cloud Software & License Seats -->
<Card class="border shadow-xs">
<CardHeader class="pb-3">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<div class="bg-primary/10 text-primary rounded-lg p-2">
<Layers class="size-4" aria-hidden="true" />
</div>
<div>
<CardTitle class="text-base font-semibold">4. Cloud Software & License Seats</CardTitle>
<CardDescription>6 assigned SaaS enterprise licenses auto-synced via Okta</CardDescription>
</div>
</div>
<Badge variant="outline" class="font-mono text-xs">Pillar 04</Badge>
</div>
</CardHeader>
<CardContent>
<div class="grid grid-cols-1 gap-2.5 sm:grid-cols-2">
<div
v-for="license in softwareLicenses"
:key="license.name"
class="border-border bg-card flex flex-col justify-between rounded-lg border p-3 shadow-xs"
>
<div class="space-y-1">
<div class="flex items-start justify-between gap-1.5">
<span class="text-foreground text-xs font-bold">{{ license.name }}</span>
<div
class="border-success/20 bg-success/10 text-success inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-xs font-medium"
>
<Check class="size-3" aria-hidden="true" />
<span>{{ license.status }}</span>
</div>
</div>
<p class="text-muted-foreground text-xs leading-tight">{{ license.tier }}</p>
</div>
<div class="border-border/60 mt-2 flex items-center justify-between border-t pt-1.5 text-xs">
<span class="text-muted-foreground font-mono text-xs">{{ license.seatId }}</span>
<Badge variant="secondary" class="font-mono text-xs">{{ license.sso }}</Badge>
</div>
</div>
</div>
</CardContent>
<CardFooter class="border-border/60 bg-muted/20 flex items-center justify-between border-t py-2.5 text-xs">
<span class="text-muted-foreground">Software Licensing Cost:</span>
<span class="text-foreground font-mono font-bold tabular-nums">Enterprise Corp Pool ($0.00 Direct)</span>
</CardFooter>
</Card>
</div>
<!-- Shipping & Delivery Tracking Card -->
<Card class="border shadow-xs">
<CardHeader class="pb-3">
<div class="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
<div class="flex items-center gap-2">
<div class="bg-primary/10 text-primary rounded-lg p-2">
<Truck class="size-4" aria-hidden="true" />
</div>
<div>
<CardTitle class="text-base font-semibold">Shipping & Delivery Tracking</CardTitle>
<CardDescription>Direct-to-home courier transit with signature required on delivery</CardDescription>
</div>
</div>
<div class="flex items-center gap-2">
<Badge variant="outline" class="font-mono text-xs">Carrier: FedEx Priority</Badge>
<button
type="button"
class="hover:bg-muted focus-visible:ring-ring border-border bg-muted/40 text-foreground inline-flex min-h-6 items-center gap-1.5 rounded border px-2 py-1 font-mono text-xs font-semibold transition-colors focus-visible:ring-2 focus-visible:outline-none"
title="Click to copy tracking number"
@click="copyTrackingNumber"
>
#TRK-8492019
<Check v-if="copiedTracking" class="text-success size-3" aria-hidden="true" />
<Copy v-else class="text-muted-foreground size-3" aria-hidden="true" />
</button>
</div>
</div>
</CardHeader>
<CardContent class="space-y-6">
<!-- Address & Courier Info Banner -->
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
<div class="border-border bg-muted/20 space-y-1 rounded-lg border p-3.5">
<span class="text-muted-foreground font-mono text-xs font-semibold tracking-wider uppercase">
Shipment Recipient
</span>
<p class="text-foreground text-sm font-bold">Elena Rostova</p>
<p class="text-muted-foreground text-xs">Senior Staff Engineer • Distributed Systems</p>
<p class="text-muted-foreground text-xs">[email protected]</p>
</div>
<div class="border-border bg-muted/20 space-y-1 rounded-lg border p-3.5">
<span class="text-muted-foreground font-mono text-xs font-semibold tracking-wider uppercase">
Destination Address
</span>
<p class="text-foreground text-sm font-bold">4820 Grand Avenue, Apt 14B</p>
<p class="text-muted-foreground text-xs">Seattle, WA 98101-2294</p>
<p class="text-muted-foreground text-xs">Direct In-Person Signature Required</p>
</div>
<div class="border-border bg-muted/20 space-y-1 rounded-lg border p-3.5 sm:col-span-2 lg:col-span-1">
<span class="text-muted-foreground font-mono text-xs font-semibold tracking-wider uppercase">
Estimated Delivery
</span>
<p class="text-foreground text-sm font-bold">Thursday, Aug 28, 2026</p>
<p class="text-success text-xs font-medium">Estimated by 10:30 AM (Morning Delivery)</p>
<p class="text-muted-foreground text-xs">FedEx Express Priority Overnight</p>
</div>
</div>
<!-- 5-Step Progress Stepper -->
<div class="space-y-2 pt-2">
<span class="text-muted-foreground font-mono text-xs font-semibold tracking-wider uppercase">
Logistics Timeline Status
</span>
<div class="grid grid-cols-1 gap-3 sm:grid-cols-5">
<div
v-for="(step, idx) in trackingSteps"
:key="step.title"
:class="
cn(
'border-border flex flex-col justify-between rounded-lg border p-3 transition-colors',
step.current
? 'border-success/40 bg-success/10 ring-success/30 ring-1'
: step.completed
? 'bg-card'
: 'bg-muted/20 opacity-60',
)
"
>
<div class="flex items-center justify-between gap-2">
<span class="text-muted-foreground font-mono text-xs">0{{ idx + 1 }}</span>
<CheckCircle2 v-if="step.completed && !step.current" class="text-success size-4" aria-hidden="true" />
<span v-else-if="step.current" class="relative flex size-2">
<span class="bg-success absolute inline-flex h-full w-full rounded-full opacity-75" />
<span class="bg-success relative inline-flex size-2 rounded-full" />
</span>
<Circle v-else class="text-muted-foreground/50 size-3.5" aria-hidden="true" />
</div>
<div class="mt-2 space-y-0.5">
<p
:class="
cn(
'text-xs font-bold',
step.current
? 'text-success font-bold'
: step.completed
? 'text-foreground'
: 'text-muted-foreground',
)
"
>
{{ step.title }}
</p>
<p class="text-muted-foreground font-mono text-xs">{{ step.date }}</p>
<p class="text-muted-foreground text-xs">{{ step.time }}</p>
</div>
</div>
</div>
</div>
</CardContent>
</Card>
<!-- Custom Hardware Order Modal Dialog -->
<div
v-if="showCustomOrderModal"
class="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4 backdrop-blur-xs"
role="dialog"
aria-modal="true"
aria-labelledby="custom-hardware-title"
>
<div
class="border-border bg-card animate-in fade-in zoom-in-95 w-full max-w-lg space-y-4 rounded-xl border p-6 shadow-xl"
>
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<div class="bg-primary/10 text-primary rounded-lg p-2">
<Laptop class="size-4" aria-hidden="true" />
</div>
<div>
<h2 id="custom-hardware-title" class="text-foreground text-base font-bold">Order Custom Hardware</h2>
<p class="text-muted-foreground text-xs">Request specialized hardware or accessories for Elena Rostova</p>
</div>
</div>
<Button variant="ghost" size="icon" class="size-8" aria-label="Close dialog" @click="handleCloseCustomOrder">
<X class="size-4" aria-hidden="true" />
</Button>
</div>
<Separator />
<div v-if="!customRequestSubmitted" class="space-y-4">
<div class="space-y-1.5">
<label class="text-foreground text-xs font-semibold">Equipment / Item Name</label>
<input
v-model="customItemName"
type="text"
placeholder="e.g. Ergonomic Split Mechanical Keyboard, 4K Webcam, eGPU"
class="border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 w-full rounded-md border px-3 py-2 text-xs shadow-xs outline-none focus-visible:ring-[3px]"
/>
</div>
<div class="space-y-1.5">
<label class="text-foreground text-xs font-semibold">Business Justification</label>
<textarea
v-model="customItemJustification"
rows="3"
placeholder="Provide engineering justification or project requirements..."
class="border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 w-full resize-none rounded-md border px-3 py-2 text-xs shadow-xs outline-none focus-visible:ring-[3px]"
/>
</div>
<div class="border-border bg-muted/20 text-muted-foreground rounded-lg border p-3 text-xs">
<p>
Custom requests are automatically routed to Engineering Management & IT Procurement for budget
sign-off.
</p>
</div>
<div class="flex items-center justify-end gap-2 pt-2">
<Button
aria-label="Close dialog"
variant="outline"
size="sm"
class="text-xs"
@click="handleCloseCustomOrder"
>Cancel</Button
>
<Button size="sm" class="gap-1.5 text-xs" :disabled="!customItemName.trim()" @click="submitCustomRequest">
<Send class="size-3.5" aria-hidden="true" />
<span>Submit Request</span>
</Button>
</div>
</div>
<div v-else class="space-y-3 py-4 text-center">
<div class="bg-success/10 text-success mx-auto flex size-12 items-center justify-center rounded-full">
<CheckCircle2 class="size-6" aria-hidden="true" />
</div>
<h3 class="text-foreground text-sm font-bold">Custom Hardware Request Submitted</h3>
<p class="text-muted-foreground text-xs">
Request for <strong class="text-foreground">{{ customItemName }}</strong> has been forwarded to IT
Procurement.
</p>
</div>
</div>
</div>
</div>
</template>
Raw manifest:https://uipkge.dev/r/vue/onboarding-equipment-provisioning.json