import moment from 'moment' import React from 'react' import Switch from '../Switch/Switch' import DatePicker from '../DatePicker/DatePicker' import FormLabel from '../FormLabel/FormLabel' import { hasValue } from '../../services/HelperServiceTyped' import ListLoading from '../Loaders/ListLoading' import MultiSelect from '../MultiSelect/MultiSelect' import type { SearchBarProps } from '../SearchBar/SearchBar' import Select from '../Form/Select/Select' import type { SelectProps } from '../Form/Select/Select' import type { TooltipProps } from '../Tooltip/Tooltip' import styles from './_filter.module.scss' import { c } from '../../translations/LibraryTranslationService' const TextInput = React.lazy( () => import(/* webpackChunkName: "textInput" */ '../Form/TextInput'), ) const Picker = React.lazy( () => import(/* webpackChunkName: "picker" */ '../Picker/Picker'), ) type FilterMenuPropsType = { /** An object containing an entry for each filter input component */ states: FilterStatesType /** A callback for when the form closes */ close: () => void /** A callback for when the form's inputs change */ onChangeCallout?: (...params: unknown[]) => void /** A boolean specifying whether the filters are still loading or not */ loading?: boolean /** A boolean specifying whether to show additional child components above or below those specified in states */ topChildren?: boolean /** A boolean specifying whether the sidedrawer with the filter form is open */ isOpen: boolean /** Anything which you would like to add in addition to Filter options- unique filter types, header/footer information, etc */ children?: (props: { isOpen?: boolean close?: () => void }) => React.ReactNode } type FormLabelProps = React.ComponentProps type FilterStateOptionType = { type: 'select' | 'dates' | 'text' | 'toggle' | 'switch' | 'multi-select' stateName: string rightLabel?: string customClass?: string qaTestId?: string } type DatePickerProps = React.ComponentProps type FilterDateType = moment.Moment | Date | string | undefined | null interface DatesStatePropType extends FilterStateOptionType { type: 'dates' labelText: string disabled?: FormLabelProps['disabled'] defaultValue: { start_date: FilterDateType end_date?: FilterDateType } dateRestrictions?: DatePickerProps['dateRestrictions'] singleDate?: boolean position?: DatePickerProps['position'] } type TextInputProps = React.ComponentProps interface TextStatePropType extends FilterStateOptionType { type: 'text' labelText: string defaultValue?: TextInputProps['value'] onBlurCallout?: TextInputProps['onBlurCallout'] inputType?: TextInputProps['type'] clearCallout?: TextInputProps['clearCallout'] onReturnCallout?: TextInputProps['onReturnCallout'] numberProps?: Pick< TextInputProps, 'min' | 'max' | 'step' | 'onlyWholeNumbers' | 'onlyPositiveNumbers' > & { suffix?: string } placeholder?: TextInputProps['placeholder'] disabled?: TextInputProps['disabled'] numberFormat?: TextInputProps['numberFormat'] inputLabel?: TextInputProps['inputLabel'] labelTooltip?: TextInputProps['labelTooltip'] keyUp?: () => void shouldClose?: boolean } type PickerProps = React.ComponentProps interface ToggleStatePropType extends FilterStateOptionType { type: 'toggle' labelText?: string options: PickerProps['options'] state?: PickerProps['state'] defaultValue?: PickerProps['selected'] labelTooltip?: PickerProps['labelTooltip'] disabled?: boolean } type MultiSelectProps = React.ComponentProps type MultiSelectStatePropType = FilterStateOptionType & Omit & { type: 'multi-select' } type SelectStatePropType = FilterStateOptionType & { type: 'select' options: SelectProps['options'] labelText: string loading?: SelectProps['loading'] labelTooltip?: TooltipProps defaultValue: SelectProps['selectedItem'] optionKeyName: string isError?: SelectProps['error'] searchBar?: boolean required?: boolean disabled?: boolean onSearchChange?: SearchBarProps['onChange'] } type SwitchProps = React.ComponentProps interface SwitchStatePropType extends FilterStateOptionType { type: 'switch' labelText: string labelTooltip: FormLabelProps['tooltip'] disabled?: FormLabelProps['disabled'] defaultValue: SwitchProps['checked'] } export type FilterStatesType = Record< string, | SelectStatePropType | DatesStatePropType | TextStatePropType | ToggleStatePropType | SwitchStatePropType | MultiSelectStatePropType > export const FilterMenu = ({ states, close, onChangeCallout, loading, topChildren, isOpen, children, }: FilterMenuPropsType): React.JSX.Element => { const updateFilters = (name: string, value: unknown) => { onChangeCallout?.(name, value) } const handleInput = (name: string, value: unknown, textInput?: string) => { if (!textInput) { hasValue(value) && updateFilters(name, value) } else { updateFilters(name, value) } } const clearInput = (name: string, clearCallout: (() => void) | undefined) => { handleInput(name, '', 'textInput') clearCallout?.() } const handleDates = ({ start, end, stateName, }: { start: FilterDateType end?: FilterDateType stateName: string }) => { onChangeCallout?.(stateName ?? 'dates', { start_date: start, ...(end ? { end_date: end } : {}), }) } const inputKeyUp = (callout?: () => void, shouldClose?: boolean) => { if (callout) { callout() } if (shouldClose) { close() } } return ( <> {!loading ? (
{topChildren && children?.({ close, isOpen })} }> {Object.entries(states).map(([stateKey, s]) => { switch (s.type) { case 'select': return (