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

168 lines
6.1 KiB
TypeScript

import {
User,
Mail,
Phone,
MapPin,
Building2,
Globe,
DollarSign,
CreditCard,
Tag,
Users,
FileText,
} 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 CustomerData = {
id?: number
customer_type_id?: number
salutation?: string
first_name?: string
last_name?: string
company_name?: string
email?: string
phone?: string
alternate_phone?: string
opening_balance?: number
credit_limit?: number
website?: string
referral_source_id?: number
payment_terms_id?: number
address_line_1?: string
address_line_2?: string
country_id?: number
state_id?: number
city?: string
zip_code?: string
created_at?: string
updated_at?: string
customer_type?: { id?: number; name?: string }
referral_source?: { id?: number; title?: string }
payment_terms?: { id?: number; title?: string }
country?: { id?: number; name?: string }
state?: { id?: number; name?: string }
}
type CustomerGeneralInfoProps = {
customer: CustomerData
}
function InfoItem({
icon: Icon,
label,
value,
}: {
icon: React.ComponentType<{ className?: string }>
label: string
value?: string | number | 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 != null && value !== "" ? (
String(value)
) : (
<span className="text-muted-foreground">â</span>
)}
</span>
</div>
</div>
)
}
export function CustomerGeneralInfo({ customer }: CustomerGeneralInfoProps) {
const fullName = [customer.salutation, customer.first_name, customer.last_name]
.filter(Boolean)
.join(" ")
return (
<div className="grid gap-6 md:grid-cols-2">
{/* Personal Info */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<User className="size-4" />
Personal Information
</CardTitle>
</CardHeader>
<CardContent className="grid gap-4">
<div className="flex flex-wrap items-center gap-2">
<Badge variant="secondary">{fullName || "Unknown"}</Badge>
{customer.customer_type?.name && (
<Badge variant="outline">{customer.customer_type.name}</Badge>
)}
</div>
<Separator />
<div className="grid gap-4 sm:grid-cols-2">
<InfoItem icon={User} label="Full Name" value={fullName} />
<InfoItem icon={Building2} label="Company" value={customer.company_name} />
<InfoItem icon={Tag} label="Customer Type" value={customer.customer_type?.name} />
<InfoItem icon={Users} label="Referral Source" value={customer.referral_source?.title} />
</div>
</CardContent>
</Card>
{/* Contact Info */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Phone className="size-4" />
Contact Details
</CardTitle>
</CardHeader>
<CardContent className="grid gap-4 sm:grid-cols-2">
<InfoItem icon={Mail} label="Email" value={customer.email} />
<InfoItem icon={Phone} label="Phone" value={customer.phone} />
<InfoItem icon={Phone} label="Alternate Phone" value={customer.alternate_phone} />
<InfoItem icon={Globe} label="Website" value={customer.website} />
</CardContent>
</Card>
{/* Address */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<MapPin className="size-4" />
Address
</CardTitle>
</CardHeader>
<CardContent className="grid gap-4 sm:grid-cols-2">
<InfoItem icon={MapPin} label="Address Line 1" value={customer.address_line_1} />
<InfoItem icon={MapPin} label="Address Line 2" value={customer.address_line_2} />
<InfoItem icon={MapPin} label="City" value={customer.city} />
<InfoItem icon={MapPin} label="ZIP Code" value={customer.zip_code} />
<InfoItem icon={MapPin} label="State" value={customer.state?.name} />
<InfoItem icon={MapPin} label="Country" value={customer.country?.name} />
</CardContent>
</Card>
{/* Financial Info */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<DollarSign className="size-4" />
Financial Details
</CardTitle>
</CardHeader>
<CardContent className="grid gap-4 sm:grid-cols-2">
<InfoItem icon={DollarSign} label="Opening Balance" value={customer.opening_balance} />
<InfoItem icon={CreditCard} label="Credit Limit" value={customer.credit_limit} />
<InfoItem icon={FileText} label="Payment Terms" value={customer.payment_terms?.title} />
</CardContent>
</Card>
</div>
)
}