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 { 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 { 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 = { '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 { 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 = { '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 { 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 = { '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 { 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 = { '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 { 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 = { '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; } }