update
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect, useCallback, useMemo } from 'react';
|
||||
import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
@@ -60,6 +60,7 @@ import type {
|
||||
VeranstaltungKategorie,
|
||||
GroupInfo,
|
||||
CreateVeranstaltungInput,
|
||||
ConflictEvent,
|
||||
} from '../types/events.types';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -609,6 +610,46 @@ function EventFormDialog({
|
||||
}
|
||||
}, [open, editingEvent]);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Conflict detection — debounced check when dates change
|
||||
// -----------------------------------------------------------------------
|
||||
const [conflicts, setConflicts] = useState<ConflictEvent[]>([]);
|
||||
const conflictTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Clear conflicts when dialog closes
|
||||
if (!open) {
|
||||
setConflicts([]);
|
||||
return;
|
||||
}
|
||||
|
||||
const vonDate = new Date(form.datum_von);
|
||||
const bisDate = new Date(form.datum_bis);
|
||||
if (isNaN(vonDate.getTime()) || isNaN(bisDate.getTime()) || bisDate <= vonDate) {
|
||||
setConflicts([]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (conflictTimerRef.current) clearTimeout(conflictTimerRef.current);
|
||||
conflictTimerRef.current = setTimeout(async () => {
|
||||
try {
|
||||
const result = await eventsApi.checkConflicts(
|
||||
vonDate.toISOString(),
|
||||
bisDate.toISOString(),
|
||||
editingEvent?.id
|
||||
);
|
||||
setConflicts(result);
|
||||
} catch {
|
||||
// Silently ignore — conflict check is advisory only
|
||||
setConflicts([]);
|
||||
}
|
||||
}, 500);
|
||||
|
||||
return () => {
|
||||
if (conflictTimerRef.current) clearTimeout(conflictTimerRef.current);
|
||||
};
|
||||
}, [open, form.datum_von, form.datum_bis, editingEvent]);
|
||||
|
||||
const handleChange = (field: keyof CreateVeranstaltungInput, value: unknown) => {
|
||||
if (field === 'kategorie_id' && !editingEvent) {
|
||||
// Auto-fill zielgruppen / alle_gruppen from the selected category (only for new events)
|
||||
@@ -771,6 +812,31 @@ function EventFormDialog({
|
||||
fullWidth
|
||||
/>
|
||||
|
||||
{/* Conflict warning */}
|
||||
{conflicts.length > 0 && (
|
||||
<Alert severity="warning" sx={{ mt: 0 }}>
|
||||
<Typography variant="body2" fontWeight={600} sx={{ mb: 0.5 }}>
|
||||
Überschneidung mit bestehenden Veranstaltungen:
|
||||
</Typography>
|
||||
{conflicts.map((c) => {
|
||||
const von = new Date(c.datum_von);
|
||||
const bis = new Date(c.datum_bis);
|
||||
const fmtDate = (d: Date) =>
|
||||
`${String(d.getDate()).padStart(2, '0')}.${String(d.getMonth() + 1).padStart(2, '0')}.${d.getFullYear()}`;
|
||||
const fmtTime = (d: Date) =>
|
||||
`${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
|
||||
const range = sameDay(von, bis)
|
||||
? `${fmtDate(von)} ${fmtTime(von)} - ${fmtTime(bis)}`
|
||||
: `${fmtDate(von)} ${fmtTime(von)} - ${fmtDate(bis)} ${fmtTime(bis)}`;
|
||||
return (
|
||||
<Typography key={c.id} variant="body2">
|
||||
{'\u2022'} "{c.titel}" ({range})
|
||||
</Typography>
|
||||
);
|
||||
})}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{/* Ort */}
|
||||
<TextField
|
||||
label="Ort"
|
||||
|
||||
Reference in New Issue
Block a user