feat(dashboard): add performance and operations slices

This commit is contained in:
jjbrunton committed 2026-08-08 15:10:52 +01:00
1 parent 20fa83f245
commit 5917b63755
13 files changed
+1059

No files matched your search

@@ -0,0 +1,73 @@
import {
DailyTrendResponseSchema,
StrategyPerformanceResponseSchema,
SubredditPerformanceResponseSchema,
SuccessfulExamplesResponseSchema,
} from '../../../../../packages/api-contracts/src/index.js';
import type { z } from 'zod';
type SubredditPerformanceResponse = z.infer<typeof SubredditPerformanceResponseSchema>;
type StrategyPerformanceResponse = z.infer<typeof StrategyPerformanceResponseSchema>;
type DailyTrendResponse = z.infer<typeof DailyTrendResponseSchema>;
type SuccessfulExamplesResponse = z.infer<typeof SuccessfulExamplesResponseSchema>;
async function parseResponse<T>(
response: Response,
schema: { parse(value: unknown): T },
): Promise<T> {
const payload: unknown = await response.json();
if (!response.ok) {
const message =
typeof payload === 'object' &&
payload !== null &&
'error' in payload &&
typeof payload.error === 'string'
? payload.error
: `Request failed (${response.status})`;
throw new Error(message);
}
return schema.parse(payload);
}
export interface PerformanceApi {
getSubredditPerformance(): Promise<SubredditPerformanceResponse>;
getStrategyPerformance(): Promise<StrategyPerformanceResponse>;
getDailyTrend(days: number): Promise<DailyTrendResponse>;
getSuccessfulExamples(): Promise<SuccessfulExamplesResponse>;
}
export function createPerformanceApi(
fetchImplementation?: typeof fetch,
) {
function request(path: string): Promise<Response> {
return (fetchImplementation ?? globalThis.fetch)(path);
}
return {
async getSubredditPerformance() {
return parseResponse(
await request('/api/analytics/by-subreddit'),
SubredditPerformanceResponseSchema,
);
},
async getStrategyPerformance() {
return parseResponse(
await request('/api/analytics/by-strategy'),
StrategyPerformanceResponseSchema,
);
},
async getDailyTrend(days: number) {
return parseResponse(
await request(`/api/analytics/trend?days=${days}`),
DailyTrendResponseSchema,
);
},
async getSuccessfulExamples() {
return parseResponse(
await request('/api/successful'),
SuccessfulExamplesResponseSchema,
);
},
} satisfies PerformanceApi;
}
export const performanceApi = createPerformanceApi();