feat: add quiet reading with rare confirmations
Part of the quiet-user-feedback change; docs and specs land in their own repositories.
This commit is contained in:
@@ -1,45 +1,54 @@
|
||||
import {
|
||||
type BrokerageAccountCard,
|
||||
brokerageAccountCards,
|
||||
useBrokerageAccounts,
|
||||
} from "@/entities/brokerage-account";
|
||||
import { useScreenSync } from "@/features/tbank-connection";
|
||||
import { apiErrorCode } from "@/shared/api";
|
||||
import { ApiErrorCode, apiErrorCode, isApiErrorCode } from "@/shared/api";
|
||||
import { useInitialAvailability } from "@/shared/lib";
|
||||
|
||||
function useAccountsPageViewModel() {
|
||||
type AccountsPageViewModel
|
||||
= | { accounts: BrokerageAccountCard[]; state: "loaded" }
|
||||
| { code?: string; state: "error" }
|
||||
| { state: "empty" }
|
||||
| { state: "loading" };
|
||||
|
||||
function isAccountsAccessFailure(code?: string) {
|
||||
return isApiErrorCode(code, ApiErrorCode.InvalidTbankToken)
|
||||
|| isApiErrorCode(code, ApiErrorCode.TbankNotConnected);
|
||||
}
|
||||
|
||||
function useAccountsPageViewModel(): AccountsPageViewModel {
|
||||
const accounts = useBrokerageAccounts();
|
||||
const sync = useScreenSync({ screen: "accounts" }, [accounts]);
|
||||
useScreenSync({ screen: "accounts" }, [accounts]);
|
||||
|
||||
if (
|
||||
!accounts.data
|
||||
|| (accounts.meta?.availability === "partial" && accounts.data.length === 0)
|
||||
) {
|
||||
if (!accounts.isError && accounts.meta?.sync.state !== "failed")
|
||||
return { state: "loading" as const };
|
||||
const code = apiErrorCode(accounts.error);
|
||||
const isAccessFailure = isAccountsAccessFailure(code);
|
||||
|
||||
const hasResult = !!accounts.data
|
||||
&& !(accounts.meta?.availability === "partial" && accounts.data.length === 0);
|
||||
|
||||
const availability = useInitialAvailability({
|
||||
hasContent: hasResult,
|
||||
identity: "accounts",
|
||||
isError: accounts.isError || accounts.meta?.sync.state === "failed",
|
||||
isFetching: accounts.isFetching,
|
||||
});
|
||||
|
||||
if (isAccessFailure) return { code, state: "error" as const };
|
||||
|
||||
if (!hasResult || !accounts.data)
|
||||
return {
|
||||
code: apiErrorCode(accounts.error),
|
||||
retry: sync.retry,
|
||||
state: "error" as const,
|
||||
};
|
||||
}
|
||||
|
||||
const refresh = {
|
||||
lastSuccessfulAt: accounts.meta?.lastSuccessfulAt,
|
||||
refreshError: accounts.isError || sync.transportError || sync.sourceError,
|
||||
refreshing: accounts.isFetching || sync.refreshing,
|
||||
retry: sync.retry,
|
||||
sourceError: sync.sourceError,
|
||||
};
|
||||
state: availability === "unavailable" ? "error" : "loading",
|
||||
} as const;
|
||||
|
||||
if (accounts.data.length === 0)
|
||||
return {
|
||||
...refresh,
|
||||
state: "empty" as const,
|
||||
};
|
||||
|
||||
return {
|
||||
accounts: brokerageAccountCards(accounts.data, accounts.meta?.dependencies),
|
||||
...refresh,
|
||||
state: "loaded" as const,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user