payment-backoffice/app/hooks/useDebouncedDateRange.ts
2025-12-27 10:57:56 +01:00

66 lines
1.7 KiB
TypeScript

"use client";
import { useState, useRef, useEffect, useCallback } from "react";
import { Range } from "react-date-range";
interface IUseDebouncedDateRangeOptions {
initialDateRange?: Range[];
debounceMs?: number;
onDateRangeChange?: (range: Range[]) => void | Promise<void>;
skipInitialFetch?: boolean;
}
export const useDebouncedDateRange = ({
initialDateRange,
debounceMs = 1000,
onDateRangeChange,
skipInitialFetch = false,
}: IUseDebouncedDateRangeOptions = {}) => {
const [dateRange, setDateRange] = useState<Range[]>(initialDateRange ?? []);
const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const isFirstMount = useRef(true);
const handleDateRangeChange = useCallback(
(newRange: Range[]) => {
// Update state immediately for UI responsiveness
setDateRange(newRange);
// Clear any existing debounce timeout
if (debounceTimeoutRef.current) {
clearTimeout(debounceTimeoutRef.current);
}
// Skip fetch on first mount if requested
if (isFirstMount.current) {
isFirstMount.current = false;
if (skipInitialFetch) {
return;
}
}
const currentRange = newRange[0];
if (!currentRange?.startDate || !currentRange?.endDate) return;
// Debounce the callback
debounceTimeoutRef.current = setTimeout(() => {
onDateRangeChange?.(newRange);
}, debounceMs);
},
[onDateRangeChange, debounceMs, skipInitialFetch]
);
// Cleanup timeout on unmount
useEffect(() => {
return () => {
if (debounceTimeoutRef.current) {
clearTimeout(debounceTimeoutRef.current);
}
};
}, []);
return {
dateRange,
handleDateRangeChange,
};
};