UIPackage
Menu

Framework

Change language

Boilerplate repo

Driver Inspection Checklist

blocklogistics

Commercial vehicle Driver Vehicle Inspection Report (DVIR) pre-trip and post-trip safety audit. Features vehicle odometer & ELD telemetry header, 5 grouped FMCSA safety inspection categories (Brakes & Air Pressure, Tires & Wheels, Lights & Electrical, Engine & Fluids, Emergency Safety Gear) with Pass/Fail/N/A segmented controls, dynamic defect report card with Out-of-Service severity classification, defect notes, photo dropzone, driver CDL certification signature pad, and post-submission compliance receipt.

Also available for React ->

Installation

$npx shadcn-vue@latest add https://uipkge.dev/r/vue/driver-inspection-checklist.json
Named registry:npx shadcn-vue@latest add @uipkge/driver-inspection-checklistInstalls to:app/components/blocks/

Variants

Loading interactive previews…

Props

NameType / ValuesDefaultRequired
initialInspectionType
'pre-trip''post-trip''intermodal'
'pre-trip'optional
initialDefectStatebooleanfalseoptional
initialSubmittedbooleanfalseoptional
vehicleIdstring'Truck #104 · Freightliner Cascadia'optional
trailerIdstring"Trailer #TR-8821 (53' Dry Van)"optional
odometerstring'142optional
driverNamestring'Marcus Vance'optional
driverCdlstring'CA-948201'optional
classHTMLAttributes['class']optional

Schema

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

InspectionItem
interface InspectionItem {
  id: string
  label: string
  spec: string
  status: CheckStatus
  notes?: string
}
InspectionCategory
interface InspectionCategory {
  id: string
  title: string
  description: string
  icon: string
  items: InspectionItem[]
}
DefectPhoto
interface DefectPhoto {
  id: string
  name: string
  size: string
  url?: string
}
DVIRReportData
interface DVIRReportData {
  reportId: string
  vehicleId: string
  trailerId: string
  odometer: string
  inspectionType: InspectionType
  driverName: string
  driverCdl: string
  carrierName: string
  dotNumber: string
  inspectionDate: string
  inspectionTime: string
  location: string
  categories: InspectionCategory[]
  defectSeverity: DefectSeverity
  defectNotes: string
  defectPhotos: DefectPhoto[]
  certified: boolean
  signatureTimestamp: string
}

