All files / packages/ui/src/components/Form FormDatePicker.tsx

100% Statements 15/15
100% Branches 6/6
100% Functions 4/4
100% Lines 15/15

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 123 124 125                                                                                                        2x                 14x   3x 3x         14x   14x       14x                         2x       2x       10x 10x           14x                         2x 2x   2x          
import {
  ForwardedRef,
  forwardRef,
  memo,
  ReactElement,
  Ref,
  useCallback,
} from "react";
import {
  Control,
  Controller,
  ControllerFieldState,
  ControllerRenderProps,
  FieldValues,
  Path,
} from "react-hook-form";
import { DateType } from "react-native-ui-datepicker";
 
import { InputDatePicker, InputDatePickerRef } from "../InputDatePicker";
 
type DatePickerValue =
  | Date
  | null
  | { startDate: Date | null; endDate: Date | null };
 
interface FormDatePickerProps<T extends FieldValues> {
  control: Control<T>;
  name: Path<T>;
  rules?: object;
  label?: string;
  disabled?: boolean;
  testID?: string;
  errorMessage?: string;
  mode?: "single" | "range";
  disabledDates?: (date: DateType) => boolean;
  onConfirm?: (value: DatePickerValue) => void;
  minDate?: Date;
}
 
interface DatePickerControllerProps<T extends FieldValues> {
  field: ControllerRenderProps<T, Path<T>>;
  fieldState: ControllerFieldState;
  props: Omit<
    FormDatePickerProps<T>,
    "control" | "name" | "rules" | "onConfirm" | "mode" | "errorMessage"
  >;
  mode?: "single" | "range";
  errorMessage?: string;
  onPropsConfirm?: (value: DatePickerValue) => void;
  datePickerRef: ForwardedRef<InputDatePickerRef>;
}
 
const DatePickerControllerInstance = <T extends FieldValues>({
  field: { onChange, value },
  fieldState: { error },
  props,
  mode,
  errorMessage,
  onPropsConfirm,
  datePickerRef,
}: DatePickerControllerProps<T>) => {
  const handleConfirm = useCallback(
    (val: DatePickerValue) => {
      onChange(val);
      onPropsConfirm?.(val);
    },
    [onChange, onPropsConfirm],
  );
 
  const valueAsSingle = mode !== "range" ? (value as Date | null) : undefined;
  const valueAsRange =
    mode === "range"
      ? (value as { startDate: Date | null; endDate: Date | null })
      : undefined;
 
  return (
    <InputDatePicker
      {...props}
      ref={datePickerRef}
      mode={mode}
      value={valueAsSingle}
      range={valueAsRange}
      onConfirm={handleConfirm}
      errorMessage={error?.message || errorMessage}
    />
  );
};
 
const DatePickerController = memo(
  DatePickerControllerInstance,
) as typeof DatePickerControllerInstance;
 
const FormDatePickerInner = <T extends FieldValues>(
  { control, name, rules, onConfirm, ...props }: FormDatePickerProps<T>,
  ref: Ref<InputDatePickerRef>,
) => {
  const { mode, errorMessage, ...rest } = props;
  return (
    <Controller
      control={control}
      name={name}
      rules={rules}
      render={(renderProps) => (
        <DatePickerController
          {...renderProps}
          props={rest}
          mode={mode}
          errorMessage={errorMessage}
          onPropsConfirm={onConfirm}
          datePickerRef={ref as ForwardedRef<InputDatePickerRef>}
        />
      )}
    />
  );
};
 
const FormDatePickerComponent = forwardRef(FormDatePickerInner);
FormDatePickerComponent.displayName = "FormDatePicker";
 
export const FormDatePicker = FormDatePickerComponent as <
  T extends FieldValues,
>(
  props: FormDatePickerProps<T> & { ref?: Ref<InputDatePickerRef> },
) => ReactElement;