feat: add settings and access dashboard slice

This commit is contained in:
jjbrunton committed 2026-08-08 15:25:34 +01:00
1 parent dcf2a1200c
commit 79de6aa2a1
11 files changed
+1066

No files matched your search

@@ -0,0 +1,58 @@
import type { ZodType } from 'zod';
import {
ConfigResponseSchema,
ConfigUpdateRequestSchema,
ConfigUpdateResponseSchema,
ErrorResponseSchema,
LoginInfoResponseSchema,
LoginStartResponseSchema,
LoginStatusResponseSchema,
type ConfigResponse,
type ConfigUpdateRequest,
type LoginStatusResponse,
} from '../../../../../packages/api-contracts/src/index.js';
async function parseResponse<T>(response: Response, schema: ZodType<T>): Promise<T> {
const payload: unknown = await response.json();
if (!response.ok) {
const parsedError = ErrorResponseSchema.safeParse(payload);
throw new Error(parsedError.success ? parsedError.data.error : `Request failed (${response.status})`);
}
return schema.parse(payload);
}
function request(path: string, init?: RequestInit): Promise<Response> {
return globalThis.fetch(path, { credentials: 'same-origin', ...init });
}
export function fetchSettings(): Promise<ConfigResponse> {
return request('/api/config').then((response) => parseResponse(response, ConfigResponseSchema));
}
export async function saveSettings(updates: ConfigUpdateRequest) {
const body = ConfigUpdateRequestSchema.parse(updates);
return parseResponse(
await request('/api/config', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
}),
ConfigUpdateResponseSchema,
);
}
export function fetchLoginInfo() {
return request('/api/login/info').then((response) => parseResponse(response, LoginInfoResponseSchema));
}
export function fetchLoginStatus(): Promise<LoginStatusResponse> {
return request('/api/login/status').then((response) => parseResponse(response, LoginStatusResponseSchema));
}
export async function startLogin(): Promise<void> {
const response = await parseResponse(
await request('/api/login/start', { method: 'POST' }),
LoginStartResponseSchema,
);
if (!response.ok) throw new Error(response.error);
}