librebooking-ui/src/services/librebooking-api.ts
Joshua Schmucker bf4136b8dc Update
2026-01-30 14:32:53 +01:00

133 lines
3.9 KiB
TypeScript

import { Resource, Reservation, CreateReservationRequest } from '../types';
export interface LibreBookingAPIConfig {
baseURL: string;
apiKey?: string;
timeout?: number;
}
class LibreBookingAPIClient {
private config: LibreBookingAPIConfig;
private baseUrl: string;
constructor(config: LibreBookingAPIConfig) {
this.config = config;
this.baseUrl = config.baseURL.replace(/\/$/, ''); // Remove trailing slash
}
private async makeRequest<T>(
endpoint: string,
options: RequestInit = {}
): Promise<T> {
const url = `${this.baseUrl}${endpoint}`;
const headers: Record<string, string> = {
'Content-Type': 'application/json',
...(options.headers as Record<string, string> || {}),
};
if (this.config.apiKey) {
headers['Authorization'] = `Bearer ${this.config.apiKey}`;
}
try {
const response = await fetch(url, {
...options,
headers,
signal: AbortSignal.timeout(this.config.timeout || 10000),
});
if (!response.ok) {
throw new Error(`API Error: ${response.status} ${response.statusText}`);
}
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
return await response.json();
} else {
return response.text() as unknown as T;
}
} catch (error) {
if (error instanceof Error) {
throw new Error(`Network error: ${error.message}`);
}
throw error;
}
}
// Resources
async getResources(): Promise<Resource[]> {
return this.makeRequest<Resource[]>('/api/resources');
}
async getResource(id: string): Promise<Resource> {
return this.makeRequest<Resource>(`/api/resources/${id}`);
}
// Reservations
async getReservations(resourceId?: string): Promise<Reservation[]> {
const params = resourceId ? `?resourceId=${resourceId}` : '';
return this.makeRequest<Reservation[]>(`/api/reservations${params}`);
}
async getReservation(id: string): Promise<Reservation> {
return this.makeRequest<Reservation>(`/api/reservations/${id}`);
}
async createReservation(data: CreateReservationRequest): Promise<Reservation> {
return this.makeRequest<Reservation>('/api/reservations', {
method: 'POST',
body: JSON.stringify(data),
});
}
async updateReservationStatus(
id: string,
status: 'confirmed' | 'cancelled'
): Promise<Reservation> {
return this.makeRequest<Reservation>(`/api/reservations/${id}/status`, {
method: 'PATCH',
body: JSON.stringify({ status }),
});
}
async cancelReservation(id: string): Promise<Reservation> {
return this.makeRequest<Reservation>(`/api/reservations/${id}/cancel`, {
method: 'POST',
});
}
// Users (if needed for admin functions)
async getUsers(): Promise<any[]> {
return this.makeRequest<any[]>('/api/users');
}
async getUserReservations(userId: string): Promise<Reservation[]> {
return this.makeRequest<Reservation[]>(`/api/users/${userId}/reservations`);
}
}
// Factory function to create API client with environment variables
export function createLibreBookingClient(
config?: Partial<LibreBookingAPIConfig>
): LibreBookingAPIClient {
const defaultConfig: LibreBookingAPIConfig = {
baseURL: process.env.REACT_APP_LIBREBOOKING_API_URL || 'http://localhost:8080',
apiKey: process.env.REACT_APP_LIBREBOOKING_API_KEY,
timeout: 10000,
};
const finalConfig = { ...defaultConfig, ...config };
return new LibreBookingAPIClient(finalConfig);
}
// Example of how to integrate with the existing mock API
export function integrateWithMockAPI(mockAPI: any) {
return {
getResources: mockAPI.getResources,
getResource: mockAPI.getResource,
getReservations: mockAPI.getReservations,
createReservation: mockAPI.createReservation,
updateReservationStatus: mockAPI.updateReservationStatus,
};
}