import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { Loader2 } from 'lucide-react'; import { api } from '../api/client'; // Consumption, cost and stock grouped by the internal material number // (#2870) — the identifier the business actually purchases and costs by, // unlike brand+material+colour. Data comes from the dedicated aggregate // endpoint so archived spools' recorded usage still counts. interface MaterialNumberStatsProps { currency: string; // Dashboard timeframe. Narrows the consumption/cost columns only — the // spool count and remaining weight are point-in-time stock. dateFrom?: string; dateTo?: string; } function formatGrams(g: number): string { if (Math.abs(g) >= 1000) return `${(g / 1000).toFixed(2)} kg`; return `${Math.round(g)} g`; } export function MaterialNumberStats({ currency, dateFrom, dateTo }: MaterialNumberStatsProps) { const { t } = useTranslation(); const { data, isLoading, isError } = useQuery({ queryKey: ['material-number-stats', dateFrom ?? null, dateTo ?? null], queryFn: () => api.getMaterialNumberStats({ dateFrom, dateTo }), }); if (isLoading) { return (
{t('stats.materialNumbers.loadFailed')}
; } if (!data || data.length === 0) { return{t('stats.materialNumbers.empty')}
; } return (| {t('inventory.materialNumber')} | {t('stats.materialNumbers.spools')} | {t('stats.materialNumbers.remaining')} | {t('stats.materialNumbers.consumed')} | {t('stats.materialNumbers.cost')} |
|---|---|---|---|---|
| {row.material_number} | {row.spool_count} | {formatGrams(row.remaining_g)} | {formatGrams(row.consumed_g)} | {currency} {row.cost.toFixed(2)} |