xtablo-source/ui/src/components/EventModal.tsx
Arthur Belleville 23840319c2
Improve UI
2025-10-16 18:56:49 +02:00

254 lines
8.5 KiB
TypeScript

import { getLocalTimeZone, parseDate, today } from "@internationalized/date";
import { Button } from "@ui/components/ui/button";
import { DatePicker } from "@ui/components/ui/date-picker";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@ui/components/ui/dialog";
import { Input } from "@ui/components/ui/input";
import { Label } from "@ui/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@ui/components/ui/select";
import { Textarea } from "@ui/components/ui/textarea";
import { TimeInput } from "@ui/components/ui/time-input";
import { useCreateEvents, useEvent, useUpdateEvent } from "@ui/hooks/events";
import { useTablosList } from "@ui/hooks/tablos";
import { useUser } from "@ui/providers/UserStoreProvider";
import { Event, EventInsert } from "@ui/types/events.types";
import { useEffect, useState } from "react";
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
export const EventModal = ({ mode }: { mode: "create" | "edit" }) => {
const { event_id } = useParams();
const { data: event } = useEvent(event_id as string);
const user = useUser();
const [searchParams] = useSearchParams();
const tablo_id = searchParams.get("tablo_id");
const dateFromParams = searchParams.get("date");
const date = dateFromParams ? new Date(dateFromParams) : new Date();
const { data: tablos, isLoading: tablosLoading } = useTablosList();
const createEvents = useCreateEvents();
const updateEvent = useUpdateEvent();
const navigate = useNavigate();
const onClose = () => {
navigate(-1);
};
// Get the local date string without timezone conversion
const getLocalDateString = (date: Date) => {
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, "0");
const day = date.getDate().toString().padStart(2, "0");
return `${year}-${month}-${day}`;
};
// Format time from Date to HH:MM string
const formatTimeFromDate = (date: Date, addMinutes: number = 0): string => {
const hours = date.getHours();
const minutes = date.getMinutes() + addMinutes;
const totalMinutes = hours * 60 + minutes;
const finalHours = Math.floor(totalMinutes / 60) % 24;
const finalMinutes = totalMinutes % 60;
return `${finalHours.toString().padStart(2, "0")}:${finalMinutes.toString().padStart(2, "0")}`;
};
const [formEvent, setFormEvent] = useState<EventInsert>({
start_date: date ? getLocalDateString(date) : "",
start_time: date ? formatTimeFromDate(date) : "",
end_time: date ? formatTimeFromDate(date, 30) : "",
tablo_id: tablo_id || "",
title: "",
created_by: user.id,
});
// Initialize form data when in edit mode
useEffect(() => {
if (mode === "edit" && event) {
setFormEvent({
start_date: event.start_date,
start_time: event.start_time || "",
end_time: event.end_time || "",
tablo_id: event.tablo_id,
title: event.title,
description: event.description || "",
created_by: event.created_by,
});
}
}, [mode, event]);
return (
<Dialog open={true} onOpenChange={onClose}>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>{mode === "edit" ? "Modifier l'événement" : "Nouvel événement"}</DialogTitle>
<DialogDescription>
{mode === "edit" && event
? new Date(event.start_date).toLocaleDateString("fr-FR", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
})
: date.toLocaleDateString("fr-FR", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
})}
</DialogDescription>
</DialogHeader>
<div className="space-y-4">
{/* Title Input */}
<div className="space-y-2">
<Label htmlFor="event-title">Titre *</Label>
<Input
id="event-title"
type="text"
value={formEvent?.title}
onChange={(e) =>
setFormEvent({
...formEvent,
title: e.target.value,
} as Event)
}
placeholder="Ajouter un titre"
autoFocus
/>
</div>
{/* Tablo Selection */}
<div className="space-y-2">
<Label htmlFor="event-tablo">Tablo *</Label>
<Select
value={formEvent?.tablo_id}
onValueChange={(value) =>
setFormEvent({
...formEvent,
tablo_id: value,
} as Event)
}
disabled={tablosLoading}
>
<SelectTrigger id="event-tablo" className="w-full">
<SelectValue placeholder="Sélectionner un tablo" />
</SelectTrigger>
<SelectContent>
{tablos?.map((tablo) => (
<SelectItem key={tablo.id} value={tablo.id}>
{tablo.name}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="grid grid-cols-3 gap-4">
<div className="space-y-2">
<Label htmlFor="event-date">Date *</Label>
<DatePicker
aria-label="Date de l'événement"
value={formEvent?.start_date ? parseDate(formEvent?.start_date) : undefined}
minValue={today(getLocalTimeZone())}
onChange={(date) => {
if (date) {
// Convert Date to YYYY-MM-DD format
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
setFormEvent({
...formEvent,
start_date: `${year}-${month}-${day}`,
});
}
}}
buttonClassName="h-10 w-full"
/>
</div>
<div className="space-y-2">
<Label htmlFor="event-start-time">Début *</Label>
<TimeInput
value={formEvent?.start_time || undefined}
onChange={(value) => {
setFormEvent({
...formEvent,
start_time: value,
});
}}
className="w-full"
id="event-start-time"
/>
</div>
<div className="space-y-2">
<Label htmlFor="event-end-time">Fin</Label>
<TimeInput
value={formEvent?.end_time || undefined}
onChange={(value) => {
setFormEvent({
...formEvent,
end_time: value,
});
}}
className="w-full"
id="event-end-time"
/>
</div>
</div>
{/* Description */}
<div className="space-y-2">
<Label htmlFor="event-description">Description</Label>
<Textarea
id="event-description"
value={formEvent?.description ?? ""}
onChange={(e) =>
setFormEvent({
...formEvent,
description: e.target.value,
} as Event)
}
rows={3}
placeholder="Ajouter une description (optionnel)"
/>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={onClose}>
Annuler
</Button>
<Button
onClick={() => {
const eventName = formEvent?.title.trim() || "(Sans titre)";
if (mode === "edit" && event) {
updateEvent.mutate(
{ id: event.id, ...formEvent, title: eventName },
{ onSuccess: () => onClose() }
);
} else {
createEvents({ ...formEvent, title: eventName }, { onSuccess: () => onClose() });
}
}}
disabled={!formEvent?.tablo_id}
>
{mode === "edit" ? "Modifier" : "Enregistrer"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};