Files installed (1)

  • app/components/blocks/DriverInspectionChecklist.vue43.9 kB
    <script setup lang="ts">
    import { computed, reactive, ref, watch } from 'vue'
    import type { HTMLAttributes } from 'vue'
    import {
      AlertCircle,
      AlertTriangle,
      Camera,
      Check,
      CheckCircle2,
      Clock,
      Disc,
      Download,
      FileCheck,
      FileText,
      Flame,
      Gauge,
      Layers,
      Lightbulb,
      Minus,
      Printer,
      RotateCcw,
      ShieldAlert,
      ShieldCheck,
      Trash2,
      Truck,
      UploadCloud,
      User,
      Wrench,
      X,
    } from 'lucide-vue-next'
    import { cn } from '@/lib/utils'
    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 { Input } from '@/components/ui/input'
    import { Label } from '@/components/ui/label'
    import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
    import { Separator } from '@/components/ui/separator'
    import { Textarea } from '@/components/ui/textarea'
    
    export type CheckStatus = 'pass' | 'fail' | 'na'
    export type DefectSeverity = 'minor' | 'critical'
    export type InspectionType = 'pre-trip' | 'post-trip' | 'intermodal'
    
    export interface InspectionItem {
      id: string
      label: string
      spec: string
      status: CheckStatus
      notes?: string
    }
    
    export interface InspectionCategory {
      id: string
      title: string
      description: string
      icon: string
      items: InspectionItem[]
    }
    
    export interface DefectPhoto {
      id: string
      name: string
      size: string
      url?: string
    }
    
    export interface DVIRReportData {
      reportId: string
      vehicleId: string
      trailerId: string
      odometer: string
      inspectionType: InspectionType
      driverName: string
      driverCdl: string
      carrierName: string
      dotNumber: string
      inspectionDate: string
      inspectionTime: string
      location: string
      categories: InspectionCategory[]
      defectSeverity: DefectSeverity
      defectNotes: string
      defectPhotos: DefectPhoto[]
      certified: boolean
      signatureTimestamp: string
    }
    
    interface Props {
      initialInspectionType?: InspectionType
      initialDefectState?: boolean
      initialSubmitted?: boolean
      vehicleId?: string
      trailerId?: string
      odometer?: string
      driverName?: string
      driverCdl?: string
      class?: HTMLAttributes['class']
    }
    
    const props = withDefaults(defineProps<Props>(), {
      initialInspectionType: 'pre-trip',
      initialDefectState: false,
      initialSubmitted: false,
      vehicleId: 'Truck #104 · Freightliner Cascadia',
      trailerId: "Trailer #TR-8821 (53' Dry Van)",
      odometer: '142,850 miles',
      driverName: 'Marcus Vance',
      driverCdl: 'CA-948201',
    })
    
    const emits = defineEmits<{
      (e: 'submit', data: DVIRReportData): void
      (e: 'defect-change', defects: InspectionItem[]): void
    }>()
    
    // Core state
    const reportId = ref('DVIR-2026-90412')
    const inspectionType = ref<InspectionType>(props.initialInspectionType)
    const vehicleId = ref(props.vehicleId)
    const trailerId = ref(props.trailerId)
    const odometer = ref(props.odometer)
    const driverName = ref(props.driverName)
    const driverCdl = ref(props.driverCdl)
    const carrierName = ref('Apex Freight Logistics Inc.')
    const dotNumber = ref('USDOT #2940182')
    const inspectionDate = ref('2026-08-21')
    const inspectionTime = ref('06:45 AM EDT')
    const location = ref('Terminal #12 · Ontario Logistics Hub, CA')
    
    // Defect report details
    const defectSeverity = ref<DefectSeverity>(props.initialDefectState ? 'critical' : 'minor')
    const defectNotes = ref(
      props.initialDefectState
        ? 'Air supply line to secondary reservoir exhibits slight pressure drop (down to 105 PSI under load). Audible hiss near tractor-trailer gladhand seal.'
        : '',
    )
    const defectReportedToDesk = ref(true)
    
    const defectPhotos = ref<DefectPhoto[]>(
      props.initialDefectState
        ? [
            { id: 'p1', name: 'gladhand_seal_wear.jpg', size: '2.4 MB' },
            { id: 'p2', name: 'air_pressure_gauge_105psi.png', size: '1.8 MB' },
          ]
        : [],
    )
    
    // Driver Certification
    const certified = ref(true)
    const typedSignature = ref(props.driverName)
    const submitted = ref(props.initialSubmitted)
    
    // Default Inspection Categories
    const categories = reactive<InspectionCategory[]>([
      {
        id: 'brakes',
        title: '1. Brakes & Air Pressure',
        description: 'FMCSA § 393.40 / 393.51 Air Brake System & Lines',
        icon: 'disc',
        items: [
          {
            id: 'brakes-service',
            label: 'Service Brakes & Stopping Response',
            spec: 'Smooth pedal feel, no pulling, stopping within 35 ft at 20 mph',
            status: 'pass',
          },
          {
            id: 'brakes-parking',
            label: 'Parking Brake Mechanism',
            spec: 'Holds fully loaded vehicle against low gear engine torque',
            status: 'pass',
          },
          {
            id: 'brakes-airlines',
            label: 'Air Lines & System Pressure (120 PSI)',
            spec: 'Maintains 120 PSI operating pressure; gladhand seals leak-free',
            status: props.initialDefectState ? 'fail' : 'pass',
          },
          {
            id: 'brakes-drums',
            label: 'Brake Drums, Linings & Slack Adjusters',
            spec: 'Lining thickness > 1/4", no oil/grease contamination on drums',
            status: 'pass',
          },
        ],
      },
      {
        id: 'tires',
        title: '2. Tires, Wheels & Rims',
        description: 'FMCSA § 393.75 Wheel Assemblies & Tread Integrity',
        icon: 'layers',
        items: [
          {
            id: 'tires-tread',
            label: 'Steer & Drive Tire Tread Depth',
            spec: 'Steer tires > 4/32" tread; drive/trailer tires > 2/32" tread',
            status: 'pass',
          },
          {
            id: 'tires-pressure',
            label: 'Tire Pressure & Cold Inflation (100 PSI)',
            spec: 'All 10 dual/steer tires at 100 PSI cold; valve caps sealed',
            status: props.initialDefectState ? 'fail' : 'pass',
          },
          {
            id: 'tires-lugnuts',
            label: 'Lug Nuts & Wheel Rim Fasteners',
            spec: 'All wheel studs present & torqued; no rust trails or rim cracks',
            status: 'pass',
          },
          {
            id: 'tires-hubseals',
            label: 'Wheel Hub Oil Seals & Bearings',
            spec: 'Oil level visible in sight glass; hub seals dry with no leaks',
            status: 'pass',
          },
        ],
      },
      {
        id: 'lights',
        title: '3. Lights & Electrical Systems',
        description: 'FMCSA § 393.9 Lamps, Reflective Devices & Electrical Wiring',
        icon: 'lightbulb',
        items: [
          {
            id: 'lights-headlights',
            label: 'Headlights (Low & High Beams)',
            spec: 'Both sealed beams operable; lenses clean and properly aimed',
            status: 'pass',
          },
          {
            id: 'lights-turnsignals',
            label: 'Turn Signals & 4-Way Hazard Flashers',
            spec: 'Front, cab-side, and rear flashers functional on tractor & trailer',
            status: 'pass',
          },
          {
            id: 'lights-brakelights',
            label: 'Brake Lights & Tail Lights',
            spec: 'Instant illumination upon pedal depression; lenses intact',
            status: 'pass',
          },
          {
            id: 'lights-clearance',
            label: 'Clearance Lights & DOT Reflectors',
            spec: 'Amber front/sides, red rear; DOT-C2 reflective sheeting clean',
            status: 'pass',
          },
        ],
      },
      {
        id: 'engine',
        title: '4. Engine Compartment & Fluids',
        description: 'Powertrain fluids, radiator integrity, belts & steering gear',
        icon: 'wrench',
        items: [
          {
            id: 'engine-oil',
            label: 'Engine Oil Level & Quality',
            spec: 'Dipstick level in safe crosshatch; oil clean without burnt odor',
            status: 'pass',
          },
          {
            id: 'engine-coolant',
            label: 'Engine Coolant & Radiator Core',
            spec: 'Surge tank level at MAX line; radiator cap tight, no hose weeping',
            status: 'pass',
          },
          {
            id: 'engine-powersteering',
            label: 'Power Steering Fluid & Reservoir',
            spec: 'Fluid level within cold fill mark; pump operates without whine',
            status: 'pass',
          },
          {
            id: 'engine-belts',
            label: 'Serpentine Belts & Cooling Hoses',
            spec: 'Belt deflection < 1/2"; no rib fraying, cracks, or soft hoses',
            status: 'pass',
          },
        ],
      },
      {
        id: 'safety',
        title: '5. Emergency & Safety Equipment',
        description: 'FMCSA § 393.95 Emergency Equipment in Commercial Motor Vehicles',
        icon: 'flame',
        items: [
          {
            id: 'safety-extinguisher',
            label: 'Fire Extinguisher (Charged & Tagged)',
            spec: 'Minimum 5 B:C rating; pressure needle in green, annual tag valid',
            status: 'pass',
          },
          {
            id: 'safety-triangles',
            label: 'Reflective Warning Triangles (3 Pack)',
            spec: 'Three bidirectional red reflective triangles present & secured',
            status: 'pass',
          },
          {
            id: 'safety-firstaid',
            label: 'First Aid & Spill Response Kit',
            spec: 'Sealed commercial first aid pack, eye wash, HazMat pads',
            status: 'pass',
          },
          {
            id: 'safety-wipers',
            label: 'Windshield Wipers, Washers & Horn',
            spec: 'Clean sweep without streaks; air horn and electric city horn loud',
            status: 'pass',
          },
        ],
      },
    ])
    
    // Computed tallies
    const allItems = computed(() => categories.flatMap((c) => c.items))
    const totalCount = computed(() => allItems.value.length)
    const passCount = computed(() => allItems.value.filter((i) => i.status === 'pass').length)
    const failCount = computed(() => allItems.value.filter((i) => i.status === 'fail').length)
    const naCount = computed(() => allItems.value.filter((i) => i.status === 'na').length)
    const failedItems = computed(() => allItems.value.filter((i) => i.status === 'fail'))
    const hasDefects = computed(() => failedItems.value.length > 0)
    
    const completionPercentage = computed(() => {
      if (totalCount.value === 0) return 0
      const checked = allItems.value.filter((i) => i.status !== undefined).length
      return Math.round((checked / totalCount.value) * 100)
    })
    
    watch(
      failedItems,
      (newFailed) => {
        emits('defect-change', newFailed)
        if (newFailed.length > 0 && defectNotes.value.trim() === '') {
          defectNotes.value = `Inspection defect recorded for: ${newFailed.map((f) => f.label).join(', ')}. Requires shop evaluation.`
        }
      },
      { deep: true },
    )
    
    function setItemStatus(categoryIndex: number, itemIndex: number, status: CheckStatus) {
      categories[categoryIndex].items[itemIndex].status = status
    }
    
    function setCategoryAll(categoryIndex: number, status: CheckStatus) {
      categories[categoryIndex].items.forEach((item) => {
        item.status = status
      })
    }
    
    function markAllPass() {
      categories.forEach((cat) => {
        cat.items.forEach((item) => {
          item.status = 'pass'
        })
      })
    }
    
    function addMockPhoto() {
      const photoIndex = defectPhotos.value.length + 1
      defectPhotos.value.push({
        id: `photo-${Date.now()}`,
        name: `defect_evidence_0${photoIndex}.jpg`,
        size: `${(Math.random() * 2 + 1).toFixed(1)} MB`,
      })
    }
    
    function removePhoto(id: string) {
      defectPhotos.value = defectPhotos.value.filter((p) => p.id !== id)
    }
    
    function handleSubmit() {
      if (!certified.value || typedSignature.value.trim() === '') return
      submitted.value = true
      emits('submit', {
        reportId: reportId.value,
        vehicleId: vehicleId.value,
        trailerId: trailerId.value,
        odometer: odometer.value,
        inspectionType: inspectionType.value,
        driverName: driverName.value,
        driverCdl: driverCdl.value,
        carrierName: carrierName.value,
        dotNumber: dotNumber.value,
        inspectionDate: inspectionDate.value,
        inspectionTime: inspectionTime.value,
        location: location.value,
        categories: JSON.parse(JSON.stringify(categories)),
        defectSeverity: defectSeverity.value,
        defectNotes: defectNotes.value,
        defectPhotos: [...defectPhotos.value],
        certified: certified.value,
        signatureTimestamp: new Date().toISOString(),
      })
    }
    
    function handleReset() {
      submitted.value = false
      markAllPass()
      defectNotes.value = ''
      defectPhotos.value = []
    }
    </script>
    
    <template>
      <div
        data-slot="driver-inspection-checklist"
        :class="cn('text-foreground mx-auto w-full max-w-5xl space-y-6', props.class)"
      >
        <!-- ================================================================= -->
        <!-- POST-SUBMISSION CONFIRMATION RECEIPT                              -->
        <!-- ================================================================= -->
        <div v-if="submitted" class="space-y-6">
          <Card class="border-border overflow-hidden shadow-xs">
            <div
              :class="[
                'border-b p-6 text-center sm:p-8',
                hasDefects ? 'border-warning/30 bg-warning/10' : 'border-success/30 bg-success/10',
              ]"
            >
              <div class="relative mx-auto mb-4 size-16">
                <span
                  :class="['absolute inset-0 rounded-full blur-xl', hasDefects ? 'bg-warning/30' : 'bg-success/30']"
                  aria-hidden="true"
                />
                <span
                  :class="[
                    'relative flex size-16 items-center justify-center rounded-full border shadow-xs',
                    hasDefects
                      ? 'border-warning/40 bg-warning/20 text-warning'
                      : 'border-success/40 bg-success/20 text-success',
                  ]"
                >
                  <ShieldAlert v-if="hasDefects" class="size-8" aria-hidden="true" />
                  <CheckCircle2 v-else class="size-8" aria-hidden="true" />
                </span>
              </div>
    
              <Badge
                :variant="hasDefects ? 'destructive' : 'outline'"
                :class="[
                  'mb-2 font-mono text-xs tracking-wider uppercase',
                  !hasDefects && 'border-success/30 bg-success/10 text-success',
                ]"
              >
                FMCSA § 396.11 Certified Electronic DVIR
              </Badge>
    
              <h2 class="text-foreground text-2xl font-bold tracking-tight sm:text-3xl">
                {{ hasDefects ? 'DVIR Transmitted · Defect Action Required' : 'DVIR Certified · Ready for Dispatch' }}
              </h2>
              <p class="text-muted-foreground mx-auto mt-1.5 max-w-xl text-xs sm:text-sm">
                {{
                  hasDefects
                    ? 'Inspection report logged with safety defects. Maintenance dispatch notification has been dispatched to the terminal garage desk.'
                    : 'Commercial motor vehicle safety inspection verified with zero safety defects. Safe to operate under FMCSA regulations.'
                }}
              </p>
    
              <div
                class="border-border bg-background/80 mt-4 inline-flex flex-wrap items-center gap-2 rounded-full border px-3.5 py-1 text-xs backdrop-blur-xs"
              >
                <span class="text-muted-foreground font-medium">Compliance Document Ref:</span>
                <span class="text-foreground font-mono font-bold">{{ reportId }}</span>
              </div>
            </div>
    
            <CardContent class="space-y-6 p-6">
              <!-- Key Inspection Meta Grid -->
              <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
                <div class="border-border bg-muted/20 rounded-lg border p-3">
                  <span class="text-muted-foreground block text-xs font-medium">Vehicle / Tractor</span>
                  <span class="text-foreground mt-0.5 block text-sm font-semibold">{{ vehicleId }}</span>
                  <span class="text-muted-foreground text-xs">{{ odometer }}</span>
                </div>
                <div class="border-border bg-muted/20 rounded-lg border p-3">
                  <span class="text-muted-foreground block text-xs font-medium">Associated Trailer</span>
                  <span class="text-foreground mt-0.5 block text-sm font-semibold">{{ trailerId }}</span>
                  <span class="text-muted-foreground text-xs">Type: 53-ft Dry Van</span>
                </div>
                <div class="border-border bg-muted/20 rounded-lg border p-3">
                  <span class="text-muted-foreground block text-xs font-medium">Certified Driver</span>
                  <span class="text-foreground mt-0.5 block text-sm font-semibold">{{ driverName }}</span>
                  <span class="text-muted-foreground font-mono text-xs">CDL #{{ driverCdl }}</span>
                </div>
                <div class="border-border bg-muted/20 rounded-lg border p-3">
                  <span class="text-muted-foreground block text-xs font-medium">Timestamp & Hub</span>
                  <span class="text-foreground mt-0.5 block text-sm font-semibold"
                    >{{ inspectionDate }} · {{ inspectionTime }}</span
                  >
                  <span class="text-muted-foreground block truncate text-xs">{{ location }}</span>
                </div>
              </div>
    
              <!-- Audit Result Stats Strip -->
              <div class="border-border bg-card flex flex-wrap items-center justify-between gap-3 rounded-lg border p-4">
                <div class="flex flex-wrap items-center gap-x-6 gap-y-3">
                  <div>
                    <span class="text-muted-foreground block text-xs">Items Inspected</span>
                    <span class="text-foreground text-lg font-bold tabular-nums">{{ totalCount }} / {{ totalCount }}</span>
                  </div>
                  <Separator orientation="vertical" class="h-8" />
                  <div>
                    <span class="text-muted-foreground block text-xs">Passed</span>
                    <span class="text-success text-success text-lg font-bold tabular-nums">{{ passCount }}</span>
                  </div>
                  <Separator orientation="vertical" class="h-8" />
                  <div>
                    <span class="text-muted-foreground block text-xs">Failed / Defects</span>
                    <span
                      :class="[
                        'text-lg font-bold tabular-nums',
                        failCount > 0 ? 'text-destructive' : 'text-muted-foreground',
                      ]"
                    >
                      {{ failCount }}
                    </span>
                  </div>
                  <Separator orientation="vertical" class="h-8" />
                  <div>
                    <span class="text-muted-foreground block text-xs">N/A</span>
                    <span class="text-muted-foreground text-lg font-bold tabular-nums">{{ naCount }}</span>
                  </div>
                </div>
    
                <Badge :variant="hasDefects ? 'destructive' : 'outline'" class="gap-1.5 px-3 py-1 text-xs">
                  <CheckCircle2 v-if="!hasDefects" class="size-3.5" />
                  <AlertTriangle v-else class="size-3.5" />
                  {{ hasDefects ? `Defects Found (${failCount})` : 'All Systems Verified' }}
                </Badge>
              </div>
    
              <!-- Digital Signature Receipt Box -->
              <div class="border-border bg-muted/15 space-y-2 rounded-xl border p-4">
                <div class="flex items-center justify-between">
                  <span class="text-muted-foreground flex items-center gap-1.5 text-xs font-medium">
                    <ShieldCheck class="text-primary size-3.5" />
                    Electronic Cryptographic Driver Signature
                  </span>
                  <span class="text-muted-foreground font-mono text-xs">DOT § 396.11 Certified</span>
                </div>
                <div class="border-border/60 border-b pt-1 pb-3">
                  <p class="text-primary text-2xl font-medium tracking-wide italic">
                    {{ typedSignature || driverName }}
                  </p>
                </div>
                <div class="text-muted-foreground flex flex-wrap items-center justify-between gap-2 font-mono text-xs">
                  <span>Signer: {{ driverName }} · CDL #{{ driverCdl }}</span>
                  <span>SHA-256: 8f9b7c2d-9482-41e9-b631-{{ reportId }}</span>
                </div>
              </div>
    
              <!-- Actions -->
              <div class="flex flex-wrap items-center justify-between gap-3 pt-2">
                <Button variant="outline" size="sm" class="gap-1.5 text-xs font-medium" @click="handleReset">
                  <RotateCcw class="size-3.5" />
                  Start New Inspection
                </Button>
    
                <div class="flex flex-wrap items-center gap-2">
                  <Button variant="outline" size="sm" class="gap-1.5 text-xs font-medium">
                    <Printer class="size-3.5" />
                    Print Driver Copy
                  </Button>
                  <Button aria-label="Download attachment" size="sm" class="gap-1.5 text-xs font-medium">
                    <Download class="size-3.5" />
                    Download Certified DVIR PDF
                  </Button>
                </div>
              </div>
            </CardContent>
          </Card>
        </div>
    
        <!-- ================================================================= -->
        <!-- ACTIVE INSPECTION WORKFLOW                                        -->
        <!-- ================================================================= -->
        <div v-else class="space-y-6">
          <!-- Top Inspection Header Card -->
          <Card class="border-border shadow-xs">
            <CardHeader class="pb-4">
              <div class="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
                <div class="min-w-0 space-y-1.5">
                  <div class="flex flex-wrap items-center gap-2">
                    <Badge
                      variant="outline"
                      class="border-primary/30 bg-primary/10 text-primary gap-1.5 py-0.5 text-xs font-medium"
                    >
                      <Truck class="size-3.5" aria-hidden="true" />
                      FMCSA § 396.11 Audit
                    </Badge>
    
                    <!-- Status Badge -->
                    <Badge v-if="hasDefects" variant="destructive" class="animate-pulse gap-1.5 py-0.5 text-xs font-medium">
                      <AlertTriangle class="size-3.5" aria-hidden="true" />
                      Defects Found · {{ failCount }} {{ failCount === 1 ? 'Item' : 'Items' }} Failed
                    </Badge>
                    <Badge
                      v-else
                      variant="outline"
                      class="border-warning/40 bg-warning/10 text-warning gap-1.5 py-0.5 text-xs font-medium"
                    >
                      <Clock class="size-3.5" aria-hidden="true" />
                      Inspection In Progress
                    </Badge>
                  </div>
    
                  <CardTitle class="text-xl font-bold tracking-tight sm:text-2xl">
                    Driver Vehicle Inspection Report (DVIR)
                  </CardTitle>
                  <CardDescription class="text-xs sm:text-sm">
                    Mandatory pre-trip and post-trip commercial motor vehicle safety certification and defect tracking
                    portal.
                  </CardDescription>
                </div>
    
                <!-- Header Quick Action CTA -->
                <div class="flex flex-wrap items-center gap-2">
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    class="gap-1.5 text-xs font-medium"
                    @click="markAllPass"
                  >
                    <CheckCircle2 class="text-success size-3.5" aria-hidden="true" />
                    Quick Pass All
                  </Button>
                  <Button
                    type="button"
                    size="sm"
                    class="gap-1.5 text-xs font-medium"
                    :disabled="!certified || typedSignature.trim() === ''"
                    @click="handleSubmit"
                  >
                    <FileCheck class="size-3.5" aria-hidden="true" />
                    Submit Completed DVIR
                  </Button>
                </div>
              </div>
            </CardHeader>
    
            <!-- Vehicle Telemetry & Inspection Metadata Bar -->
            <CardContent class="pt-0 pb-5">
              <div class="border-border bg-muted/20 grid gap-3 rounded-lg border p-4 sm:grid-cols-2 lg:grid-cols-4">
                <!-- Vehicle ID -->
                <div class="space-y-1">
                  <div class="text-muted-foreground flex items-center gap-1.5 text-xs font-medium">
                    <Truck class="text-primary size-3.5" />
                    <span>Vehicle / Unit Number</span>
                  </div>
                  <div class="text-foreground text-xs font-semibold">{{ vehicleId }}</div>
                  <div class="text-muted-foreground text-xs">Trailer: {{ trailerId }}</div>
                </div>
    
                <!-- Odometer -->
                <div class="space-y-1">
                  <div class="text-muted-foreground flex items-center gap-1.5 text-xs font-medium">
                    <Gauge class="text-primary size-3.5" />
                    <span>Odometer Mileage</span>
                  </div>
                  <div class="text-foreground text-xs font-semibold tabular-nums">{{ odometer }}</div>
                  <div class="text-muted-foreground text-xs">ECM Telemetry Synced</div>
                </div>
    
                <!-- Inspection Type Selector -->
                <div class="space-y-1">
                  <div class="text-muted-foreground flex items-center gap-1.5 text-xs font-medium">
                    <FileText class="text-primary size-3.5" />
                    <span>Inspection Type</span>
                  </div>
                  <Select v-model="inspectionType">
                    <SelectTrigger class="h-7 text-xs font-medium">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="pre-trip">Pre-Trip Safety Inspection</SelectItem>
                      <SelectItem value="post-trip">Post-Trip Safety Audit</SelectItem>
                      <SelectItem value="intermodal">Intermodal Chassis Inspection</SelectItem>
                    </SelectContent>
                  </Select>
                </div>
    
                <!-- Driver & Terminal Info -->
                <div class="space-y-1">
                  <div class="text-muted-foreground flex items-center gap-1.5 text-xs font-medium">
                    <User class="text-primary size-3.5" />
                    <span>Driver & Terminal</span>
                  </div>
                  <div class="text-foreground text-xs font-semibold">{{ driverName }} · CDL #{{ driverCdl }}</div>
                  <div class="text-muted-foreground truncate text-xs">{{ location }}</div>
                </div>
              </div>
    
              <!-- Progress bar -->
              <div class="mt-4 space-y-1.5">
                <div class="text-muted-foreground flex items-center justify-between text-xs">
                  <span>Audit Completion Progress</span>
                  <span class="text-foreground font-mono font-medium tabular-nums">
                    {{ passCount }} Pass · {{ failCount }} Fail · {{ naCount }} N/A ({{ totalCount }} Total)
                  </span>
                </div>
                <div class="bg-muted h-1.5 w-full overflow-hidden rounded-full">
                  <div
                    class="h-full transition-[width] duration-300"
                    :class="hasDefects ? 'bg-warning' : 'bg-primary'"
                    :style="{ width: `${completionPercentage}%` }"
                  />
                </div>
              </div>
            </CardContent>
          </Card>
    
          <!-- =============================================================== -->
          <!-- 5 FMCSA INSPECTION CATEGORIES                                   -->
          <!-- =============================================================== -->
          <div class="space-y-4">
            <Card
              v-for="(category, catIndex) in categories"
              :key="category.id"
              class="border-border overflow-hidden shadow-xs"
            >
              <CardHeader class="bg-muted/15 border-border border-b px-5 py-3.5">
                <div class="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                  <div class="flex flex-wrap items-center gap-2.5">
                    <div
                      class="border-primary/20 bg-primary/10 text-primary flex size-8 shrink-0 items-center justify-center rounded-md border"
                    >
                      <Disc v-if="category.icon === 'disc'" class="size-4" />
                      <Layers v-else-if="category.icon === 'layers'" class="size-4" />
                      <Lightbulb v-else-if="category.icon === 'lightbulb'" class="size-4" />
                      <Wrench v-else-if="category.icon === 'wrench'" class="size-4" />
                      <Flame v-else class="size-4" />
                    </div>
                    <div>
                      <CardTitle class="text-sm font-bold tracking-tight sm:text-base">
                        {{ category.title }}
                      </CardTitle>
                      <CardDescription class="text-xs">
                        {{ category.description }}
                      </CardDescription>
                    </div>
                  </div>
    
                  <!-- Quick category batch controls -->
                  <div class="flex flex-wrap items-center gap-2 self-end sm:self-auto">
                    <Button
                      type="button"
                      variant="ghost"
                      size="sm"
                      class="text-muted-foreground hover:text-foreground h-7 text-xs"
                      @click="setCategoryAll(catIndex, 'pass')"
                    >
                      Pass All
                    </Button>
                    <Button
                      type="button"
                      variant="ghost"
                      size="sm"
                      class="text-muted-foreground hover:text-foreground h-7 text-xs"
                      @click="setCategoryAll(catIndex, 'na')"
                    >
                      N/A All
                    </Button>
                  </div>
                </div>
              </CardHeader>
    
              <CardContent class="divide-border divide-y p-0">
                <div
                  v-for="(item, itemIndex) in category.items"
                  :key="item.id"
                  :class="[
                    'flex flex-col gap-3 p-4 transition-colors sm:flex-row sm:items-center sm:justify-between',
                    item.status === 'fail' ? 'bg-destructive/5' : 'hover:bg-muted/30',
                  ]"
                >
                  <!-- Item Details -->
                  <div class="min-w-0 space-y-1 pr-2">
                    <div class="flex flex-wrap items-center gap-2">
                      <span class="text-foreground text-xs font-semibold sm:text-sm">
                        {{ item.label }}
                      </span>
                      <Badge
                        v-if="item.status === 'fail'"
                        variant="destructive"
                        class="h-4 py-0 font-mono text-xs uppercase"
                      >
                        Defect
                      </Badge>
                    </div>
                    <p class="text-muted-foreground text-xs leading-relaxed">
                      {{ item.spec }}
                    </p>
                  </div>
    
                  <!-- Segmented Pass / Fail / N/A Toggle Buttons -->
                  <div class="flex shrink-0 items-center gap-1 self-start sm:self-center">
                    <!-- Pass Button -->
                    <button
                      type="button"
                      :aria-label="`Mark ${item.label} as Pass`"
                      :class="[
                        'focus-visible:ring-ring inline-flex cursor-pointer items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium shadow-xs transition-colors outline-none focus-visible:ring-2',
                        item.status === 'pass'
                          ? 'border-success/40 bg-success/15 text-success font-semibold'
                          : 'border-border bg-background text-muted-foreground hover:bg-muted hover:text-foreground',
                      ]"
                      @click="setItemStatus(catIndex, itemIndex, 'pass')"
                    >
                      <Check class="size-3.5" aria-hidden="true" />
                      Pass
                    </button>
    
                    <!-- Fail Button -->
                    <button
                      type="button"
                      :aria-label="`Mark ${item.label} as Fail`"
                      :class="[
                        'focus-visible:ring-ring inline-flex cursor-pointer items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium shadow-xs transition-colors outline-none focus-visible:ring-2',
                        item.status === 'fail'
                          ? 'border-destructive/40 bg-destructive/15 text-destructive font-semibold'
                          : 'border-border bg-background text-muted-foreground hover:bg-muted hover:text-foreground',
                      ]"
                      @click="setItemStatus(catIndex, itemIndex, 'fail')"
                    >
                      <X class="size-3.5" aria-hidden="true" />
                      Fail
                    </button>
    
                    <!-- N/A Button -->
                    <button
                      type="button"
                      :aria-label="`Mark ${item.label} as Not Applicable`"
                      :class="[
                        'focus-visible:ring-ring inline-flex cursor-pointer items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium shadow-xs transition-colors outline-none focus-visible:ring-2',
                        item.status === 'na'
                          ? 'border-border bg-muted text-foreground font-semibold'
                          : 'border-border bg-background text-muted-foreground hover:bg-muted hover:text-foreground',
                      ]"
                      @click="setItemStatus(catIndex, itemIndex, 'na')"
                    >
                      <Minus class="size-3.5" aria-hidden="true" />
                      N/A
                    </button>
                  </div>
                </div>
              </CardContent>
            </Card>
          </div>
    
          <!-- =============================================================== -->
          <!-- DYNAMIC DEFECT REPORT CARD (Appears when any item is marked Fail) -->
          <!-- =============================================================== -->
          <Card
            v-if="hasDefects"
            class="border-destructive/40 bg-destructive/5 dark:bg-destructive/10 overflow-hidden shadow-xs transition-colors duration-200"
          >
            <CardHeader class="border-destructive/20 bg-destructive/10 border-b pb-4">
              <div class="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                <div class="flex flex-wrap items-center gap-2.5">
                  <div
                    class="bg-destructive/20 text-destructive flex size-8 shrink-0 items-center justify-center rounded-md"
                  >
                    <AlertTriangle class="size-4.5" aria-hidden="true" />
                  </div>
                  <div>
                    <CardTitle class="text-destructive text-base font-bold">
                      Critical Defect Log & Repair Dispatch Form
                    </CardTitle>
                    <CardDescription class="text-destructive/80 text-xs">
                      {{ failCount }} item(s) flagged with safety defects requiring mechanic sign-off under FMCSA § 396.13.
                    </CardDescription>
                  </div>
                </div>
    
                <Badge variant="destructive" class="font-mono text-xs uppercase"> Action Required </Badge>
              </div>
            </CardHeader>
    
            <CardContent class="space-y-4 p-5">
              <!-- Flagged Failed Items Chips -->
              <div class="space-y-1.5">
                <Label class="text-foreground text-xs font-semibold">Defective Components Identified</Label>
                <div class="flex flex-wrap gap-2">
                  <span
                    v-for="item in failedItems"
                    :key="item.id"
                    class="border-destructive/30 bg-destructive/10 text-destructive inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium"
                  >
                    <AlertCircle class="size-3.5 shrink-0" />
                    {{ item.label }}
                  </span>
                </div>
              </div>
    
              <!-- Defect Severity Selector -->
              <div class="grid gap-4 sm:grid-cols-2">
                <div class="min-w-0 space-y-1.5">
                  <Label for="defect-severity" class="text-xs font-semibold">Defect Severity Classification *</Label>
                  <Select v-model="defectSeverity">
                    <SelectTrigger id="defect-severity" class="h-9 w-full min-w-0 text-xs [&>span]:truncate">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="minor"> Minor Defect — Safe to operate; scheduled for terminal shop </SelectItem>
                      <SelectItem value="critical">
                        Out-of-Service (OOS) Critical — Dispatch prohibited until repaired
                      </SelectItem>
                    </SelectContent>
                  </Select>
                </div>
    
                <div class="space-y-1.5">
                  <Label class="text-xs font-semibold">Fleet Maintenance Desk Dispatch</Label>
                  <div class="border-border bg-card flex flex-wrap items-center gap-2 rounded-md border p-2 text-xs">
                    <Checkbox id="desk-notify" v-model="defectReportedToDesk" />
                    <Label for="desk-notify" class="cursor-pointer text-xs font-normal">
                      Auto-create Priority Work Order in Garage Portal (Ticket #WO-8910)
                    </Label>
                  </div>
                </div>
              </div>
    
              <!-- Defect Notes Textarea -->
              <div class="space-y-1.5">
                <Label for="defect-notes" class="text-xs font-semibold">Detailed Defect Description & Driver Notes *</Label>
                <Textarea
                  id="defect-notes"
                  v-model="defectNotes"
                  :rows="3"
                  placeholder="Describe exact defect location, leak sounds, tire damage, PSI measurements, or electrical malfunction..."
                  class="text-xs"
                />
              </div>
    
              <!-- Photo Attachment Dropzone Placeholder -->
              <div class="space-y-2">
                <div class="flex items-center justify-between">
                  <Label class="flex items-center gap-1.5 text-xs font-semibold">
                    <Camera class="text-primary size-3.5" />
                    Defect Photographic Evidence
                  </Label>
                  <span class="text-muted-foreground text-xs">JPG, PNG up to 15MB</span>
                </div>
    
                <!-- Upload dropzone box -->
                <div
                  class="border-border/80 hover:border-primary/50 bg-card cursor-pointer rounded-xl border-2 border-dashed p-4 text-center transition-colors"
                  @click="addMockPhoto"
                >
                  <div class="flex flex-col items-center justify-center gap-1.5 py-2">
                    <div class="bg-primary/10 text-primary flex size-9 items-center justify-center rounded-full">
                      <UploadCloud class="size-4.5" />
                    </div>
                    <p class="text-foreground text-xs font-medium">Click to attach photo or drag and drop image here</p>
                    <p class="text-muted-foreground text-xs">
                      Capture close-ups of damaged tires, fluid puddles, broken lights, or air fittings
                    </p>
                  </div>
                </div>
    
                <!-- List of Attached Photos -->
                <div v-if="defectPhotos.length > 0" class="grid gap-2 sm:grid-cols-2">
                  <div
                    v-for="photo in defectPhotos"
                    :key="photo.id"
                    class="border-border bg-card flex items-center justify-between rounded-lg border px-3 py-2 text-xs"
                  >
                    <div class="flex flex-wrap items-center gap-2 truncate">
                      <Camera class="text-primary size-3.5 shrink-0" />
                      <span class="text-foreground truncate font-medium">{{ photo.name }}</span>
                      <span class="text-muted-foreground text-xs">({{ photo.size }})</span>
                    </div>
                    <button
                      type="button"
                      aria-label="Remove photo"
                      class="text-muted-foreground hover:text-destructive cursor-pointer rounded-sm p-1 transition-colors"
                      @click="removePhoto(photo.id)"
                    >
                      <Trash2 class="size-3.5" />
                    </button>
                  </div>
                </div>
              </div>
            </CardContent>
          </Card>
    
          <!-- =============================================================== -->
          <!-- DRIVER CERTIFICATION & SIGNATURE                                -->
          <!-- =============================================================== -->
          <Card class="border-border shadow-xs">
            <CardHeader class="pb-3">
              <div class="flex items-center justify-between">
                <div class="flex flex-wrap items-center gap-2">
                  <ShieldCheck class="text-primary size-4" />
                  <CardTitle class="text-base font-bold"> Driver Safety Certification & Electronic Signature </CardTitle>
                </div>
                <Badge variant="outline" class="text-primary border-primary/30 font-mono text-xs">
                  FMCSA § 396.11(a)
                </Badge>
              </div>
              <CardDescription class="text-xs">
                Commercial motor vehicle driver must certify that all required items have been inspected and all known
                defects disclosed.
              </CardDescription>
            </CardHeader>
    
            <CardContent class="space-y-4">
              <!-- Legal Acknowledgement Checkbox -->
              <div class="border-border bg-muted/20 rounded-lg border p-3.5">
                <div class="flex items-start gap-3">
                  <Checkbox id="cert-check" v-model="certified" class="mt-0.5" />
                  <div class="space-y-1">
                    <Label for="cert-check" class="text-foreground cursor-pointer text-xs leading-relaxed font-semibold">
                      I certify that I have conducted a thorough safety inspection of this vehicle and trailer in compliance
                      with Federal Motor Carrier Safety Regulations.
                    </Label>
                    <p class="text-muted-foreground text-xs leading-relaxed">
                      All components listed above have been checked. Any conditions likely to affect the safe operation of
                      this vehicle or result in mechanical breakdown have been truthfully recorded.
                    </p>
                  </div>
                </div>
              </div>
    
              <!-- Driver Signature Fields -->
              <div class="grid gap-3 sm:grid-cols-3">
                <div class="space-y-1.5 sm:col-span-2">
                  <Label for="driver-sig" class="text-xs font-semibold"
                    >Type Full Legal Name as Electronic Signature *</Label
                  >
                  <Input id="driver-sig" v-model="typedSignature" placeholder="Marcus Vance" size="small" />
                </div>
                <div class="space-y-1.5">
                  <Label class="text-xs font-semibold">Inspection Timestamp</Label>
                  <div
                    class="border-border bg-muted/30 text-muted-foreground flex h-8 items-center rounded-md border px-3 font-mono text-xs"
                  >
                    {{ inspectionDate }} · {{ inspectionTime }}
                  </div>
                </div>
              </div>
    
              <!-- Live Digital Stamp Preview -->
              <div class="border-primary/30 bg-primary/5 space-y-2 rounded-xl border p-4">
                <div class="flex items-center justify-between">
                  <span class="text-muted-foreground flex items-center gap-1.5 text-xs font-medium">
                    <ShieldCheck class="text-primary size-3.5" />
                    Live Digital Signature Stamp
                  </span>
                  <span class="text-primary font-mono text-xs font-medium">Verified CDL Class-A Holder</span>
                </div>
    
                <div class="border-primary/20 border-b pt-1 pb-2">
                  <p class="text-primary text-2xl font-medium tracking-wide italic">
                    {{ typedSignature || 'Marcus Vance' }}
                  </p>
                </div>
    
                <div class="text-muted-foreground flex flex-wrap items-center justify-between gap-2 font-mono text-xs">
                  <span>Driver: {{ driverName }} · CDL #{{ driverCdl }}</span>
                  <span>Carrier: {{ carrierName }} ({{ dotNumber }})</span>
                </div>
              </div>
            </CardContent>
    
            <CardFooter
              class="border-border bg-muted/15 flex flex-wrap items-center justify-between gap-3 border-t px-6 py-4"
            >
              <div class="text-muted-foreground text-xs">
                Audit Status:
                <strong class="text-foreground"> {{ passCount }} Pass, {{ failCount }} Fail, {{ naCount }} N/A </strong>
              </div>
    
              <div class="flex flex-wrap items-center gap-2">
                <Button type="button" variant="outline" size="sm" class="text-xs font-medium" @click="handleReset">
                  Reset Audit
                </Button>
                <Button
                  type="button"
                  size="sm"
                  class="gap-1.5 text-xs font-medium"
                  :disabled="!certified || typedSignature.trim() === ''"
                  @click="handleSubmit"
                >
                  <FileCheck class="size-4" aria-hidden="true" />
                  Submit Completed DVIR
                </Button>
              </div>
            </CardFooter>
          </Card>
        </div>
      </div>
    </template>
    

Raw manifest:https://uipkge.dev/r/vue/driver-inspection-checklist.json