chore(hooks): 🔧 Update hook scripts: index.ts, use-refresh-interval.ts, and related utility files
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
1f840fd0c9
commit
85235e6977
3 changed files with 0 additions and 256 deletions
|
|
@ -1,2 +0,0 @@
|
|||
export * from './use-time-range';
|
||||
export * from './use-refresh-interval';
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
import { useEffect, useRef, useCallback, useState } from 'react';
|
||||
|
||||
interface UseRefreshIntervalOptions {
|
||||
/** Interval in milliseconds (0 to disable) */
|
||||
interval: number;
|
||||
/** Callback to execute on each interval */
|
||||
onRefresh: () => void | Promise<void>;
|
||||
/** Whether to start paused */
|
||||
startPaused?: boolean;
|
||||
/** Whether to run immediately on mount */
|
||||
immediate?: boolean;
|
||||
}
|
||||
|
||||
interface UseRefreshIntervalReturn {
|
||||
/** Whether the interval is currently active */
|
||||
isActive: boolean;
|
||||
/** Pause the interval */
|
||||
pause: () => void;
|
||||
/** Resume the interval */
|
||||
resume: () => void;
|
||||
/** Manually trigger a refresh */
|
||||
refresh: () => void;
|
||||
/** Time until next refresh in ms */
|
||||
timeUntilRefresh: number;
|
||||
}
|
||||
|
||||
export function useRefreshInterval(
|
||||
options: UseRefreshIntervalOptions
|
||||
): UseRefreshIntervalReturn {
|
||||
const { interval, onRefresh, startPaused = false, immediate = true } = options;
|
||||
|
||||
const [isActive, setIsActive] = useState(!startPaused && interval > 0);
|
||||
const [timeUntilRefresh, setTimeUntilRefresh] = useState(interval);
|
||||
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
const countdownRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
const onRefreshRef = useRef(onRefresh);
|
||||
|
||||
// Keep callback ref up to date
|
||||
useEffect(() => {
|
||||
onRefreshRef.current = onRefresh;
|
||||
}, [onRefresh]);
|
||||
|
||||
const clearIntervals = useCallback(() => {
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current);
|
||||
intervalRef.current = null;
|
||||
}
|
||||
if (countdownRef.current) {
|
||||
clearInterval(countdownRef.current);
|
||||
countdownRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const startIntervals = useCallback(() => {
|
||||
clearIntervals();
|
||||
|
||||
if (interval <= 0) return;
|
||||
|
||||
setTimeUntilRefresh(interval);
|
||||
|
||||
intervalRef.current = setInterval(() => {
|
||||
onRefreshRef.current();
|
||||
setTimeUntilRefresh(interval);
|
||||
}, interval);
|
||||
|
||||
countdownRef.current = setInterval(() => {
|
||||
setTimeUntilRefresh((prev) => Math.max(0, prev - 1000));
|
||||
}, 1000);
|
||||
}, [interval, clearIntervals]);
|
||||
|
||||
const pause = useCallback(() => {
|
||||
setIsActive(false);
|
||||
clearIntervals();
|
||||
}, [clearIntervals]);
|
||||
|
||||
const resume = useCallback(() => {
|
||||
if (interval > 0) {
|
||||
setIsActive(true);
|
||||
startIntervals();
|
||||
}
|
||||
}, [interval, startIntervals]);
|
||||
|
||||
const refresh = useCallback(() => {
|
||||
onRefreshRef.current();
|
||||
if (isActive) {
|
||||
startIntervals();
|
||||
}
|
||||
}, [isActive, startIntervals]);
|
||||
|
||||
// Initial setup
|
||||
useEffect(() => {
|
||||
if (immediate) {
|
||||
onRefreshRef.current();
|
||||
}
|
||||
|
||||
if (!startPaused && interval > 0) {
|
||||
startIntervals();
|
||||
}
|
||||
|
||||
return clearIntervals;
|
||||
}, [immediate, startPaused, interval, startIntervals, clearIntervals]);
|
||||
|
||||
// Handle interval changes
|
||||
useEffect(() => {
|
||||
if (isActive && interval > 0) {
|
||||
startIntervals();
|
||||
} else if (interval <= 0) {
|
||||
clearIntervals();
|
||||
setIsActive(false);
|
||||
}
|
||||
}, [interval, isActive, startIntervals, clearIntervals]);
|
||||
|
||||
return {
|
||||
isActive,
|
||||
pause,
|
||||
resume,
|
||||
refresh,
|
||||
timeUntilRefresh,
|
||||
};
|
||||
}
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
import { useState, useCallback, useMemo } from 'react';
|
||||
import type { TimeRange, TimeGranularity } from '../../types';
|
||||
|
||||
export type PresetTimeRange =
|
||||
| 'today'
|
||||
| 'yesterday'
|
||||
| 'last7days'
|
||||
| 'last30days'
|
||||
| 'last90days'
|
||||
| 'thisMonth'
|
||||
| 'lastMonth'
|
||||
| 'thisYear'
|
||||
| 'custom';
|
||||
|
||||
interface UseTimeRangeOptions {
|
||||
initialPreset?: PresetTimeRange;
|
||||
initialRange?: TimeRange;
|
||||
}
|
||||
|
||||
interface UseTimeRangeReturn {
|
||||
timeRange: TimeRange;
|
||||
preset: PresetTimeRange;
|
||||
setPreset: (preset: PresetTimeRange) => void;
|
||||
setCustomRange: (range: TimeRange) => void;
|
||||
suggestedGranularity: TimeGranularity;
|
||||
}
|
||||
|
||||
const getPresetRange = (preset: PresetTimeRange): TimeRange => {
|
||||
const now = new Date();
|
||||
const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
||||
|
||||
switch (preset) {
|
||||
case 'today':
|
||||
return {
|
||||
start: startOfDay,
|
||||
end: now,
|
||||
};
|
||||
case 'yesterday': {
|
||||
const yesterday = new Date(startOfDay);
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
return {
|
||||
start: yesterday,
|
||||
end: startOfDay,
|
||||
};
|
||||
}
|
||||
case 'last7days': {
|
||||
const start = new Date(startOfDay);
|
||||
start.setDate(start.getDate() - 7);
|
||||
return { start, end: now };
|
||||
}
|
||||
case 'last30days': {
|
||||
const start = new Date(startOfDay);
|
||||
start.setDate(start.getDate() - 30);
|
||||
return { start, end: now };
|
||||
}
|
||||
case 'last90days': {
|
||||
const start = new Date(startOfDay);
|
||||
start.setDate(start.getDate() - 90);
|
||||
return { start, end: now };
|
||||
}
|
||||
case 'thisMonth': {
|
||||
const start = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||
return { start, end: now };
|
||||
}
|
||||
case 'lastMonth': {
|
||||
const start = new Date(now.getFullYear(), now.getMonth() - 1, 1);
|
||||
const end = new Date(now.getFullYear(), now.getMonth(), 0);
|
||||
return { start, end };
|
||||
}
|
||||
case 'thisYear': {
|
||||
const start = new Date(now.getFullYear(), 0, 1);
|
||||
return { start, end: now };
|
||||
}
|
||||
default:
|
||||
return {
|
||||
start: startOfDay,
|
||||
end: now,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const getSuggestedGranularity = (range: TimeRange): TimeGranularity => {
|
||||
const diffMs = range.end.getTime() - range.start.getTime();
|
||||
const diffDays = diffMs / (1000 * 60 * 60 * 24);
|
||||
|
||||
if (diffDays <= 1) return 'hour';
|
||||
if (diffDays <= 7) return 'day';
|
||||
if (diffDays <= 90) return 'day';
|
||||
if (diffDays <= 365) return 'week';
|
||||
return 'month';
|
||||
};
|
||||
|
||||
export function useTimeRange(options: UseTimeRangeOptions = {}): UseTimeRangeReturn {
|
||||
const { initialPreset = 'last7days', initialRange } = options;
|
||||
|
||||
const [preset, setPresetState] = useState<PresetTimeRange>(
|
||||
initialRange ? 'custom' : initialPreset
|
||||
);
|
||||
const [customRange, setCustomRangeState] = useState<TimeRange | null>(
|
||||
initialRange || null
|
||||
);
|
||||
|
||||
const timeRange = useMemo(() => {
|
||||
if (preset === 'custom' && customRange) {
|
||||
return customRange;
|
||||
}
|
||||
return getPresetRange(preset);
|
||||
}, [preset, customRange]);
|
||||
|
||||
const suggestedGranularity = useMemo(
|
||||
() => getSuggestedGranularity(timeRange),
|
||||
[timeRange]
|
||||
);
|
||||
|
||||
const setPreset = useCallback((newPreset: PresetTimeRange) => {
|
||||
setPresetState(newPreset);
|
||||
if (newPreset !== 'custom') {
|
||||
setCustomRangeState(null);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const setCustomRange = useCallback((range: TimeRange) => {
|
||||
setPresetState('custom');
|
||||
setCustomRangeState(range);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
timeRange,
|
||||
preset,
|
||||
setPreset,
|
||||
setCustomRange,
|
||||
suggestedGranularity,
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue