garage-erp/apps/dashboard/modules/inspections/inspection-general-info.tsx
2026-04-06 02:32:47 +03:00

216 lines
7.9 KiB
TypeScript

import {
ClipboardCheck,
Calendar,
Clock,
Hash,
FileText,
User,
Car,
Building2,
FolderOpen,
} from "lucide-react"
import {
Card,
CardContent,
CardHeader,
CardTitle,
} from "@/shared/components/ui/card"
import { Badge } from "@/shared/components/ui/badge"
import { Separator } from "@/shared/components/ui/separator"
type InspectionData = {
id?: number
title?: string
customer_id?: number
vehicle_id?: number
department_id?: number
inspection_category_id?: number
employee_id?: number
order_number?: string
date?: string
time?: string
note?: string
status?: string
created_at?: string
updated_at?: string
customer?: { id?: number; first_name?: string; last_name?: string }
vehicle?: { id?: number; make?: string; model?: string; license_plate?: string }
department?: { id?: number; name?: string }
inspection_category?: { id?: number; name?: string }
employee?: { id?: number; first_name?: string; last_name?: string }
}
type InspectionGeneralInfoProps = {
inspection: InspectionData
}
function InfoItem({
icon: Icon,
label,
value,
}: {
icon: React.ComponentType<{ className?: string }>
label: string
value?: string | null
}) {
return (
<div className="flex items-start gap-3">
<div className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground">
<Icon className="size-4" />
</div>
<div className="flex flex-col gap-0.5">
<span className="text-xs text-muted-foreground">{label}</span>
<span className="text-sm font-medium">
{value || <span className="text-muted-foreground"></span>}
</span>
</div>
</div>
)
}
const STATUS_COLORS: Record<string, string> = {
open: "bg-blue-100 text-blue-800",
in_progress: "bg-yellow-100 text-yellow-800",
completed: "bg-green-100 text-green-800",
}
function formatStatus(status?: string) {
if (!status) return "—"
return status.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
}
export function InspectionGeneralInfo({ inspection }: InspectionGeneralInfoProps) {
const customerName = inspection.customer
? `${inspection.customer.first_name ?? ""} ${inspection.customer.last_name ?? ""}`.trim()
: undefined
const vehicleName = inspection.vehicle
? `${inspection.vehicle.make ?? ""} ${inspection.vehicle.model ?? ""}`.trim()
: undefined
const employeeName = inspection.employee
? `${inspection.employee.first_name ?? ""} ${inspection.employee.last_name ?? ""}`.trim()
: undefined
return (
<div className="grid gap-6 md:grid-cols-2">
{/* Inspection Details */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<ClipboardCheck className="size-4" />
Inspection Details
</CardTitle>
</CardHeader>
<CardContent className="grid gap-4">
<div className="flex flex-wrap items-center gap-2">
{inspection.title && (
<Badge variant="secondary">{inspection.title}</Badge>
)}
{inspection.status && (
<Badge className={STATUS_COLORS[inspection.status] || ""}>
{formatStatus(inspection.status)}
</Badge>
)}
</div>
<Separator />
<div className="grid gap-4 sm:grid-cols-2">
<InfoItem
icon={Hash}
label="Order Number"
value={inspection.order_number}
/>
<InfoItem
icon={FolderOpen}
label="Category"
value={inspection.inspection_category?.name}
/>
<InfoItem
icon={Calendar}
label="Date"
value={inspection.date ? new Date(inspection.date).toLocaleDateString() : null}
/>
<InfoItem
icon={Clock}
label="Time"
value={inspection.time}
/>
</div>
</CardContent>
</Card>
{/* Assignments */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<User className="size-4" />
Assignments
</CardTitle>
</CardHeader>
<CardContent className="grid gap-4 sm:grid-cols-2">
<InfoItem
icon={User}
label="Customer"
value={customerName}
/>
<InfoItem
icon={Car}
label="Vehicle"
value={vehicleName}
/>
<InfoItem
icon={User}
label="Employee"
value={employeeName}
/>
<InfoItem
icon={Building2}
label="Department"
value={inspection.department?.name}
/>
</CardContent>
</Card>
{/* Notes & Timestamps */}
{(inspection.note || inspection.created_at) && (
<Card className="md:col-span-2">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<FileText className="size-4" />
Notes & Timestamps
</CardTitle>
</CardHeader>
<CardContent className="grid gap-4">
<div className="grid gap-4 sm:grid-cols-2">
<InfoItem
icon={Calendar}
label="Created At"
value={inspection.created_at ? new Date(inspection.created_at).toLocaleString() : null}
/>
<InfoItem
icon={Calendar}
label="Updated At"
value={inspection.updated_at ? new Date(inspection.updated_at).toLocaleString() : null}
/>
</div>
{inspection.note && (
<>
<Separator />
<div className="flex items-start gap-3">
<div className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground">
<FileText className="size-4" />
</div>
<div className="flex flex-col gap-0.5">
<span className="text-xs text-muted-foreground">Note</span>
<p className="text-sm whitespace-pre-wrap">{inspection.note}</p>
</div>
</div>
</>
)}
</CardContent>
</Card>
)}
</div>
)
}