diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts new file mode 100644 index 0000000..f72e134 --- /dev/null +++ b/web/src/lib/api.ts @@ -0,0 +1,121 @@ +import type { + Ticket, + Queue, + Transaction, + Scrip, + Lifecycle, + CustomField, + PreviewResult, + UpdateResult, +} from "./types"; + +const BASE_URL = "/api"; + +async function request(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(`/tickets${qs ? `?${qs}` : ""}`); +} + +export async function getTicket(id: string): Promise<{ data: Ticket | null; error: string | null }> { + return request(`/tickets/${id}`); +} + +export async function createTicket(data: { subject: string; queue_id: string }): Promise<{ data: Ticket | null; error: string | null }> { + return request("/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(`/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(`/tickets/${id}/preview`, { method: "POST", body: JSON.stringify(data) }); +} + +export async function getTicketTransactions(id: string): Promise<{ data: Transaction[] | null; error: string | null }> { + return request(`/tickets/${id}/transactions`); +} + +export async function getQueues(): Promise<{ data: Queue[] | null; error: string | null }> { + return request("/queues"); +} + +export async function createQueue(data: { name: string; description?: string }): Promise<{ data: Queue | null; error: string | null }> { + return request("/queues", { method: "POST", body: JSON.stringify(data) }); +} + +export async function getScrips(): Promise<{ data: Scrip[] | null; error: string | null }> { + return request("/scrips"); +} + +export async function createScrip(data: { + name: string; + queue_id?: string | null; + condition_type: string; + action_type: string; + action_config?: Record; + template_id?: string | null; + stage?: string; + sort_order?: number; + disabled?: boolean; +}): Promise<{ data: Scrip | null; error: string | null }> { + return request("/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; + template_id?: string | null; + stage?: string; + sort_order?: number; + disabled?: boolean; +}): Promise<{ data: Scrip | null; error: string | null }> { + return request(`/scrips/${id}`, { method: "PATCH", body: JSON.stringify(data) }); +} + +export async function getLifecycles(): Promise<{ data: Lifecycle[] | null; error: string | null }> { + return request("/lifecycles"); +} + +export async function createLifecycle(data: { + name: string; + definition: Record; +}): Promise<{ data: Lifecycle | null; error: string | null }> { + return request("/lifecycles", { method: "POST", body: JSON.stringify(data) }); +} + +export async function getCustomFields(): Promise<{ data: CustomField[] | null; error: string | null }> { + return request("/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("/custom-fields", { method: "POST", body: JSON.stringify(data) }); +}