'use client';
import { useMemo } from 'react';
import { parseAsString, useQueryStates } from 'nuqs';
import { useSuspenseQuery } from '@tanstack/react-query';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow
} from '@/components/ui/table';
import type {
CrmEnquiryAgingReportResponse,
CrmLeadAgingReportResponse
} from '../api/types';
import {
crmEnquiryAgingReportQueryOptions,
crmLeadAgingReportQueryOptions,
crmReportFiltersQueryOptions
} from '../api/queries';
import { ReportFilterBar } from './report-filter-bar';
function formatNumber(value: number) {
return new Intl.NumberFormat('en-US').format(value);
}
function AgingReportLayout({
variant,
canExport,
data
}: {
variant: 'lead' | 'enquiry';
canExport: boolean;
data: CrmLeadAgingReportResponse | CrmEnquiryAgingReportResponse;
}) {
const { data: filterData } = useSuspenseQuery(crmReportFiltersQueryOptions());
const summaryCards =
variant === 'lead' && 'leadCount' in data.summary
? [
['Lead Count', formatNumber(data.summary.leadCount)],
['Average Aging', `${data.summary.averageAgingDays} days`],
['Maximum Aging', `${data.summary.maximumAgingDays} days`]
]
: [
[
'Open Enquiries',
formatNumber('openEnquiries' in data.summary ? data.summary.openEnquiries : 0)
],
['Average Aging', `${data.summary.averageAgingDays} days`],
['Maximum Aging', `${data.summary.maximumAgingDays} days`]
];
return (
{summaryCards.map(([label, value]) => (
{label}
{value}
))}
{variant === 'lead' ? 'Lead Aging Buckets' : 'Enquiry Aging Buckets'}
Bucketed view to spot stagnant records quickly.
{data.buckets.map((bucket) => (
{bucket.label}
{formatNumber(bucket.count)}
))}
{variant === 'lead' ? 'Lead Drill-down' : 'Enquiry Drill-down'}
{variant === 'lead'
? 'Open leads sorted from oldest to newest.'
: 'Open enquiries with latest follow-up visibility.'}
{variant === 'lead' ? (
<>
Lead Number
Customer
Assigned User
Created Date
Aging Days
>
) : (
<>
Enquiry No
Customer
Salesman
Last Follow-Up
Aging Days
>
)}
{data.rows.length ? (
data.rows.map((row) => (
{'leadId' in row ? (
<>
{row.leadCode}
{row.customerName}
{row.assignedUserName ?? '-'}
{new Date(row.createdDate).toLocaleDateString('en-CA')}
{formatNumber(row.agingDays)}
>
) : (
<>
{row.enquiryCode}
{row.customerName}
{row.salesmanName ?? '-'}
{row.lastFollowupDate
? new Date(row.lastFollowupDate).toLocaleDateString('en-CA')
: '-'}
{formatNumber(row.agingDays)}
>
)}
))
) : (
No records found.
)}
);
}
function LeadAgingReportInner({ canExport }: { canExport: boolean }) {
const [params] = useQueryStates({
dateFrom: parseAsString,
dateTo: parseAsString,
branch: parseAsString,
productType: parseAsString,
customerOwner: parseAsString,
leadSource: parseAsString
});
const filters = useMemo(
() => ({
dateFrom: params.dateFrom,
dateTo: params.dateTo,
branch: params.branch,
productType: params.productType,
sales: null,
customerOwner: params.customerOwner,
leadSource: params.leadSource
}),
[params]
);
const { data } = useSuspenseQuery(crmLeadAgingReportQueryOptions(filters));
return ;
}
function EnquiryAgingReportInner({ canExport }: { canExport: boolean }) {
const [params] = useQueryStates({
dateFrom: parseAsString,
dateTo: parseAsString,
branch: parseAsString,
productType: parseAsString,
sales: parseAsString
});
const filters = useMemo(
() => ({
dateFrom: params.dateFrom,
dateTo: params.dateTo,
branch: params.branch,
productType: params.productType,
sales: params.sales,
customerOwner: null,
leadSource: null
}),
[params]
);
const { data } = useSuspenseQuery(crmEnquiryAgingReportQueryOptions(filters));
return ;
}
export function AgingReportView({
variant,
canExport
}: {
variant: 'lead' | 'enquiry';
canExport: boolean;
}) {
return variant === 'lead' ? (
) : (
);
}