One helper for every request
Every screen talks to the API. Put HTTP in one typed helper: it builds the URL (with properly encoded query strings), sends the request, and turns every outcome — success, 404, 422, 500, no network — into a Result the rest of the app understands.
The client
const BASE = "https://api.sikau.cafe";
function buildUrl(path: string, params: Record<string, string | number> = {}): string {
const query = new URLSearchParams();
for (const [key, value] of Object.entries(params)) query.set(key, String(value));
const qs = query.toString();
return BASE + path + (qs ? "?" + qs : "");
}
async function send<T>(url: string, init?: { method?: string; body?: string }): Promise<Result<T>> {
let res: FakeResponse;
try {
res = await fakeFetch(url, init);
} catch {
return { ok: false, error: "Network error" };
}
if (res.status >= 200 && res.status < 300) return { ok: true, value: JSON.parse(res.body) as T };
if (res.status === 404) return { ok: false, error: "Not found" };
if (res.status === 422) return { ok: false, error: (JSON.parse(res.body) as { error: string }).error };
return { ok: false, error: `HTTP ${res.status}` };
}
function getJson<T>(path: string, params?: Record<string, string | number>): Promise<Result<T>> {
return send<T>(buildUrl(path, params));
}
interface NewOrder { items: { id: string; qty: number }[] }
function createOrder(order: NewOrder): Promise<Result<{ number: string }>> {
return send<{ number: string }>(buildUrl("/orders"), { method: "POST", body: JSON.stringify(order) });
}