Add typed fetch API client with 15 endpoint functions

This commit is contained in:
Gjermund Høsøien Wiggen
2026-06-07 22:02:01 +02:00
parent 59d66b3392
commit 00dd21f4dd

121
web/src/lib/api.ts Normal file
View File

@@ -0,0 +1,121 @@
import type {
Ticket,
Queue,
Transaction,
Scrip,
Lifecycle,
CustomField,
PreviewResult,
UpdateResult,
} from "./types";
const BASE_URL = "/api";
async function request<T>(url: string, options?: RequestInit): Promise<{ data: T | null; error: string | null }> {
try {
const res = await fetch(`${BASE_URL}${url}`, {
headers: { "Content-Type": "application/json" },
...options,
});
if (!res.ok) {
const body = await res.json().catch(() => ({ error: res.statusText }));
return { data: null, error: body.error || body.message || `HTTP ${res.status}` };
}
const data = await res.json();
return { data, error: null };
} catch (err) {
return { data: null, error: err instanceof Error ? err.message : "Unknown error" };
}
}
export async function getTickets(params?: { queue_id?: string; status?: string }): Promise<{ data: Ticket[] | null; error: string | null }> {
const sp = new URLSearchParams();
if (params?.queue_id) sp.set("queue_id", params.queue_id);
if (params?.status) sp.set("status", params.status);
const qs = sp.toString();
return request<Ticket[]>(`/tickets${qs ? `?${qs}` : ""}`);
}
export async function getTicket(id: string): Promise<{ data: Ticket | null; error: string | null }> {
return request<Ticket>(`/tickets/${id}`);
}
export async function createTicket(data: { subject: string; queue_id: string }): Promise<{ data: Ticket | null; error: string | null }> {
return request<Ticket>("/tickets", { method: "POST", body: JSON.stringify(data) });
}
export async function updateTicket(id: string, data: { subject?: string; status?: string }): Promise<{ data: UpdateResult | null; error: string | null }> {
return request<UpdateResult>(`/tickets/${id}`, { method: "PATCH", body: JSON.stringify(data) });
}
export async function previewTicket(id: string, data: { status?: string }): Promise<{ data: PreviewResult | null; error: string | null }> {
return request<PreviewResult>(`/tickets/${id}/preview`, { method: "POST", body: JSON.stringify(data) });
}
export async function getTicketTransactions(id: string): Promise<{ data: Transaction[] | null; error: string | null }> {
return request<Transaction[]>(`/tickets/${id}/transactions`);
}
export async function getQueues(): Promise<{ data: Queue[] | null; error: string | null }> {
return request<Queue[]>("/queues");
}
export async function createQueue(data: { name: string; description?: string }): Promise<{ data: Queue | null; error: string | null }> {
return request<Queue>("/queues", { method: "POST", body: JSON.stringify(data) });
}
export async function getScrips(): Promise<{ data: Scrip[] | null; error: string | null }> {
return request<Scrip[]>("/scrips");
}
export async function createScrip(data: {
name: string;
queue_id?: string | null;
condition_type: string;
action_type: string;
action_config?: Record<string, unknown>;
template_id?: string | null;
stage?: string;
sort_order?: number;
disabled?: boolean;
}): Promise<{ data: Scrip | null; error: string | null }> {
return request<Scrip>("/scrips", { method: "POST", body: JSON.stringify(data) });
}
export async function updateScrip(id: string, data: {
name?: string;
queue_id?: string | null;
condition_type?: string;
action_type?: string;
action_config?: Record<string, unknown>;
template_id?: string | null;
stage?: string;
sort_order?: number;
disabled?: boolean;
}): Promise<{ data: Scrip | null; error: string | null }> {
return request<Scrip>(`/scrips/${id}`, { method: "PATCH", body: JSON.stringify(data) });
}
export async function getLifecycles(): Promise<{ data: Lifecycle[] | null; error: string | null }> {
return request<Lifecycle[]>("/lifecycles");
}
export async function createLifecycle(data: {
name: string;
definition: Record<string, unknown>;
}): Promise<{ data: Lifecycle | null; error: string | null }> {
return request<Lifecycle>("/lifecycles", { method: "POST", body: JSON.stringify(data) });
}
export async function getCustomFields(): Promise<{ data: CustomField[] | null; error: string | null }> {
return request<CustomField[]>("/custom-fields");
}
export async function createCustomField(data: {
name: string;
field_type: string;
values?: unknown | null;
max_values?: number;
}): Promise<{ data: CustomField | null; error: string | null }> {
return request<CustomField>("/custom-fields", { method: "POST", body: JSON.stringify(data) });
}