Files
alla-allaos-fullstack/src/features/crm/dashboard/components/dashboard-summary-cards.tsx
phaichayon 721653f692 thai-uxui
2026-06-19 11:11:17 +07:00

102 lines
4.3 KiB
TypeScript

'use client';
import Link from 'next/link';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import type { CrmDashboardSummary } from '../api/types';
function formatNumber(value: number) {
return new Intl.NumberFormat('en-US', { maximumFractionDigits: 2 }).format(value);
}
function SummaryCard({
title,
description,
items,
href
}: {
title: string;
description: string;
items: Array<{ label: string; value: number; suffix?: string }>;
href?: string;
}) {
const content = (
<Card className='h-full'>
<CardHeader>
<CardTitle>{title}</CardTitle>
<CardDescription>{description}</CardDescription>
</CardHeader>
<CardContent className='grid gap-4 sm:grid-cols-2'>
{items.map((item) => (
<div key={item.label} className='rounded-lg border bg-muted/20 p-4'>
<div className='text-muted-foreground text-xs'>{item.label}</div>
<div className='mt-2 text-2xl font-semibold'>
{formatNumber(item.value)}
{item.suffix ? <span className='ml-1 text-sm font-normal'>{item.suffix}</span> : null}
</div>
</div>
))}
</CardContent>
</Card>
);
return href ? <Link href={href} className='block'>{content}</Link> : content;
}
export function DashboardSummaryCards({
summary,
canViewCommercialData
}: {
summary: CrmDashboardSummary;
canViewCommercialData: boolean;
}) {
return (
<div className={`grid gap-4 ${canViewCommercialData ? 'xl:grid-cols-2 2xl:grid-cols-4' : 'xl:grid-cols-2'}`}>
<SummaryCard
title='ลีด'
description='รายการที่ยังอยู่ในขั้นลีดและอยู่ในความรับผิดชอบของการตลาด'
href='/dashboard/crm/leads'
items={[
{ label: 'จำนวนลีด', value: summary.lead.leadCount },
{ label: 'ลีดใหม่', value: summary.lead.newLeads },
{ label: 'ลีดยังไม่มอบหมาย', value: summary.lead.unassignedLeads },
{ label: 'อายุลีดเฉลี่ย', value: summary.lead.averageLeadAgingDays, suffix: 'วัน' }
]}
/>
<SummaryCard
title='โอกาสขาย'
description='รายการที่อยู่ในขั้นโอกาสขาย รวมถึงผลลัพธ์ชนะและแพ้'
href='/dashboard/crm/enquiries'
items={[
{ label: 'จำนวนโอกาสขาย', value: summary.enquiry.enquiryCount },
{ label: 'โอกาสขายที่กำลังดำเนินการ', value: summary.enquiry.activeEnquiries },
{ label: 'จำนวนงานที่ชนะ', value: summary.enquiry.wonCount },
{ label: 'จำนวนงานที่แพ้', value: summary.enquiry.lostCount }
]}
/>
{canViewCommercialData ? (
<SummaryCard
title='ใบเสนอราคา'
description='สถานะของใบเสนอราคาจากข้อมูลจริงในระบบ'
items={[
{ label: 'ฉบับร่าง', value: summary.quotation.draftQuotations },
{ label: 'รออนุมัติ', value: summary.quotation.pendingApproval },
{ label: 'อนุมัติแล้ว', value: summary.quotation.approvedQuotations },
{ label: 'ส่งแล้ว', value: summary.quotation.sentQuotations }
]}
/>
) : null}
{canViewCommercialData ? (
<SummaryCard
title='มูลค่าใบเสนอราคา'
description='มูลค่าใบเสนอราคา งานที่ชนะ และงานที่แพ้ตามกติกา revenue attribution'
items={[
{ label: 'มูลค่าใบเสนอราคา', value: summary.revenue.quotationValue },
{ label: 'มูลค่างานที่ชนะ', value: summary.revenue.wonValue },
{ label: 'มูลค่างานที่แพ้', value: summary.revenue.lostValue }
]}
/>
) : null}
</div>
);
}