|
- "use client";
-
- import {
- Autocomplete,
- MenuItem,
- TextField,
- Checkbox,
- Chip,
- } from "@mui/material";
- import {
- Controller,
- FieldValues,
- Path,
- Control,
- RegisterOptions,
- } from "react-hook-form";
- import { useTranslation } from "react-i18next";
- import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank";
- import CheckBoxIcon from "@mui/icons-material/CheckBox";
-
- const icon = <CheckBoxOutlineBlankIcon fontSize="medium" />;
- const checkedIcon = <CheckBoxIcon fontSize="medium" />;
- // label -> e.g. code - name -> 001 - WL
- // name -> WL
- interface Props<
- T extends { id?: number | string | null; label?: string; name?: string },
- TField extends FieldValues,
- > {
- control: Control<TField>;
- options: T[];
- name: Path<TField>; // register name
- label?: string; // display label
- noOptionsText?: string;
- isMultiple?: boolean;
- rules?: RegisterOptions<FieldValues>;
- disabled?: boolean;
- }
-
- function ControlledAutoComplete<
- T extends { id?: number | string; label?: string; name?: string },
- TField extends FieldValues,
- >(props: Props<T, TField>) {
- const { t } = useTranslation();
- const {
- control,
- options,
- name,
- label,
- noOptionsText,
- isMultiple,
- rules,
- disabled,
- } = props;
-
- // set default value if value is null
- if (!Boolean(isMultiple) && !Boolean(control._formValues[name])) {
- control._formValues[name] = options[0]?.id ?? undefined;
- } else if (Boolean(isMultiple) && !Boolean(control._formValues[name])) {
- control._formValues[name] = [];
- }
-
- return (
- <Controller
- name={name}
- control={control}
- rules={rules}
- render={({ field, fieldState, formState }) => {
- return isMultiple ? (
- <Autocomplete
- multiple
- disableClearable
- disableCloseOnSelect
- // disablePortal
- disabled={disabled}
- noOptionsText={noOptionsText ?? t("No Options")}
- value={options.filter((option) => {
- return field.value?.includes(option.id);
- })}
- options={options}
- getOptionLabel={(option) => option.label ?? option.name!}
- isOptionEqualToValue={(option, value) => option.id === value.id}
- renderOption={(params, option, { selected }) => {
- return (
- <li {...params} key={option?.id}>
- <Checkbox
- icon={icon}
- checkedIcon={checkedIcon}
- checked={selected}
- style={{ marginRight: 8 }}
- />
- {option.label ?? option.name}
- </li>
- );
- }}
- renderTags={(tagValue, getTagProps) => {
- return tagValue.map((option, index) => (
- <Chip
- {...getTagProps({ index })}
- key={option?.id}
- label={option.label ?? option.name}
- />
- ));
- }}
- onChange={(event, value) => {
- field.onChange(value?.map((v) => v.id));
- }}
- onBlur={field.onBlur}
- renderInput={(params) => (
- <TextField
- {...params}
- error={Boolean(formState.errors[name])}
- variant="outlined"
- label={label}
- />
- )}
- />
- ) : (
- <Autocomplete
- disableClearable
- // disablePortal
- disabled={disabled}
- noOptionsText={noOptionsText ?? t("No Options")}
- value={
- options.find((option) => option.id === field.value) ?? options[0]
- }
- options={options}
- getOptionLabel={(option) => option.label ?? option.name!}
- isOptionEqualToValue={(option, value) => option?.id === value?.id}
- renderOption={(params, option) => {
- return (
- <MenuItem {...params} key={option?.id} value={option.id}>
- {option.label ?? option.name}
- </MenuItem>
- );
- }}
- renderTags={(tagValue, getTagProps) => {
- return tagValue.map((option, index) => (
- <Chip
- {...getTagProps({ index })}
- key={option?.id}
- label={option.label ?? option.name}
- />
- ));
- }}
- onChange={(event, value) => {
- field.onChange(value?.id ?? null);
- }}
- onBlur={field.onBlur}
- renderInput={(params) => (
- <TextField
- {...params}
- error={Boolean(formState.errors[name])}
- variant="outlined"
- label={label}
- />
- )}
- />
- );
- }}
- />
- );
- }
-
- export default ControlledAutoComplete;
|