feat: add API client, types, layout, and all page routes
This commit is contained in:
parent
2e4e3fba50
commit
b140c55cda
71 changed files with 3237 additions and 58 deletions
192
frontend/src/lib/api.ts
Normal file
192
frontend/src/lib/api.ts
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
import { PUBLIC_API_BASE } from '$env/static/public';
|
||||
import type {
|
||||
LabResult,
|
||||
MedicationEntry,
|
||||
MedicationUsage,
|
||||
Product,
|
||||
ProductInventory,
|
||||
Routine,
|
||||
RoutineStep,
|
||||
SkinConditionSnapshot
|
||||
} from './types';
|
||||
|
||||
// ─── Core fetch helpers ──────────────────────────────────────────────────────
|
||||
|
||||
async function request<T>(path: string, init: RequestInit = {}): Promise<T> {
|
||||
const url = `${PUBLIC_API_BASE}${path}`;
|
||||
const res = await fetch(url, {
|
||||
headers: { 'Content-Type': 'application/json', ...init.headers },
|
||||
...init
|
||||
});
|
||||
if (!res.ok) {
|
||||
const detail = await res.json().catch(() => ({ detail: res.statusText }));
|
||||
throw new Error(detail?.detail ?? res.statusText);
|
||||
}
|
||||
if (res.status === 204) return undefined as T;
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export const api = {
|
||||
get: <T>(path: string) => request<T>(path),
|
||||
post: <T>(path: string, body: unknown) =>
|
||||
request<T>(path, { method: 'POST', body: JSON.stringify(body) }),
|
||||
patch: <T>(path: string, body: unknown) =>
|
||||
request<T>(path, { method: 'PATCH', body: JSON.stringify(body) }),
|
||||
del: (path: string) => request<void>(path, { method: 'DELETE' })
|
||||
};
|
||||
|
||||
// ─── Products ────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface ProductListParams {
|
||||
category?: string;
|
||||
brand?: string;
|
||||
targets?: string[];
|
||||
is_medication?: boolean;
|
||||
is_tool?: boolean;
|
||||
}
|
||||
|
||||
export function getProducts(params: ProductListParams = {}): Promise<Product[]> {
|
||||
const q = new URLSearchParams();
|
||||
if (params.category) q.set('category', params.category);
|
||||
if (params.brand) q.set('brand', params.brand);
|
||||
if (params.targets) params.targets.forEach((t) => q.append('targets', t));
|
||||
if (params.is_medication != null) q.set('is_medication', String(params.is_medication));
|
||||
if (params.is_tool != null) q.set('is_tool', String(params.is_tool));
|
||||
const qs = q.toString();
|
||||
return api.get(`/products${qs ? `?${qs}` : ''}`);
|
||||
}
|
||||
|
||||
export const getProduct = (id: string): Promise<Product> => api.get(`/products/${id}`);
|
||||
export const createProduct = (body: Record<string, unknown>): Promise<Product> =>
|
||||
api.post('/products', body);
|
||||
export const updateProduct = (id: string, body: Record<string, unknown>): Promise<Product> =>
|
||||
api.patch(`/products/${id}`, body);
|
||||
export const deleteProduct = (id: string): Promise<void> => api.del(`/products/${id}`);
|
||||
|
||||
export const getInventory = (productId: string): Promise<ProductInventory[]> =>
|
||||
api.get(`/products/${productId}/inventory`);
|
||||
export const createInventory = (
|
||||
productId: string,
|
||||
body: Record<string, unknown>
|
||||
): Promise<ProductInventory> => api.post(`/products/${productId}/inventory`, body);
|
||||
|
||||
// ─── Routines ────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface RoutineListParams {
|
||||
from_date?: string;
|
||||
to_date?: string;
|
||||
part_of_day?: string;
|
||||
}
|
||||
|
||||
export function getRoutines(params: RoutineListParams = {}): Promise<Routine[]> {
|
||||
const q = new URLSearchParams();
|
||||
if (params.from_date) q.set('from_date', params.from_date);
|
||||
if (params.to_date) q.set('to_date', params.to_date);
|
||||
if (params.part_of_day) q.set('part_of_day', params.part_of_day);
|
||||
const qs = q.toString();
|
||||
return api.get(`/routines${qs ? `?${qs}` : ''}`);
|
||||
}
|
||||
|
||||
export const getRoutine = (id: string): Promise<Routine> => api.get(`/routines/${id}`);
|
||||
export const createRoutine = (body: Record<string, unknown>): Promise<Routine> =>
|
||||
api.post('/routines', body);
|
||||
export const updateRoutine = (id: string, body: Record<string, unknown>): Promise<Routine> =>
|
||||
api.patch(`/routines/${id}`, body);
|
||||
export const deleteRoutine = (id: string): Promise<void> => api.del(`/routines/${id}`);
|
||||
|
||||
export const addRoutineStep = (routineId: string, body: Record<string, unknown>): Promise<RoutineStep> =>
|
||||
api.post(`/routines/${routineId}/steps`, body);
|
||||
export const updateRoutineStep = (stepId: string, body: Record<string, unknown>): Promise<RoutineStep> =>
|
||||
api.patch(`/routines/steps/${stepId}`, body);
|
||||
export const deleteRoutineStep = (stepId: string): Promise<void> =>
|
||||
api.del(`/routines/steps/${stepId}`);
|
||||
|
||||
// ─── Health – Medications ────────────────────────────────────────────────────
|
||||
|
||||
export interface MedicationListParams {
|
||||
kind?: string;
|
||||
product_name?: string;
|
||||
}
|
||||
|
||||
export function getMedications(params: MedicationListParams = {}): Promise<MedicationEntry[]> {
|
||||
const q = new URLSearchParams();
|
||||
if (params.kind) q.set('kind', params.kind);
|
||||
if (params.product_name) q.set('product_name', params.product_name);
|
||||
const qs = q.toString();
|
||||
return api.get(`/health/medications${qs ? `?${qs}` : ''}`);
|
||||
}
|
||||
|
||||
export const getMedication = (id: string): Promise<MedicationEntry> =>
|
||||
api.get(`/health/medications/${id}`);
|
||||
export const createMedication = (body: Record<string, unknown>): Promise<MedicationEntry> =>
|
||||
api.post('/health/medications', body);
|
||||
export const updateMedication = (
|
||||
id: string,
|
||||
body: Record<string, unknown>
|
||||
): Promise<MedicationEntry> => api.patch(`/health/medications/${id}`, body);
|
||||
export const deleteMedication = (id: string): Promise<void> =>
|
||||
api.del(`/health/medications/${id}`);
|
||||
|
||||
export const getMedicationUsages = (medicationId: string): Promise<MedicationUsage[]> =>
|
||||
api.get(`/health/medications/${medicationId}/usages`);
|
||||
export const createMedicationUsage = (
|
||||
medicationId: string,
|
||||
body: Record<string, unknown>
|
||||
): Promise<MedicationUsage> => api.post(`/health/medications/${medicationId}/usages`, body);
|
||||
|
||||
// ─── Health – Lab results ────────────────────────────────────────────────────
|
||||
|
||||
export interface LabResultListParams {
|
||||
test_code?: string;
|
||||
flag?: string;
|
||||
lab?: string;
|
||||
from_date?: string;
|
||||
to_date?: string;
|
||||
}
|
||||
|
||||
export function getLabResults(params: LabResultListParams = {}): Promise<LabResult[]> {
|
||||
const q = new URLSearchParams();
|
||||
if (params.test_code) q.set('test_code', params.test_code);
|
||||
if (params.flag) q.set('flag', params.flag);
|
||||
if (params.lab) q.set('lab', params.lab);
|
||||
if (params.from_date) q.set('from_date', params.from_date);
|
||||
if (params.to_date) q.set('to_date', params.to_date);
|
||||
const qs = q.toString();
|
||||
return api.get(`/health/lab-results${qs ? `?${qs}` : ''}`);
|
||||
}
|
||||
|
||||
export const getLabResult = (id: string): Promise<LabResult> =>
|
||||
api.get(`/health/lab-results/${id}`);
|
||||
export const createLabResult = (body: Record<string, unknown>): Promise<LabResult> =>
|
||||
api.post('/health/lab-results', body);
|
||||
export const updateLabResult = (id: string, body: Record<string, unknown>): Promise<LabResult> =>
|
||||
api.patch(`/health/lab-results/${id}`, body);
|
||||
export const deleteLabResult = (id: string): Promise<void> =>
|
||||
api.del(`/health/lab-results/${id}`);
|
||||
|
||||
// ─── Skin ────────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface SnapshotListParams {
|
||||
from_date?: string;
|
||||
to_date?: string;
|
||||
overall_state?: string;
|
||||
}
|
||||
|
||||
export function getSkinSnapshots(params: SnapshotListParams = {}): Promise<SkinConditionSnapshot[]> {
|
||||
const q = new URLSearchParams();
|
||||
if (params.from_date) q.set('from_date', params.from_date);
|
||||
if (params.to_date) q.set('to_date', params.to_date);
|
||||
if (params.overall_state) q.set('overall_state', params.overall_state);
|
||||
const qs = q.toString();
|
||||
return api.get(`/skincare${qs ? `?${qs}` : ''}`);
|
||||
}
|
||||
|
||||
export const getSkinSnapshot = (id: string): Promise<SkinConditionSnapshot> =>
|
||||
api.get(`/skincare/${id}`);
|
||||
export const createSkinSnapshot = (body: Record<string, unknown>): Promise<SkinConditionSnapshot> =>
|
||||
api.post('/skincare', body);
|
||||
export const updateSkinSnapshot = (
|
||||
id: string,
|
||||
body: Record<string, unknown>
|
||||
): Promise<SkinConditionSnapshot> => api.patch(`/skincare/${id}`, body);
|
||||
export const deleteSkinSnapshot = (id: string): Promise<void> => api.del(`/skincare/${id}`);
|
||||
Loading…
Add table
Add a link
Reference in a new issue