djbob2000

use-date-picker-state.ts

Sep 2nd, 2025 (edited)
471
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { useState, useRef, useCallback, useEffect } from "react";
  2. import { UseFormReturn } from "react-hook-form";
  3. import { Time } from "@fd-toolbox/dates/time";
  4. import { VoidFunc } from "@fd-toolbox/functions/getter-setter-functions";
  5. import { parseUtcStringToDate } from "@fd-toolbox/dates/date-times";
  6. import { useAsyncEffect } from "@fd-toolbox/hooks/use-async-effect";
  7. import {
  8.     setDatePickerState,
  9.     handleDatePickerOpenChange,
  10. } from "@fd-component-toolbox/datepicker/FdDatePicker.funcs";
  11.  
  12. export interface UseDatePickerStateProps {
  13.     date?: string;
  14.     form?: UseFormReturn;
  15.     name?: string;
  16.     onDateValueChange?: (date?: Date) => void;
  17.     onTimeValueChange?: VoidFunc<Time>;
  18.     onOpenChange?: (isOpen: boolean) => void;
  19. }
  20.  
  21. export interface UseDatePickerStateReturn {
  22.     dateValue: Date | undefined;
  23.     timeValue: Time;
  24.     isOpen: boolean;
  25.     setDateValue: (date?: Date) => void;
  26.     setTimeValue: React.Dispatch<React.SetStateAction<Time>>;
  27.     onOpenChangeCallback: (open: boolean) => void;
  28.     onTimeValueChange: (operation: string, value: number) => void;
  29. }
  30.  
  31. /**
  32.  * Custom hook for managing the state of the DatePicker component
  33.  *
  34.  * @param props - hook parameters
  35.  * @returns object with state and control methods
  36.  */
  37. export function useDatePickerState({
  38.     date = "",
  39.     form,
  40.     name,
  41.     onDateValueChange: onDateValueChangeProp,
  42.     onTimeValueChange: onTimeValueChangeProp,
  43.     onOpenChange,
  44. }: UseDatePickerStateProps): UseDatePickerStateReturn {
  45.     const [dateValue, setDateValue] = useState<Date>();
  46.     const [timeValue, setTimeValue] = useState<Time>({ hours: 0, minutes: 0 });
  47.     const [isOpen, setIsOpen] = useState(false);
  48.     const prevIsoString = useRef<string | null>(null);
  49.  
  50.     // Initialize date and time from the date prop
  51.     useEffect(() => {
  52.         if (date !== "") {
  53.             const parseData = parseUtcStringToDate(date);
  54.             setDateValue(parseData);
  55.             setTimeValue({ hours: parseData.getHours(), minutes: parseData.getMinutes() });
  56.         } else {
  57.             setDateValue(undefined);
  58.             setTimeValue({ hours: 0, minutes: 0 });
  59.         }
  60.     }, [date]);
  61.  
  62.     // Check if the form is ready for update
  63.     const isFormReadyToUpdate = useCallback(() => {
  64.         return !!(form && name);
  65.     }, [form, name]);
  66.  
  67.     // Set the previous ISO string
  68.     const setPrevIsoString = useCallback((isoString: string | null) => {
  69.         prevIsoString.current = isoString;
  70.     }, []);
  71.  
  72.     // Set the value in the form
  73.     const setFormValue = useCallback(
  74.         (datePickerName: string, isoString: string | null) => {
  75.             form?.setValue(datePickerName, isoString);
  76.         },
  77.         [form],
  78.     );
  79.  
  80.     // Synchronize state with the form
  81.     useAsyncEffect(async () => {
  82.         setDatePickerState(
  83.             timeValue,
  84.             setPrevIsoString,
  85.             setFormValue,
  86.             isFormReadyToUpdate(),
  87.             prevIsoString?.current ?? undefined,
  88.             dateValue ?? undefined,
  89.             name,
  90.             onDateValueChangeProp,
  91.         );
  92.     }, [timeValue, dateValue, form, name]);
  93.  
  94.     // Notify about time change
  95.     useAsyncEffect(async () => {
  96.         onTimeValueChangeProp?.(timeValue);
  97.     }, [timeValue]);
  98.  
  99.     // Time change handler
  100.     const onTimeValueChange = useCallback(
  101.         (operation: string, value: number) => {
  102.             if (operation === "hours") {
  103.                 setTimeValue((prevTimeValue) => ({ ...prevTimeValue, hours: value }));
  104.             } else if (operation === "minutes") {
  105.                 setTimeValue((prevTimeValue) => ({ ...prevTimeValue, minutes: value }));
  106.             }
  107.         },
  108.         [setTimeValue],
  109.     );
  110.  
  111.     // Handler for changing the open state of the popup
  112.     const onOpenChangeCallback = useCallback(
  113.         (open: boolean) => {
  114.             handleDatePickerOpenChange(open, setIsOpen, onOpenChange);
  115.         },
  116.         [onOpenChange],
  117.     );
  118.  
  119.     return {
  120.         dateValue,
  121.         timeValue,
  122.         isOpen,
  123.         setDateValue,
  124.         setTimeValue,
  125.         onOpenChangeCallback,
  126.         onTimeValueChange,
  127.     };
  128. }
Advertisement
Add Comment
Please, Sign In to add comment