garage-erp/apps/dashboard/modules/credit-notes/credit-note-general-info.tsx

147 lines
4.8 KiB
TypeScript

import {
FileText,
Calendar,
Hash,
Users,
Building2,
Clock,
} 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 CreditNoteData = {
id?: number
subject?: string
credit_invoice?: string
date?: string
status?: string
notes?: string
customer_id?: number
customer_name?: string
department_name?: string
department_id?: number
invoice_id?: number
created_at?: string
updated_at?: string
}
type CreditNoteGeneralInfoProps = {
creditNote: CreditNoteData
}
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 statusColorMap: Record<string, string> = {
draft: "secondary",
open: "default",
applied: "default",
void: "outline",
}
export function CreditNoteGeneralInfo({ creditNote }: CreditNoteGeneralInfoProps) {
return (
<div className="grid gap-6 md:grid-cols-2">
{/* Credit Note Details */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<FileText className="size-4" />
Credit Note Details
</CardTitle>
</CardHeader>
<CardContent className="grid gap-4">
<div className="flex flex-wrap items-center gap-2">
{creditNote.subject && (
<Badge variant="secondary">{creditNote.subject}</Badge>
)}
{creditNote.status && (
<Badge variant={statusColorMap[creditNote.status] as any ?? "outline"}>
{creditNote.status.charAt(0).toUpperCase() + creditNote.status.slice(1)}
</Badge>
)}
</div>
<Separator />
<div className="grid gap-4 sm:grid-cols-2">
<InfoItem
icon={Hash}
label="Credit Note #"
value={creditNote.credit_invoice}
/>
<InfoItem
icon={Calendar}
label="Date"
value={creditNote.date}
/>
<InfoItem
icon={Clock}
label="Created"
value={creditNote.created_at ? new Date(creditNote.created_at).toLocaleDateString() : null}
/>
</div>
</CardContent>
</Card>
{/* Relations */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Users className="size-4" />
Related Info
</CardTitle>
</CardHeader>
<CardContent className="grid gap-4">
<div className="grid gap-4">
<InfoItem
icon={Users}
label="Customer"
value={creditNote.customer_name}
/>
<InfoItem
icon={Building2}
label="Department"
value={creditNote.department_name}
/>
</div>
{creditNote.notes && (
<>
<Separator />
<div className="flex flex-col gap-1">
<span className="text-xs text-muted-foreground">Notes</span>
<p className="text-sm">{creditNote.notes}</p>
</div>
</>
)}
</CardContent>
</Card>
</div>
)
}