All files / src/pages/dashboard Dashboard.tsx

100% Statements 135/135
100% Branches 7/7
100% Functions 4/4
100% Lines 135/135

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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 1361x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 1x 1x  
/**
 * @file Dashboard.tsx
 * @module pages/dashboard
 *
 * @description
 * Main dashboard page providing system overview and quick navigation.
 * Displays KPI cards (inventory count, suppliers, low stock items) and a 90-day
 * stock movement chart. Includes resilient error handling: if API endpoints
 * are unavailable, cards gracefully show "—" instead of breaking the page.
 *
 * @responsibilities
 * - Fetch and display key metrics via useDashboardMetrics hook
 * - Render KPI stat cards with loading states
 * - Display monthly stock movement chart
 * - Provide action buttons for quick navigation to main features
 * - Support help system integration
 *
 * @i18n
 * Uses 'common' namespace for all translations:
 * - dashboard.title: Page title
 * - dashboard.kpi.*: KPI card labels
 * - dashboard.actions.*: Button labels
 * - actions.help: Help button tooltip
 */
import * as React from 'react';
import { Box, Grid, Button, Stack, Typography, Paper } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { useDashboardMetrics } from '../../api/analytics/hooks';
import MonthlyMovementMini from './blocks/MonthlyMovementMini';
import StatCard from '../../components/ui/StatCard';
import { useNavigate } from 'react-router-dom';
import { HelpIconButton } from '../../features/help';
 
/**
 * Dashboard page component.
 * Provides KPI overview, trending chart, and navigation shortcuts.
 * Resilient to partial API failures (missing KPI data shows "—").
 * @returns React component with grid layout of cards and action buttons
 */
const Dashboard: React.FC = () => {
  const { t } = useTranslation('common');
  const navigate = useNavigate();
 
  // Fetch all KPI metrics in a single query with cache durability
  const metricsQuery = useDashboardMetrics(true);
 
  return (
    <Paper
      elevation={0}
      sx={{
        flex: 1,
        display: 'flex',
        flexDirection: 'column',
        bgcolor: 'background.paper',
        m: 0,
      }}
    >
      <Box
        sx={{
          flex: 1,
          display: 'flex',
          flexDirection: 'column',
          px: { xs: 2, md: 3 },
          pt: { xs: 1.5, md: 2 },
          pb: { xs: 2, md: 3 },
        }}
      >
        {/* Header with title and help button */}
        <Box
          sx={{
            mb: 1.5,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'space-between',
          }}
        >
          <Typography variant="h5" sx={{ fontWeight: 600 }}>
            {t('dashboard.title')}
          </Typography>
 
          <HelpIconButton topicId="app.main" tooltip={t('actions.help', 'Help')} />
        </Box>
 
        {/* KPI metrics grid: Total inventory, suppliers count, low stock count */}
        <Grid container spacing={2} sx={{ mb: 2 }}>
          <Grid size={{ xs: 12, sm: 4 }}>
            <StatCard
              title={t('dashboard.kpi.totalItems')}
              value={metricsQuery.data?.inventoryCount}
              loading={metricsQuery.isLoading}
            />
          </Grid>
          <Grid size={{ xs: 12, sm: 4 }}>
            <StatCard
              title={t('dashboard.kpi.suppliers')}
              value={metricsQuery.data?.suppliersCount}
              loading={metricsQuery.isLoading}
            />
          </Grid>
          <Grid size={{ xs: 12, sm: 4 }}>
            <StatCard
              title={t('dashboard.kpi.lowStock')}
              value={metricsQuery.data?.lowStockCount}
              loading={metricsQuery.isLoading}
            />
          </Grid>
        </Grid>
 
        {/* Trending chart: Monthly stock movement over last 90 days */}
        <Box sx={{ mb: 2 }}>
          <MonthlyMovementMini />
        </Box>
 
        {/* Action buttons for main workflows (responsive layout) */}
        <Stack
          direction={{ xs: 'column', sm: 'row' }}
          spacing={1}
          sx={{ mt: 'auto', pt: 1 }}
        >
          <Button variant="contained" onClick={() => navigate('/inventory')}>
            {t('dashboard.actions.manageInventory')}
          </Button>
          <Button variant="outlined" onClick={() => navigate('/suppliers')}>
            {t('dashboard.actions.manageSuppliers')}
          </Button>
          <Button variant="outlined" onClick={() => navigate('/analytics/overview')}>
            {t('dashboard.actions.viewAnalytics')}
          </Button>
        </Stack>
      </Box>
    </Paper>
  );
};
 
export default Dashboard;