Files
AgendaPro/src/lib/publicApi.ts
T
AgendaPro Dev d796538fd9 feat: rebrand AgendaPro -> AgendaMax + calendar fixes + current-week demo seed
- Rebrand all user-facing text to AgendaMax
- Fix sidebar scrolling: card container no longer overflows html (flex h-full min-h-0)
- Fix calendar toolbar hover: active buttons keep readable contrast
- Sticky calendar toolbar (month/week/day always visible on scroll)
- Seed guarantees 2-4 appointments per day for current week (Mon-Sat)
2026-07-27 10:11:16 -06:00

112 lines
2.5 KiB
TypeScript

import type { BookResponse } from "../../shared/types";
export type { BookResponse };
const BASE = "/api/public";
export interface PublicBusiness {
id: number;
name: string;
industry: string;
currency_symbol: string;
phone: string | null;
address: string | null;
booking_enabled: boolean;
cancel_window_hours: number;
cancel_penalty_pct: number;
require_deposit: boolean;
deposit_pct: number;
auto_assign_specialist: number | boolean;
}
export interface PublicService {
id: number;
name: string;
description: string | null;
category: string;
duration_min: number;
price: number;
color: string;
}
export interface PublicEmployee {
id: number;
name: string;
role: string;
color: string;
}
export interface PublicBusinessResponse {
business: PublicBusiness;
services: PublicService[];
employees: PublicEmployee[];
}
export interface PublicSlot {
time: string;
iso: string;
employee_id: number;
employee_name: string;
}
export interface PublicSlotsResponse {
slots: PublicSlot[];
service: Pick<PublicService, "id" | "name" | "price" | "duration_min">;
}
export interface BookClient {
name: string;
email?: string;
phone?: string;
notes?: string;
}
export interface BookPayload {
service_id: number;
employee_id?: number;
start_at: string;
client: BookClient;
}
async function request<T>(path: string, init?: RequestInit): Promise<T> {
const res = await fetch(`${BASE}${path}`, {
...init,
headers: {
"Content-Type": "application/json",
...(init?.headers as Record<string, string> | undefined),
},
});
if (!res.ok) {
let message = `Error ${res.status}`;
try {
const body = await res.json();
if (body?.error) message = body.error;
} catch {
/* ignore */
}
throw new Error(message);
}
return (await res.json()) as T;
}
export function getBusiness(slug: string): Promise<PublicBusinessResponse> {
return request<PublicBusinessResponse>(`/${slug}`);
}
export function getSlots(
slug: string,
serviceId: number,
date: string,
employeeId?: number
): Promise<PublicSlotsResponse> {
const q = new URLSearchParams({ service_id: String(serviceId), date });
if (employeeId) q.set("employee_id", String(employeeId));
return request<PublicSlotsResponse>(`/${slug}/slots?${q.toString()}`);
}
export function book(slug: string, payload: BookPayload): Promise<BookResponse> {
return request<BookResponse>(`/${slug}/book`, {
method: "POST",
body: JSON.stringify(payload),
});
}