"use client"; import { useCallback, useEffect, useRef, useState } from "react"; export type RequestStatus = "idle" | "loading" | "success" | "error"; export type RequestState = { status: RequestStatus; data: T | null; error: Error | null; }; type UseRequestOptions = { successDuration?: number; }; export function useRequest( fn: (...args: TArgs) => Promise, options: UseRequestOptions = {}, ) { const { successDuration = 1500 } = options; const [state, setState] = useState>({ status: "idle", data: null, error: null, }); const timeoutRef = useRef | null>(null); useEffect(() => { return () => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); } }; }, []); const run = useCallback( async (...args: TArgs) => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); } setState({ status: "loading", data: null, error: null }); try { const data = await fn(...args); setState({ status: "success", data, error: null }); if (successDuration > 0) { timeoutRef.current = setTimeout(() => { setState((prev) => ({ ...prev, status: "idle" })); }, successDuration); } return data; } catch (error) { const normalized = error instanceof Error ? error : new Error("Request failed"); setState({ status: "error", data: null, error: normalized }); throw normalized; } }, [fn, successDuration], ); return { ...state, isLoading: state.status === "loading", run, reset: () => setState({ status: "idle", data: null, error: null }), }; }