All files / src/stock-items/add-stock-item/concepts-selector concepts-selector.component.tsx

100% Statements 18/18
100% Branches 10/10
100% Functions 8/8
100% Lines 18/18

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                                    1x     6x   6x   6x 2x     6x 6x   3x     6x 1x     5x         7x         29x     2x 1x 1x   1x           18x                    
import React, { type ReactNode, useMemo, useState } from 'react';
import { ComboBox, TextInputSkeleton } from '@carbon/react';
import { type Control, Controller, type FieldValues } from 'react-hook-form';
import { type Concept } from '../../../core/api/types/concept/Concept';
import { useConcepts } from '../../../stock-lookups/stock-lookups.resource';
 
interface ConceptsSelectorProps<T> {
  conceptUuid?: string;
  control: Control<FieldValues, T>;
  controllerName: string;
  invalid?: boolean;
  invalidText?: ReactNode;
  name: string;
  onConceptUuidChange?: (unit: Concept) => void;
  placeholder?: string;
  title?: string;
}
 
const ConceptsSelector = <T,>(props: ConceptsSelectorProps<T>) => {
  const {
    items: { results: concepts },
    isLoading,
  } = useConcepts({});
  const [inputValue, setInputValue] = useState('');
 
  const handleInputChange = (value: string) => {
    setInputValue(value);
  };
 
  const filteredConcepts = useMemo(() => {
    return inputValue.trim() === ''
      ? concepts
      : concepts.filter((concept) => concept.display?.toLowerCase().includes(inputValue.trim()?.toLowerCase()));
  }, [inputValue, concepts]);
 
  if (isLoading) {
    return <TextInputSkeleton />;
  }
 
  return (
    <Controller
      control={props.control}
      name={props.controllerName}
      render={({ field: { onChange, value, ref } }) => (
        <ComboBox
          id={props.name}
          invalid={props.invalid}
          invalidText={props.invalidText}
          items={filteredConcepts}
          itemToString={(item?: Concept) => item?.display ?? ''}
          name={props.name}
          onChange={(data: { selectedItem: Concept | null | undefined }) => {
            if (data.selectedItem) {
              props.onConceptUuidChange?.(data.selectedItem);
              onChange(data.selectedItem.uuid);
            } else {
              onChange('');
            }
          }}
          onInputChange={handleInputChange}
          placeholder={props.placeholder}
          ref={ref}
          selectedItem={concepts?.find((p) => p.uuid === value) ?? null}
          size="md"
          titleText={props.title}
        />
      )}
    />
  );
};
 
export default ConceptsSelector;