import { useState } from "react"; import { useParams } from "react-router"; import { type BrokerageEvent, useBrokerageEvents, } from "@/entities/brokerage-event"; import { useScreenSync } from "@/features/tbank-connection"; import { isValidPeriod, useUrlPeriod } from "@/shared/lib"; type AccountEventsPageViewModel = | { canApply: boolean; draftPeriod: [null | string, null | string]; events: BrokerageEvent[]; lastSuccessfulAt?: null | string; onApply: () => void; onPeriodChange: (value: [null | string, null | string]) => void; onReset: () => void; partial?: boolean; refreshError: boolean; refreshing: boolean; retry: () => void; sourceError?: boolean; state: "loaded"; } | { onReset: () => void; retry: () => void; state: "error" } | { state: "loading" }; function useAccountEventsPageViewModel(): AccountEventsPageViewModel { const { accountId = "" } = useParams(); const { from: appliedFrom, setParameters: setSearchParameters, to: appliedTo, } = useUrlPeriod(); const [draftPeriod, setDraftPeriod] = useState<[ null | string, null | string, ]>([appliedFrom, appliedTo]); const [draftFrom, draftTo] = draftPeriod; const scope = JSON.stringify([accountId, appliedFrom, appliedTo]); const [previousScope, setPreviousScope] = useState(scope); if (previousScope !== scope) { setPreviousScope(scope); setDraftPeriod([appliedFrom, appliedTo]); } const events = useBrokerageEvents(accountId, { ...(appliedFrom && { from: appliedFrom }), ...(appliedTo && { to: appliedTo }), }); const sync = useScreenSync( { accountId, screen: "events", ...(appliedFrom && { from: appliedFrom }), ...(appliedTo && { to: appliedTo }), }, [events], ); if (events.isLoading) return { state: "loading" }; const onReset = () => { setDraftPeriod([null, null]); setSearchParameters({}); }; if ((events.isError || events.meta?.sync.state === "failed") && !events.data) return { onReset, retry: () => { void sync.retry(); }, state: "error", }; if (!events.data) return { state: "loading" }; return { canApply: (draftFrom !== appliedFrom || draftTo !== appliedTo) && isValidPeriod(draftFrom, draftTo), draftPeriod, events: events.data.events, lastSuccessfulAt: events.meta?.lastSuccessfulAt, onApply: () => { if (!isValidPeriod(draftFrom, draftTo)) return; setSearchParameters({ ...(draftFrom && { from: draftFrom }), ...(draftTo && { to: draftTo }), }); }, onPeriodChange: setDraftPeriod, onReset, partial: events.meta?.availability !== "complete", refreshError: events.isError || sync.sourceError || sync.transportError, refreshing: events.isFetching || sync.refreshing, retry: () => { void sync.retry(); }, sourceError: sync.sourceError, state: "loaded", }; } export { type AccountEventsPageViewModel, useAccountEventsPageViewModel };