This commit is contained in:
Matthias Hochmeister
2026-03-16 15:01:09 +01:00
parent 3c72fe627f
commit f3ad989a9e
28 changed files with 794 additions and 52 deletions

View File

@@ -1,5 +1,5 @@
import { api } from './api';
import type { MonitoredService, PingResult, PingHistoryEntry, StatusSummary, SystemHealth, UserOverview, BroadcastPayload } from '../types/admin.types';
import type { MonitoredService, PingResult, PingHistoryEntry, StatusSummary, SystemHealth, UserOverview, BroadcastPayload, BroadcastPreviewPayload } from '../types/admin.types';
interface ApiResponse<T> {
success: boolean;
@@ -26,6 +26,7 @@ export const adminApi = {
getSystemHealth: () => api.get<ApiResponse<SystemHealth>>('/api/admin/system/health').then(r => r.data.data),
getUsers: () => api.get<ApiResponse<UserOverview[]>>('/api/admin/users').then(r => r.data.data),
broadcast: (data: BroadcastPayload) => api.post<ApiResponse<{ sent: number }>>('/api/admin/notifications/broadcast', data).then(r => r.data.data),
broadcastPreview: (data: BroadcastPreviewPayload) => api.post<ApiResponse<{ count: number }>>('/api/admin/notifications/broadcast/preview', data).then(r => r.data.data),
getPingHistory: (serviceId: string) => api.get<ApiResponse<PingHistoryEntry[]>>(`/api/admin/services/${serviceId}/ping-history`).then(r => r.data.data),
fdiskSyncLogs: () => api.get<ApiResponse<FdiskSyncLogsResponse>>('/api/admin/fdisk-sync/logs').then(r => r.data.data),
fdiskSyncTrigger: (force = false) => api.post<ApiResponse<{ started: boolean }>>('/api/admin/fdisk-sync/trigger', { force }).then(r => r.data.data),

View File

@@ -76,4 +76,9 @@ export const atemschutzApi = {
async delete(id: string): Promise<void> {
await api.delete(`/api/atemschutz/${id}`);
},
async getExpiring(): Promise<any[]> {
const response = await api.get<{ success: boolean; data: any[] }>('/api/atemschutz/expiring');
return response.data?.data ?? [];
},
};

View File

@@ -4,6 +4,7 @@ import type {
FahrzeugBuchung,
Fahrzeug,
CreateBuchungInput,
MaintenanceWindow,
} from '../types/booking.types';
// ---------------------------------------------------------------------------
@@ -22,15 +23,22 @@ export const bookingApi = {
// Calendar / listing
// -------------------------------------------------------------------------
getCalendarRange(from: Date, to: Date, fahrzeugId?: string): Promise<FahrzeugBuchungListItem[]> {
getCalendarRange(
from: Date,
to: Date,
fahrzeugId?: string
): Promise<{ bookings: FahrzeugBuchungListItem[]; maintenanceWindows: MaintenanceWindow[] }> {
return api
.get<ApiResponse<FahrzeugBuchungListItem[]>>('/api/bookings/calendar', {
params: {
from: from.toISOString(),
to: to.toISOString(),
...(fahrzeugId ? { fahrzeugId } : {}),
},
})
.get<ApiResponse<{ bookings: FahrzeugBuchungListItem[]; maintenanceWindows: MaintenanceWindow[] }>>(
'/api/bookings/calendar',
{
params: {
from: from.toISOString(),
to: to.toISOString(),
...(fahrzeugId ? { fahrzeugId } : {}),
},
}
)
.then((r) => r.data.data);
},

View File

@@ -5,6 +5,7 @@ import type {
Veranstaltung,
GroupInfo,
CreateVeranstaltungInput,
ConflictEvent,
} from '../types/events.types';
// ---------------------------------------------------------------------------
@@ -153,4 +154,13 @@ export const eventsApi = {
.post<ApiResponse<{ created: number; errors: string[] }>>('/api/events/import', { events })
.then((r) => r.data.data);
},
/** Check for overlapping events in a time range */
checkConflicts(from: string, to: string, excludeId?: string): Promise<ConflictEvent[]> {
return api
.get<ApiResponse<ConflictEvent[]>>('/api/events/conflicts', {
params: { from, to, ...(excludeId ? { excludeId } : {}) },
})
.then((r) => r.data.data);
},
};

View File

@@ -93,4 +93,11 @@ export const vehiclesApi = {
}
return response.data.data;
},
async exportAlerts(): Promise<Blob> {
const response = await api.get('/api/vehicles/alerts/export', {
responseType: 'blob',
});
return response.data as Blob;
},
};