All files / src/pages/analytics/blocks MonthlyMovementCard.tsx

96% Statements 72/75
80% Branches 8/10
60% Functions 3/5
96% Lines 72/75

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 751x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 7x 7x 7x 7x 7x 7x 2x 2x 2x 2x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 5x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x       2x 2x 2x 2x 2x 2x 2x 2x 7x 7x 7x 7x 7x
/**
* @file MonthlyMovementCard.tsx
* @module pages/analytics/blocks/MonthlyMovementCard
*
* @summary
* Card that renders monthly stock movement (A2).
*/
import { useCallback } from 'react';
import { Card, CardContent, Typography, Skeleton, Box } from '@mui/material';
import { useTheme as useMuiTheme } from '@mui/material/styles';
import { useTranslation } from 'react-i18next';
import { useQuery } from '@tanstack/react-query';
import { getMonthlyStockMovement, type MonthlyMovement } from '../../../api/analytics/stock';
import { ResponsiveContainer, BarChart, CartesianGrid, XAxis, YAxis, Tooltip, Legend, Bar } from 'recharts';
import { useSettings } from '../../../hooks/useSettings';
import { formatDate, formatNumber } from '../../../utils/formatters';
 
 
export type MonthlyMovementCardProps = { from?: string; to?: string; supplierId?: string | null };
 
 
export default function MonthlyMovementCard({ from, to, supplierId }: MonthlyMovementCardProps) {
    const { t } = useTranslation(['analytics']);
    const muiTheme = useMuiTheme();
    const { userPreferences } = useSettings();
    const formatDateLabel = useCallback(
        (value: string | number) => {
            const str = String(value);
            const formatted = formatDate(str, userPreferences.dateFormat);
            return formatted || str;
        },
        [userPreferences.dateFormat]
    );
    
    
    const q = useQuery<MonthlyMovement[]>({
        queryKey: ['analytics', 'movement', from, to, supplierId ?? null],
        queryFn: () => getMonthlyStockMovement({ from, to, supplierId: supplierId ?? undefined }),
    });
    
    
    return (
        <Card>
        <CardContent>
        <Typography variant="subtitle1" sx={{ mb: 1 }}>
        {t('analytics:cards.monthlyMovement')}
        </Typography>
        {q.isLoading ? (
            <Skeleton variant="rounded" height={220} />
        ) : (
            <Box sx={{ height: 260 }}>
            <ResponsiveContainer width="100%" height="100%">
                        <BarChart data={q.data ?? []}>
                        <CartesianGrid strokeDasharray="3 3" />
                        <XAxis dataKey="month" tickFormatter={formatDateLabel} />
                        <YAxis tickFormatter={(value) => formatNumber(Number(value), userPreferences.numberFormat, 0)} />
                        <Tooltip
                            labelFormatter={(value) => formatDateLabel(value as string)}
                            formatter={(value: number | string) =>
                                typeof value === 'number'
                                    ? formatNumber(value, userPreferences.numberFormat, 0)
                                    : value
                            }
                        />
            <Legend />
            <Bar dataKey="stockIn" fill={muiTheme.palette.success.main} />
            <Bar dataKey="stockOut" fill={muiTheme.palette.error.main} />
            </BarChart>
            </ResponsiveContainer>
            </Box>
        )}
        </CardContent>
        </Card>
    );
}