import { type BrokerageAccountCard, brokerageAccountCards, useBrokerageAccounts, } from "@/entities/brokerage-account"; import { useScreenSync } from "@/features/tbank-connection"; import { ApiErrorCode, apiErrorCode, isApiErrorCode, readRetry, } from "@/shared/api"; import { useInitialAvailability } from "@/shared/lib"; type AccountsPageReadRetry = ReturnType; type AccountsPageViewModel = | { accounts: BrokerageAccountCard[]; meta: NonNullable["meta"]>; readRetry: AccountsPageReadRetry; state: "loaded"; } | { code?: string; readRetry: AccountsPageReadRetry; state: "error" } | { state: "empty" } | { state: "loading" }; function isAccountsAccessFailure(code?: string) { return isApiErrorCode(code, ApiErrorCode.InvalidTbankToken) || isApiErrorCode(code, ApiErrorCode.TbankNotConnected); } function useAccountsPageVm(): AccountsPageViewModel { const accounts = useBrokerageAccounts(); useScreenSync({ screen: "accounts" }, [accounts]); const code = apiErrorCode(accounts.error); const retry = readRetry([accounts]); const isAccessFailure = isAccountsAccessFailure(code); const hasResult = !!accounts.data && !!accounts.meta && !(accounts.meta.completeness === "incomplete" && accounts.data.length === 0); const availability = useInitialAvailability({ hasContent: hasResult, identity: "accounts", isError: accounts.isError || accounts.meta?.lastAttempt.state === "failed", isFetching: accounts.isFetching, }); if (isAccessFailure) return { code, readRetry: retry, state: "error" as const }; if (!hasResult || !accounts.data) return availability === "unavailable" ? { code, readRetry: retry, state: "error" as const } : { state: "loading" as const }; if (accounts.data.length === 0) return { state: "empty" as const, }; const meta = accounts.meta; if (!meta) return { state: "loading" as const }; return { accounts: brokerageAccountCards(accounts.data, meta.dependencies), meta, readRetry: retry, state: "loaded" as const, }; } export { useAccountsPageVm };