118 lines
3.4 KiB
TypeScript
118 lines
3.4 KiB
TypeScript
// Use VITE_API_URL if set at build time, otherwise derive from current origin
|
|
const API_URL = import.meta.env.VITE_API_URL || `${window.location.origin}/api`;
|
|
|
|
export interface ParticipantAPI {
|
|
id: string;
|
|
name: string;
|
|
email: string;
|
|
timezone: string;
|
|
ics_url: string | null;
|
|
created_at: string;
|
|
updated_at: string;
|
|
}
|
|
|
|
export interface TimeSlotAPI {
|
|
day: string;
|
|
hour: number;
|
|
start_time: string;
|
|
availability: 'full' | 'partial' | 'none';
|
|
availableParticipants: string[];
|
|
}
|
|
|
|
export interface CreateParticipantRequest {
|
|
name: string;
|
|
email: string;
|
|
timezone: string;
|
|
ics_url?: string;
|
|
}
|
|
|
|
export interface UpdateParticipantRequest {
|
|
timezone?: string;
|
|
ics_url?: string;
|
|
}
|
|
|
|
async function handleResponse<T>(response: Response): Promise<T> {
|
|
if (!response.ok) {
|
|
const error = await response.json().catch(() => ({ detail: 'Request failed' }));
|
|
throw new Error(error.detail || 'Request failed');
|
|
}
|
|
return response.json();
|
|
}
|
|
|
|
export async function fetchParticipants(): Promise<ParticipantAPI[]> {
|
|
const response = await fetch(`${API_URL}/api/participants`);
|
|
return handleResponse<ParticipantAPI[]>(response);
|
|
}
|
|
|
|
export async function createParticipant(data: CreateParticipantRequest): Promise<ParticipantAPI> {
|
|
const response = await fetch(`${API_URL}/api/participants`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(data),
|
|
});
|
|
return handleResponse<ParticipantAPI>(response);
|
|
}
|
|
|
|
export async function updateParticipant(id: string, data: UpdateParticipantRequest): Promise<ParticipantAPI> {
|
|
const response = await fetch(`${API_URL}/api/participants/${id}`, {
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(data),
|
|
});
|
|
return handleResponse<ParticipantAPI>(response);
|
|
}
|
|
|
|
export async function deleteParticipant(id: string): Promise<void> {
|
|
const response = await fetch(`${API_URL}/api/participants/${id}`, {
|
|
method: 'DELETE',
|
|
});
|
|
if (!response.ok) {
|
|
throw new Error('Failed to delete participant');
|
|
}
|
|
}
|
|
|
|
export async function fetchAvailability(participantIds: string[]): Promise<TimeSlotAPI[]> {
|
|
const response = await fetch(`${API_URL}/api/availability`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ participant_ids: participantIds }),
|
|
});
|
|
const data = await handleResponse<{ slots: TimeSlotAPI[] }>(response);
|
|
return data.slots;
|
|
}
|
|
|
|
export async function syncCalendars(): Promise<void> {
|
|
const response = await fetch(`${API_URL}/api/sync`, { method: 'POST' });
|
|
if (!response.ok) {
|
|
throw new Error('Failed to sync calendars');
|
|
}
|
|
}
|
|
|
|
export async function syncParticipant(id: string): Promise<void> {
|
|
const response = await fetch(`${API_URL}/api/sync/${id}`, { method: 'POST' });
|
|
if (!response.ok) {
|
|
throw new Error('Failed to sync participant calendar');
|
|
}
|
|
}
|
|
|
|
export async function scheduleMeeting(
|
|
participantIds: string[],
|
|
title: string,
|
|
description: string,
|
|
startTime: string,
|
|
endTime: string,
|
|
): Promise<{ email_sent: boolean; zulip_sent: boolean }> {
|
|
const response = await fetch(`${API_URL}/api/schedule`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
participant_ids: participantIds,
|
|
title,
|
|
description,
|
|
start_time: startTime,
|
|
end_time: endTime,
|
|
}),
|
|
});
|
|
return handleResponse(response);
|
|
}
|