Review a React dashboard data waterfall

src/dashboard-api.tsTypeScript
@@ -0,0 +1,58 @@
1+export interface Account {
2+ readonly id: string;
3+ readonly name: string;
4+}
5+
6+export interface Summary {
7+ readonly totalCents: number;
8+ readonly windowStart: string;
9+ readonly trend: readonly number[];
10+}
11+
12+export interface Alert {
13+ readonly id: string;
14+ readonly message: string;
15+}
16+
17+async function requestJson<T>(path: string): Promise<T> {
18+ const response = await fetch(path);
19+ if (!response.ok) {
20+ throw new Error(`Dashboard request failed: ${response.status}`);
21+ }
22+ return (await response.json()) as T;
23+}
24+
25+export function loadAccount(accountId: string): Promise<Account> {
26+ return requestJson(`/api/accounts/${encodeURIComponent(accountId)}`);
27+}
28+
29+export async function loadSummary(accountId: string): Promise<Summary> {
30+ const totals = await requestJson<{
31+ totalCents: number;
32+ windowStart: string;
33+ }>(`/api/accounts/${accountId}/totals`);
34+ const trend = await requestJson<readonly number[]>(
35+ `/api/accounts/${accountId}/trend`,
36+ );
37+
38+ return { ...totals, trend };
39+}
40+
41+export function loadAlerts(accountId: string): Promise<readonly Alert[]> {
42+ return requestJson(`/api/accounts/${accountId}/alerts`);
43+}
44+
45+export function loadActivity(
46+ accountId: string,
47+ windowStart: string,
48+): Promise<readonly string[]> {
49+ return requestJson(
50+ `/api/accounts/${accountId}/activity?from=${encodeURIComponent(windowStart)}`,
51+ );
52+}
53+
54+export function loadRecommendations(
55+ accountId: string,
56+): Promise<readonly string[]> {
57+ return requestJson(`/api/accounts/${accountId}/recommendations`);
58+}