140 lines
5.0 KiB
TypeScript
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/vehicles')
|
|
.then((r) => r.data.data);
|
|
}
|