130 lines
6.1 KiB
TypeScript
130 lines
6.1 KiB
TypeScript
import { memo } from 'react';
|
|
import { User } from 'lucide-react';
|
|
import { Card } from '@/components/ui/card';
|
|
import type { Dealer } from '@/lib/mockData';
|
|
|
|
interface DealerSnapshotProps {
|
|
dealer: Dealer;
|
|
title?: string;
|
|
}
|
|
|
|
export const DealerSnapshot = memo(({ dealer, title = "Dealer Snapshot" }: DealerSnapshotProps) => {
|
|
const snapshotItems = [
|
|
{ label: "Type", value: dealer.dealerType },
|
|
{ label: "Total Companies Associated", value: dealer.noOfCompanies },
|
|
{ label: "Active Products", value: dealer.noOfProducts },
|
|
{ label: "Total Sales (6M Rolling)", value: `${dealer.totalSales6M} MT` },
|
|
{ label: "Total Purchase (6M Rolling)", value: `${dealer.totalPurchase6M} MT` },
|
|
{ label: "Avg. Liquidity Cycle (3M Weighted)", value: `${dealer.avgLiquidityCycle > 0 ? dealer.avgLiquidityCycle.toFixed(1) : 0} Days` },
|
|
{ label: "Avg. Acknowledgment Cycle (3M Weighted)", value: `${dealer.avgAcknowledgmentCycle > 0 ? dealer.avgAcknowledgmentCycle.toFixed(1) : 0} Days` },
|
|
{ label: "Avg. Stock Age", value: `${dealer.stockAge} Days` },
|
|
{ label: "Aged Stock (>90 Days)", value: `${dealer.agedStock} MT` },
|
|
{ label: "Current Stock Quantity", value: `${dealer.currentStock} MT` },
|
|
];
|
|
|
|
return (
|
|
<Card className="p-4 sm:p-6">
|
|
<div className="flex items-center gap-2 mb-4">
|
|
<User className="h-5 w-5 text-primary" />
|
|
<h2 className="text-xl font-semibold text-foreground">{title}</h2>
|
|
</div>
|
|
<div className="space-y-3">
|
|
{snapshotItems.map((item, idx) => (
|
|
<div key={idx} className="flex flex-col min-[450px]:flex-row justify-between py-2 border-b border-border last:border-0 gap-1 min-[450px]:gap-4">
|
|
<span className="text-xs sm:text-sm text-muted-foreground">{item.label}</span>
|
|
<span className="text-sm font-medium text-foreground">{item.value}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</Card>
|
|
);
|
|
});
|
|
|
|
DealerSnapshot.displayName = 'DealerSnapshot';
|
|
|
|
// Compare My Dealer Business variant for manufacturers
|
|
interface ManufacturerData {
|
|
type: string;
|
|
totalCompanies?: number;
|
|
total_companies_associated?: number;
|
|
activeProducts?: number;
|
|
active_products?: number;
|
|
totalSales?: number;
|
|
total_sales_6m_rolling?: number | { value: number; unit: string };
|
|
totalPurchase?: number;
|
|
total_purchase_6m_rolling?: number | { value: number; unit: string };
|
|
avgLiquidityCycle?: number;
|
|
avg_liquidity_cycle_3m_weighted?: number | { value: number; unit: string };
|
|
avgAcknowledgmentCycle?: number;
|
|
avg_acknowledgment_cycle_3m_weighted?: number | { value: number; unit: string };
|
|
avgStockAge?: number;
|
|
avg_stock_age?: number | { value: number; unit: string };
|
|
agedStock?: number;
|
|
aged_stock_over_90_days?: number | { value: number; unit: string };
|
|
currentStock?: number;
|
|
current_stock_quantity?: number | { value: number; unit: string };
|
|
}
|
|
|
|
interface CompareBusinessSnapshotProps {
|
|
data: ManufacturerData;
|
|
}
|
|
|
|
export const CompareBusinessSnapshot = memo(({ data }: CompareBusinessSnapshotProps) => {
|
|
// Helper function to extract value from API response (handles both formats)
|
|
const getValue = (value: number | { value: number; unit: string } | undefined, defaultVal: number = 0): number => {
|
|
if (value === undefined) return defaultVal;
|
|
if (typeof value === 'number') return value;
|
|
return value.value || defaultVal;
|
|
};
|
|
|
|
// Helper function to get unit from API response
|
|
const getUnit = (value: number | { value: number; unit: string } | undefined, defaultUnit: string = ''): string => {
|
|
if (value === undefined || typeof value === 'number') return defaultUnit;
|
|
return value.unit || defaultUnit;
|
|
};
|
|
|
|
// Extract values from API response format or fallback to direct values
|
|
const type = data.type || 'N/A';
|
|
const totalCompanies = data.total_companies_associated ?? data.totalCompanies ?? 0;
|
|
const activeProducts = data.active_products ?? data.activeProducts ?? 0;
|
|
const totalSales = getValue(data.total_sales_6m_rolling ?? data.totalSales, 0);
|
|
const totalPurchase = getValue(data.total_purchase_6m_rolling ?? data.totalPurchase, 0);
|
|
const avgLiquidityCycle = getValue(data.avg_liquidity_cycle_3m_weighted ?? data.avgLiquidityCycle, 0);
|
|
const avgAcknowledgmentCycle = getValue(data.avg_acknowledgment_cycle_3m_weighted ?? data.avgAcknowledgmentCycle, 0);
|
|
const avgStockAge = getValue(data.avg_stock_age ?? data.avgStockAge, 0);
|
|
const agedStock = getValue(data.aged_stock_over_90_days ?? data.agedStock, 0);
|
|
const currentStock = getValue(data.current_stock_quantity ?? data.currentStock, 0);
|
|
|
|
const snapshotItems = [
|
|
{ label: "Type", value: type },
|
|
{ label: "Total Companies Associated", value: totalCompanies },
|
|
{ label: "Active Products", value: activeProducts },
|
|
{ label: "Total Sales (6M Rolling)", value: `${totalSales} MT` },
|
|
{ label: "Total Purchase (6M Rolling)", value: `${totalPurchase} MT` },
|
|
{ label: "Avg. Liquidity Cycle (3M Weighted)", value: `${avgLiquidityCycle > 0 ? avgLiquidityCycle.toFixed(1) : 0} Days` },
|
|
{ label: "Avg. Acknowledgment Cycle (3M Weighted)", value: `${avgAcknowledgmentCycle > 0 ? avgAcknowledgmentCycle.toFixed(1) : 0} Days` },
|
|
{ label: "Avg. Stock Age", value: `${avgStockAge} Days` },
|
|
{ label: "Aged Stock (>90 Days)", value: `${agedStock} MT` },
|
|
{ label: "Current Stock Quantity", value: `${currentStock} MT` },
|
|
];
|
|
|
|
return (
|
|
<Card className="p-4 sm:p-6">
|
|
<div className="flex items-center gap-2 mb-4">
|
|
<User className="h-5 w-5 text-primary" />
|
|
<h2 className="text-xl font-semibold text-foreground">Compare My Dealer Business</h2>
|
|
</div>
|
|
<div className="space-y-3">
|
|
{snapshotItems.map((item, idx) => (
|
|
<div key={idx} className="flex flex-col min-[400px]:flex-row justify-between py-2 border-b border-border last:border-0 gap-1 min-[400px]:gap-4">
|
|
<span className="text-xs sm:text-sm text-muted-foreground">{item.label}</span>
|
|
<span className="text-sm font-medium text-foreground">{item.value}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</Card>
|
|
);
|
|
});
|
|
|
|
CompareBusinessSnapshot.displayName = 'CompareBusinessSnapshot';
|