Neah/components/calendar/event-dialog.tsx
2025-04-17 11:39:15 +02:00

262 lines
7.7 KiB
TypeScript

import { useState, useEffect } from "react";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogFooter,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import { Checkbox } from "@/components/ui/checkbox";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { format, parseISO } from "date-fns";
import { fr } from "date-fns/locale";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Calendar as CalendarType } from "@prisma/client";
interface EventDialogProps {
open: boolean;
event?: any;
onClose: () => void;
onSave: (eventData: any) => Promise<void>;
onDelete?: (eventId: string) => Promise<void>;
calendars: CalendarType[];
}
export function EventDialog({
open,
event,
onClose,
onSave,
onDelete,
calendars,
}: EventDialogProps) {
const [title, setTitle] = useState(event?.title || "");
const [description, setDescription] = useState(event?.description || "");
const [location, setLocation] = useState(event?.location || "");
const [start, setStart] = useState(event?.start || "");
const [end, setEnd] = useState(event?.end || "");
const [allDay, setAllDay] = useState(event?.allDay || false);
const [calendarId, setCalendarId] = useState(event?.calendarId || "");
const [confirmDelete, setConfirmDelete] = useState(false);
// Formater les dates pour l'affichage
const formatDate = (dateStr: string) => {
if (!dateStr) return "";
try {
// @ts-ignore
const date = parseISO(dateStr);
// @ts-ignore
return format(date, allDay ? "yyyy-MM-dd" : "yyyy-MM-dd'T'HH:mm", {
// @ts-ignore
locale: fr,
});
} catch (e) {
return dateStr;
}
};
// Gérer le changement de l'option "Toute la journée"
const handleAllDayChange = (checked: boolean) => {
setAllDay(checked);
// Ajuster les dates si nécessaire
if (checked && start) {
// @ts-ignore
const startDate = parseISO(start);
// @ts-ignore
setStart(format(startDate, "yyyy-MM-dd"));
if (end) {
// @ts-ignore
const endDate = parseISO(end);
// @ts-ignore
setEnd(format(endDate, "yyyy-MM-dd"));
}
}
};
// Enregistrer l'événement
const handleSave = () => {
onSave({
id: event?.id,
title,
description,
location,
start,
end,
calendarId,
isAllDay: allDay,
});
};
// Supprimer l'événement
const handleDelete = () => {
if (onDelete && event?.id) {
onDelete(event.id);
}
};
return (
<>
<Dialog open={open} onOpenChange={onClose}>
<DialogContent className='sm:max-w-[550px]'>
<DialogHeader>
<DialogTitle>
{event?.id ? "Modifier l'événement" : "Nouvel événement"}
</DialogTitle>
</DialogHeader>
<div className='grid gap-4 py-4'>
<div className='grid gap-2'>
<Label htmlFor='title'>Titre *</Label>
<Input
id='title'
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder='Ajouter un titre'
required
/>
</div>
{/* Sélection du calendrier */}
<div className='grid gap-2'>
<Label htmlFor='calendar'>Calendrier *</Label>
<Select value={calendarId} onValueChange={setCalendarId} required>
<SelectTrigger>
<SelectValue placeholder='Sélectionner un calendrier' />
</SelectTrigger>
<SelectContent>
{calendars.map((calendar) => (
<SelectItem key={calendar.id} value={calendar.id}>
<div className='flex items-center gap-2'>
<div
className='w-3 h-3 rounded-full'
style={{ backgroundColor: calendar.color }}
/>
<span>{calendar.name}</span>
</div>
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className='grid grid-cols-2 gap-4'>
<div className='grid gap-2'>
<Label htmlFor='start-date'>Début *</Label>
<Input
type={allDay ? "date" : "datetime-local"}
id='start-date'
value={formatDate(start)}
onChange={(e) => setStart(e.target.value)}
required
/>
</div>
<div className='grid gap-2'>
<Label htmlFor='end-date'>Fin *</Label>
<Input
type={allDay ? "date" : "datetime-local"}
id='end-date'
value={formatDate(end)}
onChange={(e) => setEnd(e.target.value)}
required
/>
</div>
</div>
<div className='flex items-center gap-2'>
<Checkbox
id='all-day'
checked={allDay}
onCheckedChange={handleAllDayChange}
/>
<Label htmlFor='all-day'>Toute la journée</Label>
</div>
<div className='grid gap-2'>
<Label htmlFor='location'>Lieu (optionnel)</Label>
<Input
id='location'
value={location}
onChange={(e) => setLocation(e.target.value)}
placeholder='Ajouter un lieu'
/>
</div>
<div className='grid gap-2'>
<Label htmlFor='description'>Description (optionnel)</Label>
<Textarea
id='description'
value={description}
onChange={(e) => setDescription(e.target.value)}
placeholder='Ajouter une description'
rows={3}
/>
</div>
</div>
<DialogFooter>
{event?.id && onDelete && (
<Button
variant='destructive'
onClick={() => setConfirmDelete(true)}
type='button'
>
Supprimer
</Button>
)}
<Button variant='outline' onClick={onClose} type='button'>
Annuler
</Button>
<Button
onClick={handleSave}
disabled={!title || !start || !end || !calendarId}
type='button'
>
Enregistrer
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<AlertDialog open={confirmDelete} onOpenChange={setConfirmDelete}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Supprimer l'événement</AlertDialogTitle>
<AlertDialogDescription>
Êtes-vous sûr de vouloir supprimer cet événement ? Cette action
est irréversible.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Annuler</AlertDialogCancel>
<AlertDialogAction onClick={handleDelete}>
Supprimer
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
);
}