feat: show persisted investment data and sync state

Consume the provided resource-envelope API snapshot. Preserve financial snapshots during
refresh, observe synchronization without importing, and fence late responses across
account and connection changes.
This commit is contained in:
2026-09-26 21:22:49 +03:00
parent b987fd8e78
commit 4e5f564fa1
81 changed files with 4714 additions and 1420 deletions
@@ -4,6 +4,7 @@ import {
type BrokerageEvent,
useBrokerageEvents,
} from "@/entities/brokerage-event";
import { useScreenSync } from "@/features/tbank-connection";
type AccountEventsPageViewModel =
| { state: "loading" }
@@ -11,6 +12,9 @@ type AccountEventsPageViewModel =
| {
state: "loaded";
events: BrokerageEvent[];
sourceError?: boolean;
lastSuccessfulAt?: string | null;
partial?: boolean;
refreshing: boolean;
refreshError: boolean;
retry: () => void;
@@ -41,22 +45,34 @@ function useAccountEventsPageViewModel(
...(appliedFrom ? { from: appliedFrom } : {}),
...(appliedTo ? { to: appliedTo } : {}),
});
const sync = useScreenSync(
{
screen: "events",
accountId,
...(appliedFrom ? { from: appliedFrom } : {}),
...(appliedTo ? { to: appliedTo } : {}),
},
[events],
);
if (events.isLoading) return { state: "loading" };
if (events.isError && !events.data)
if ((events.isError || events.meta?.sync.state === "failed") && !events.data)
return {
state: "error",
retry: () => {
void events.refetch();
void sync.refresh();
},
};
if (!events.data) return { state: "loading" };
return {
state: "loaded",
events: events.data.events,
refreshing: events.isFetching,
refreshError: events.isError,
sourceError: sync.sourceError,
lastSuccessfulAt: events.meta?.lastSuccessfulAt,
partial: events.meta?.availability !== "complete",
refreshing: events.isFetching || sync.refreshing,
refreshError: events.isError || sync.sourceError || sync.transportError,
retry: () => {
void events.refetch();
void sync.refresh();
},
draftFrom,
draftTo,