Initial commit: twin-optimiser sub-app (housekeeping category)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-07-02 20:14:01 +00:00
commit a695bd843f
28 changed files with 1913 additions and 0 deletions

36
frontend/src/api.ts Normal file
View file

@ -0,0 +1,36 @@
import type { GridData, AppSettings } from './types'
const BASE = '/twin-optimiser/api'
async function request<T>(path: string, opts?: RequestInit): Promise<T> {
const res = await fetch(BASE + path, { credentials: 'include', ...opts })
if (!res.ok) {
const body = await res.json().catch(() => ({})) as { error?: string }
throw new Error(body.error || `HTTP ${res.status}`)
}
return res.json() as Promise<T>
}
export function getGrid(startDate?: string, days = 14, force = false): Promise<GridData> {
const p = new URLSearchParams()
if (startDate) p.set('start_date', startDate)
p.set('days', String(days))
if (force) p.set('force', '1')
return request<GridData>(`/grid?${p}`)
}
export function getSettings(): Promise<AppSettings> {
return request<AppSettings>('/settings')
}
export function postSettings(settings: Partial<AppSettings>): Promise<AppSettings> {
return request<AppSettings>('/settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(settings),
})
}
export function testNewbook(): Promise<{ ok: boolean; message?: string; error?: string }> {
return request('/newbook/test', { method: 'POST' })
}