librebooking-ui/src/services/librebooking-api.ts
2026-02-06 10:36:40 +01:00

254 lines
7.7 KiB
TypeScript

import { Resource, CreateReservationRequest, Reservation } from '../types';
export class SimpleLibreBookingClient {
private baseUrl: string;
private sessionToken: string | null = null;
private userId: string | null = null;
constructor(baseUrl?: string) {
this.baseUrl = baseUrl || process.env.REACT_APP_LIBREBOOKING_API_URL || 'http://localhost:8080/Web';
}
async authenticate(username: string, password: string): Promise<boolean> {
try {
console.log('Attempting authentication with:', { username, baseUrl: this.baseUrl });
const response = await fetch(`${this.baseUrl}/Services/index.php/Authentication/Authenticate`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password }),
});
console.log('Authentication response status:', response.status);
const data = await response.json();
console.log('Authentication response data:', data);
if (response.ok && data.isAuthenticated) {
this.sessionToken = data.sessionToken;
this.userId = data.userId?.toString();
console.log('Authentication successful:', { sessionToken: this.sessionToken, userId: this.userId });
return true;
} else {
console.log('Authentication failed:', { status: response.status, data });
return false;
}
} catch (error) {
console.error('Authentication error:', error);
return false;
}
}
async getResources(): Promise<Resource[]> {
if (!this.sessionToken) {
const username = process.env.REACT_APP_LIBREBOOKING_USERNAME;
const password = process.env.REACT_APP_LIBREBOOKING_PASSWORD;
if (username && password) {
const authenticated = await this.authenticate(username, password);
if (!authenticated) {
throw new Error('Authentication failed');
}
}
}
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (this.sessionToken && this.userId) {
headers['X-Booked-SessionToken'] = this.sessionToken;
headers['X-Booked-UserId'] = this.userId;
}
const response = await fetch(`${this.baseUrl}/Services/index.php/Resources/`, {
headers,
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('Resources response:', data);
return data.resources || [];
}
async getResource(id: string): Promise<Resource | null> {
if (!this.sessionToken) {
const username = process.env.REACT_APP_LIBREBOOKING_USERNAME;
const password = process.env.REACT_APP_LIBREBOOKING_PASSWORD;
if (username && password) {
const authenticated = await this.authenticate(username, password);
if (!authenticated) {
throw new Error('Authentication failed');
}
}
}
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (this.sessionToken && this.userId) {
headers['X-Booked-SessionToken'] = this.sessionToken;
headers['X-Booked-UserId'] = this.userId;
}
const response = await fetch(`${this.baseUrl}/Services/index.php/Resources/${id}`, {
headers,
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('Resource response:', data);
return data || null;
}
async getReservations(resourceId?: string): Promise<Reservation[]> {
if (!this.sessionToken) {
const username = process.env.REACT_APP_LIBREBOOKING_USERNAME;
const password = process.env.REACT_APP_LIBREBOOKING_PASSWORD;
if (username && password) {
const authenticated = await this.authenticate(username, password);
if (!authenticated) {
throw new Error('Authentication failed');
}
}
}
// Use a wide date range to get all reservations
const today = new Date();
const threeMonthsAgo = new Date(today.getTime() - (90 * 24 * 60 * 60 * 1000));
const threeMonthsFromNow = new Date(today.getTime() + (90 * 24 * 60 * 60 * 1000));
const params = new URLSearchParams({
startDateTime: threeMonthsAgo.toISOString().split('.')[0] + 'Z',
endDateTime: threeMonthsFromNow.toISOString().split('.')[0] + 'Z',
});
if (resourceId) {
params.append('resourceId', resourceId);
}
const url = `${this.baseUrl}/Services/index.php/Reservations/?${params.toString()}`;
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (this.sessionToken && this.userId) {
headers['X-Booked-SessionToken'] = this.sessionToken;
headers['X-Booked-UserId'] = this.userId;
}
const response = await fetch(url, {
headers,
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('API date range:', {
start: data.startDateTime,
end: data.endDateTime
});
console.log('Found reservations:', data.reservations.length);
return data.reservations || [];
}
async createReservation(data: CreateReservationRequest): Promise<Reservation> {
if (!this.sessionToken) {
const username = process.env.REACT_APP_LIBREBOOKING_USERNAME;
const password = process.env.REACT_APP_LIBREBOOKING_PASSWORD;
if (username && password) {
const authenticated = await this.authenticate(username, password);
if (!authenticated) {
throw new Error('Authentication failed');
}
}
}
// Use the exact field names expected by LibreBooking API
const requestData = {
resourceId: data.resourceId,
startDateTime: data.startDateTime,
endDateTime: data.endDateTime,
title: data.title,
description: data.description || '',
allowParticipation: false,
termsAccepted: true
};
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (this.sessionToken && this.userId) {
headers['X-Booked-SessionToken'] = this.sessionToken;
headers['X-Booked-UserId'] = this.userId;
}
const response = await fetch(`${this.baseUrl}/Services/index.php/Reservations/`, {
method: 'POST',
headers,
body: JSON.stringify(requestData),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reservation = await response.json();
return reservation;
}
async updateReservationStatus(id: string, status: 'confirmed' | 'cancelled'): Promise<Reservation> {
if (!this.sessionToken) {
const username = process.env.REACT_APP_LIBREBOOKING_USERNAME;
const password = process.env.REACT_APP_LIBREBOOKING_PASSWORD;
if (username && password) {
const authenticated = await this.authenticate(username, password);
if (!authenticated) {
throw new Error('Authentication failed');
}
}
}
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (this.sessionToken && this.userId) {
headers['X-Booked-SessionToken'] = this.sessionToken;
headers['X-Booked-UserId'] = this.userId;
}
const response = await fetch(`${this.baseUrl}/Services/index.php/Reservations/${id}`, {
method: 'PUT',
headers,
body: JSON.stringify({ status }),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reservation = await response.json();
return reservation;
}
getUserId(): string | null {
return this.userId || null;
}
}