All files / src/pages/inventory/dialogs/QuantityAdjustDialog QuantityAdjustItemSelect.tsx

99.18% Statements 121/122
81.81% Branches 9/11
100% Functions 5/5
99.18% Lines 121/122

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 1231x 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 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 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x   4x 4x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 4x 4x 4x 4x 4x 4x  
/**
 * @file QuantityAdjustItemSelect.tsx
 * @module dialogs/QuantityAdjustDialog/QuantityAdjustItemSelect
 *
 * @summary
 * Specialized component for item selection step.
 * Pure presentation component with autocomplete search.
 *
 * @enterprise
 * - Single responsibility: render item autocomplete only
 * - Handles search input and item selection
 * - Conditional rendering: disabled until supplier is selected
 * - Provides helpful placeholder and search hints
 */
 
import * as React from 'react';
import { Autocomplete, TextField, CircularProgress, Box, Typography } from '@mui/material';
import { useTranslation } from 'react-i18next';
import type { ItemOption, SupplierOption } from '../../../../api/analytics/types';
 
/**
 * Props for QuantityAdjustItemSelect component.
 * 
 * @interface QuantityAdjustItemSelectProps
 * @property {ItemOption | null} selectedItem - Currently selected item
 * @property {(item: ItemOption | null) => void} onItemChange - Item selection handler
 * @property {string} searchQuery - Current search query text
 * @property {(query: string) => void} onSearchChange - Search query change handler
 * @property {ItemOption[] | undefined} items - Available items filtered by supplier
 * @property {boolean} loading - Whether items are loading
 * @property {SupplierOption | null} selectedSupplier - Selected supplier (for disable logic)
 */
interface QuantityAdjustItemSelectProps {
  selectedItem: ItemOption | null;
  onItemChange: (item: ItemOption | null) => void;
  searchQuery: string;
  onSearchChange: (query: string) => void;
  items: ItemOption[] | undefined;
  loading: boolean;
  selectedSupplier: SupplierOption | null;
}
 
/**
 * Step 2: Item selection component.
 * 
 * Renders an autocomplete field for searching and selecting items.
 * Only enabled after a supplier is selected.
 * Provides search hints and loading indicators.
 * 
 * @component
 * @param props - Component props
 * @returns JSX element for item autocomplete
 * 
 * @example
 * ```tsx
 * <QuantityAdjustItemSelect
 *   selectedItem={form.selectedItem}
 *   onItemChange={form.setSelectedItem}
 *   searchQuery={form.itemQuery}
 *   onSearchChange={form.setItemQuery}
 *   items={form.items}
 *   loading={form.itemsLoading}
 *   selectedSupplier={form.selectedSupplier}
 * />
 * ```
 */
export const QuantityAdjustItemSelect: React.FC<QuantityAdjustItemSelectProps> = ({
  selectedItem,
  onItemChange,
  searchQuery,
  onSearchChange,
  items,
  loading,
  selectedSupplier,
}) => {
  const { t } = useTranslation(['common', 'inventory']);
 
  return (
    <Box>
      <Typography variant="subtitle2" gutterBottom color="primary">
        {t('inventory:steps.selectItem', 'Step 2: Select Item')}
      </Typography>
 
      <Autocomplete
        fullWidth
        size="small"
        options={items || []}
        getOptionLabel={(option) => option.name}
        value={selectedItem}
        onChange={(_, newValue) => onItemChange(newValue)}
        inputValue={searchQuery}
        onInputChange={(_, newInputValue) => onSearchChange(newInputValue)}
        disabled={!selectedSupplier}
        loading={loading}
        noOptionsText={
          searchQuery.length < 2
            ? t('inventory:search.typeToSearch', 'Type at least 2 characters to search')
            : t('inventory:search.noItemsFound', 'No items found')
        }
        renderInput={(params) => (
          <TextField
            {...params}
            label={t('inventory:search.searchSelectItem', 'Search and select item...')}
            placeholder={
              !selectedSupplier ? t('inventory:search.selectSupplierFirst', 'Select supplier first') : undefined
            }
            InputProps={{
              ...params.InputProps,
              endAdornment: (
                <>
                  {loading ? <CircularProgress color="inherit" size={20} /> : null}
                  {params.InputProps.endAdornment}
                </>
              ),
            }}
          />
        )}
        sx={{ mb: 2 }}
      />
    </Box>
  );
};