122 lines
3.8 KiB
TypeScript
122 lines
3.8 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect, useState } from "react"
|
|
import { toast } from "sonner"
|
|
import { Button } from "@/components/ui/button"
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from "@/components/ui/dialog"
|
|
import { Input } from "@/components/ui/input"
|
|
import { Label } from "@/components/ui/label"
|
|
import {
|
|
useCreateAgendaCalendar,
|
|
useUpdateAgendaCalendar,
|
|
} from "@/lib/api/hooks/use-calendar-mutations"
|
|
import { AGENDA_COLOR_PALETTE } from "@/lib/agenda/agenda-colors"
|
|
import { calendarColor } from "@/lib/agenda/agenda-events"
|
|
import type { AgendaCalendar } from "@/lib/agenda/agenda-types"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
export function AgendaCalendarDialog({
|
|
open,
|
|
onOpenChange,
|
|
calendar,
|
|
}: {
|
|
open: boolean
|
|
onOpenChange: (open: boolean) => void
|
|
/** Agenda à modifier — absent en création. */
|
|
calendar?: AgendaCalendar | null
|
|
}) {
|
|
const [name, setName] = useState("")
|
|
const [color, setColor] = useState(AGENDA_COLOR_PALETTE[0].value)
|
|
const createMutation = useCreateAgendaCalendar()
|
|
const updateMutation = useUpdateAgendaCalendar()
|
|
const pending = createMutation.isPending || updateMutation.isPending
|
|
|
|
useEffect(() => {
|
|
if (!open) return
|
|
setName(calendar?.display_name ?? "")
|
|
setColor(calendar ? calendarColor(calendar) : AGENDA_COLOR_PALETTE[0].value)
|
|
}, [open, calendar])
|
|
|
|
const submit = async () => {
|
|
const displayName = name.trim()
|
|
if (!displayName) return
|
|
try {
|
|
if (calendar) {
|
|
await updateMutation.mutateAsync({
|
|
id: calendar.id,
|
|
display_name: displayName,
|
|
color,
|
|
})
|
|
toast.success("Agenda mis à jour")
|
|
} else {
|
|
await createMutation.mutateAsync({ display_name: displayName, color })
|
|
toast.success(`Agenda « ${displayName} » créé`)
|
|
}
|
|
onOpenChange(false)
|
|
} catch {
|
|
toast.error("Impossible d'enregistrer l'agenda")
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent className="sm:max-w-md">
|
|
<DialogHeader>
|
|
<DialogTitle>
|
|
{calendar ? "Modifier l'agenda" : "Nouvel agenda"}
|
|
</DialogTitle>
|
|
</DialogHeader>
|
|
<div className="flex flex-col gap-4">
|
|
<div className="flex flex-col gap-2">
|
|
<Label htmlFor="agenda-cal-name">Nom</Label>
|
|
<Input
|
|
id="agenda-cal-name"
|
|
value={name}
|
|
autoFocus
|
|
placeholder="Mon agenda"
|
|
onChange={(e) => setName(e.target.value)}
|
|
onKeyDown={(e) => {
|
|
if (e.key === "Enter") void submit()
|
|
}}
|
|
/>
|
|
</div>
|
|
<div className="flex flex-col gap-2">
|
|
<Label>Couleur</Label>
|
|
<div className="flex flex-wrap gap-2">
|
|
{AGENDA_COLOR_PALETTE.map((c) => (
|
|
<button
|
|
key={c.value}
|
|
type="button"
|
|
title={c.label}
|
|
aria-label={c.label}
|
|
onClick={() => setColor(c.value)}
|
|
className={cn(
|
|
"size-7 rounded-full transition-transform hover:scale-110",
|
|
color === c.value &&
|
|
"ring-2 ring-foreground/70 ring-offset-2 ring-offset-background",
|
|
)}
|
|
style={{ backgroundColor: c.value }}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<DialogFooter>
|
|
<Button variant="ghost" onClick={() => onOpenChange(false)}>
|
|
Annuler
|
|
</Button>
|
|
<Button onClick={() => void submit()} disabled={!name.trim() || pending}>
|
|
{calendar ? "Enregistrer" : "Créer"}
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
)
|
|
}
|