All files / src/pages/analytics/blocks/price-trend PriceTrendCard.tsx

100% Statements 95/95
100% Branches 8/8
100% Functions 2/2
100% Lines 95/95

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 961x 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 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 7x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x  
/**
 * @file PriceTrendCard.tsx
 * @module pages/analytics/blocks/price-trend
 *
 * @description
 * Price trend card with item search and price line chart (A3).
 * Supports global or supplier-scoped item searches.
 * Chart fetches only after explicit item selection.
 *
 * @remarks
 * - Enforces supplier scoping: prevents cross-supplier selections
 * - Debounced search (250ms) to avoid flooding server
 * - Keeps previous data during refetch for smooth UX
 * - Resets on supplier change to prevent data leaks
 *
 * @i18n
 * Uses 'analytics' namespace for all translation keys
 */
 
import * as React from 'react';
import { Card, CardContent, Typography, Stack } from '@mui/material';
import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { getPriceTrend, type ItemRef, type PricePoint } from '../../../../api/analytics';
import { useSettings } from '../../../../hooks/useSettings';
import { ItemAutocomplete } from './ItemAutocomplete';
import { PriceChart } from './PriceChart';
import type { PriceTrendCardProps } from './PriceTrendCard.types';
 
/**
 * Price trend card component
 * Shows item price movement over selected date range and supplier
 *
 * @example
 * ```tsx
 * <PriceTrendCard from="2025-01-01" to="2025-12-31" supplierId="sup-123" />
 * ```
 */
export default function PriceTrendCard({
  from,
  to,
  supplierId,
}: PriceTrendCardProps) {
  const { t } = useTranslation(['analytics']);
  const { userPreferences } = useSettings();
 
  // Item selection state
  const [selectedItem, setSelectedItem] = React.useState<ItemRef | null>(null);
  const selectedItemId = selectedItem?.id ?? '';
 
  // Reset on supplier change to prevent cross-supplier leaks
  React.useEffect(() => {
    setSelectedItem(null);
  }, [supplierId]);
 
  // Fetch price trend data only after item selection
  const priceQ = useQuery<PricePoint[]>({
    queryKey: ['analytics', 'priceTrend', selectedItemId, from, to],
    queryFn: () => getPriceTrend(selectedItemId, { from, to, supplierId: supplierId ?? undefined }),
    enabled: !!selectedItemId,
  });
 
  return (
    <Card>
      <CardContent>
        {/* Header with title and item search */}
        <Stack
          direction={{ xs: 'column', sm: 'row' }}
          spacing={2}
          alignItems="center"
          justifyContent="space-between"
          sx={{ mb: 1 }}
        >
          <Typography variant="subtitle1">
            {t('analytics:cards.priceTrend')}
          </Typography>
 
          <ItemAutocomplete
            value={selectedItem}
            onChange={setSelectedItem}
            supplierId={supplierId}
          />
        </Stack>
 
        {/* Price trend chart */}
        <PriceChart
          data={priceQ.data ?? []}
          isLoading={!selectedItemId || priceQ.isLoading}
          dateFormat={userPreferences.dateFormat}
          numberFormat={userPreferences.numberFormat}
        />
      </CardContent>
    </Card>
  );
}