Add typed fetch API client with 15 endpoint functions
This commit is contained in:
121
web/src/lib/api.ts
Normal file
121
web/src/lib/api.ts
Normal 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) });
|
||||
}
|
||||
Reference in New Issue
Block a user