Files
dashboard/frontend/src/services/bookings.ts
2026-03-26 08:47:38 +01:00

140 lines
5.0 KiB
TypeScript

import { api } from './api';
import type {
FahrzeugBuchungListItem,
FahrzeugBuchung,
Fahrzeug,
CreateBuchungInput,
MaintenanceWindow,
BuchungsKategorie,
} from '../types/booking.types';
// ---------------------------------------------------------------------------
// Response shapes from the backend
// ---------------------------------------------------------------------------
interface ApiResponse<T> {
success: boolean;
data: T;
}
// ---------------------------------------------------------------------------
// Booking API service
// ---------------------------------------------------------------------------
export const bookingApi = {
// -------------------------------------------------------------------------
// Calendar / listing
// -------------------------------------------------------------------------
getCalendarRange(
from: Date,
to: Date,
fahrzeugId?: string
): Promise<{ bookings: FahrzeugBuchungListItem[]; maintenanceWindows: MaintenanceWindow[] }> {
return api
.get<ApiResponse<{ bookings: FahrzeugBuchungListItem[]; maintenanceWindows: MaintenanceWindow[] }>>(
'/api/bookings/calendar',
{
params: {
from: from.toISOString(),
to: to.toISOString(),
...(fahrzeugId ? { fahrzeugId } : {}),
},
}
)
.then((r) => r.data.data);
},
getUpcoming(limit = 20): Promise<FahrzeugBuchungListItem[]> {
return api
.get<ApiResponse<FahrzeugBuchungListItem[]>>('/api/bookings/upcoming', {
params: { limit },
})
.then((r) => r.data.data);
},
// -------------------------------------------------------------------------
// Availability check
// -------------------------------------------------------------------------
checkAvailability(
fahrzeugId: string,
from: Date,
to: Date,
excludeId?: string
): Promise<{ available: boolean; reason?: string; ausserDienstVon?: string; ausserDienstBis?: string }> {
return api
.get<ApiResponse<{ available: boolean; reason?: string; ausserDienstVon?: string; ausserDienstBis?: string }>>('/api/bookings/availability', {
params: {
fahrzeugId,
from: from.toISOString(),
to: to.toISOString(),
...(excludeId ? { excludeId } : {}),
},
})
.then((r) => r.data.data);
},
// -------------------------------------------------------------------------
// Single booking
// -------------------------------------------------------------------------
getById(id: string): Promise<FahrzeugBuchung> {
return api
.get<ApiResponse<FahrzeugBuchung>>(`/api/bookings/${id}`)
.then((r) => r.data.data);
},
// -------------------------------------------------------------------------
// CRUD
// -------------------------------------------------------------------------
create(data: CreateBuchungInput): Promise<FahrzeugBuchung> {
return api
.post<ApiResponse<FahrzeugBuchung>>('/api/bookings', data)
.then((r) => r.data.data);
},
update(id: string, data: Partial<CreateBuchungInput>): Promise<FahrzeugBuchung> {
return api
.patch<ApiResponse<FahrzeugBuchung>>(`/api/bookings/${id}`, data)
.then((r) => r.data.data);
},
cancel(id: string, abgesagt_grund: string): Promise<void> {
return api
.patch(`/api/bookings/${id}/cancel`, { abgesagt_grund })
.then(() => undefined);
},
// -------------------------------------------------------------------------
// iCal
// -------------------------------------------------------------------------
getCalendarToken(): Promise<{ token: string; subscribeUrl: string }> {
return api
.get<ApiResponse<{ token: string; subscribeUrl: string }>>(
'/api/bookings/calendar-token'
)
.then((r) => r.data.data);
},
};
// ---------------------------------------------------------------------------
// Booking categories
// ---------------------------------------------------------------------------
export const kategorieApi = {
getAll: () => api.get<{ success: boolean; data: BuchungsKategorie[] }>('/api/buchungskategorien').then((r) => r.data.data),
getActive: () => api.get<{ success: boolean; data: BuchungsKategorie[] }>('/api/buchungskategorien/active').then((r) => r.data.data),
create: (data: Omit<BuchungsKategorie, 'id'>) => api.post<{ success: boolean; data: BuchungsKategorie }>('/api/buchungskategorien', data).then((r) => r.data.data),
update: (id: number, data: Partial<BuchungsKategorie>) => api.patch<{ success: boolean; data: BuchungsKategorie }>(`/api/buchungskategorien/${id}`, data).then((r) => r.data.data),
delete: (id: number) => api.delete(`/api/buchungskategorien/${id}`).then((r) => r.data),
};
// ---------------------------------------------------------------------------
// Vehicle helper (shared with booking page)
// ---------------------------------------------------------------------------
export function fetchVehicles(): Promise<Fahrzeug[]> {
return api
.get<ApiResponse<Fahrzeug[]>>('/api/bookings/vehicles')
.then((r) => r.data.data);
}