v1.2 scaffold

This commit is contained in:
2026-04-25 20:43:37 +12:00
parent 658cda8c35
commit bc211ffcc8
58 changed files with 5104 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
import { env } from '$env/dynamic/public';
import { mockCosts, mockMixes, mockProducts, mockRawMaterials, mockScenarios } from '$lib/mock';
import type {
LoginResponse,
Product,
ProductCostBreakdown,
RawMaterial,
RawMaterialCreateInput,
RawMaterialPriceCreateInput,
Scenario
} from '$lib/types';
const API_BASE_URL = env.PUBLIC_API_BASE_URL || 'http://localhost:8000';
async function fetchJson<T>(path: string, fallback: T): Promise<T> {
try {
const response = await fetch(`${API_BASE_URL}${path}`);
if (!response.ok) {
return fallback;
}
return (await response.json()) as T;
} catch {
return fallback;
}
}
async function request<T>(path: string, options: RequestInit): Promise<T> {
const response = await fetch(`${API_BASE_URL}${path}`, {
headers: {
'Content-Type': 'application/json',
...(options.headers ?? {})
},
...options
});
if (!response.ok) {
let message = 'Request failed';
try {
const body = (await response.json()) as { detail?: string };
message = body.detail ?? message;
} catch {
message = response.statusText || message;
}
throw new Error(message);
}
return (await response.json()) as T;
}
export const api = {
rawMaterials: () => fetchJson<RawMaterial[]>('/api/raw-materials', mockRawMaterials),
mixes: () => fetchJson('/api/mixes', mockMixes),
products: () => fetchJson<Product[]>('/api/products', mockProducts),
productCosts: () => fetchJson<ProductCostBreakdown[]>('/api/powerbi/product-costs', mockCosts),
scenarios: () => fetchJson<Scenario[]>('/api/scenarios', mockScenarios),
dataQuality: () => fetchJson('/api/powerbi/data-quality-issues', []),
login: (email: string, password: string) =>
request<LoginResponse>('/api/auth/login', {
method: 'POST',
body: JSON.stringify({ email, password })
}),
createRawMaterial: (payload: RawMaterialCreateInput) =>
request<RawMaterial>('/api/raw-materials', {
method: 'POST',
body: JSON.stringify(payload)
}),
addRawMaterialPrice: (rawMaterialId: number, payload: RawMaterialPriceCreateInput) =>
request(`/api/raw-materials/${rawMaterialId}/prices`, {
method: 'POST',
body: JSON.stringify(payload)
})
};