calendar 14

This commit is contained in:
Alma 2025-04-13 14:16:02 +02:00
parent 7dab3da369
commit 0d78cc4e6a
4 changed files with 112 additions and 44 deletions

View File

@ -149,31 +149,29 @@ export async function DELETE(
}
try {
// Vérifier que le calendrier existe et appartient à l'utilisateur
const existingCalendar = await prisma.calendar.findUnique({
// Verify calendar ownership
const calendar = await prisma.calendar.findFirst({
where: {
id: params.id,
userId: session.user.username,
},
});
if (!existingCalendar) {
if (!calendar) {
return NextResponse.json(
{ error: "Calendrier non trouvé" },
{ error: "Calendrier non trouvé ou non autorisé" },
{ status: 404 }
);
}
if (existingCalendar.userId !== session.user.username) {
return NextResponse.json({ error: "Non autorisé" }, { status: 403 });
}
// Delete the calendar (this will also delete all associated events due to the cascade delete)
await prisma.calendar.delete({
where: {
id: params.id,
},
});
return new NextResponse(null, { status: 204 });
return NextResponse.json({ success: true });
} catch (error) {
console.error("Erreur lors de la suppression du calendrier:", error);
return NextResponse.json({ error: "Erreur serveur" }, { status: 500 });

View File

@ -14,15 +14,17 @@ export async function DELETE(
}
try {
// Verify event ownership
// Verify event ownership through calendar
const event = await prisma.event.findFirst({
where: {
id: params.id,
userId: session.user.username,
},
include: {
calendar: true
}
});
if (!event) {
if (!event || event.calendar.userId !== session.user.username) {
return NextResponse.json(
{ error: "Événement non trouvé ou non autorisé" },
{ status: 404 }

View File

@ -44,8 +44,11 @@ export async function POST(req: NextRequest) {
end: new Date(end),
isAllDay: allDay || false,
location,
calendarId,
userId: session.user.username,
calendar: {
connect: {
id: calendarId
}
}
},
});
@ -74,15 +77,22 @@ export async function PUT(req: NextRequest) {
);
}
// Verify event ownership
const existingEvent = await prisma.event.findFirst({
// Verify calendar ownership
const calendar = await prisma.calendar.findFirst({
where: {
id,
id: calendarId,
userId: session.user.username,
},
include: {
events: {
where: {
id
}
}
}
});
if (!existingEvent) {
if (!calendar || calendar.events.length === 0) {
return NextResponse.json(
{ error: "Événement non trouvé ou non autorisé" },
{ status: 404 }
@ -98,7 +108,11 @@ export async function PUT(req: NextRequest) {
end: new Date(end),
isAllDay: allDay || false,
location,
calendarId,
calendar: {
connect: {
id: calendarId
}
}
},
});

View File

@ -79,10 +79,11 @@ interface CalendarDialogProps {
open: boolean;
onClose: () => void;
onSave: (calendarData: Partial<Calendar>) => Promise<void>;
onDelete?: (calendarId: string) => Promise<void>;
initialData?: Partial<Calendar>;
}
function CalendarDialog({ open, onClose, onSave, initialData }: CalendarDialogProps) {
function CalendarDialog({ open, onClose, onSave, onDelete, initialData }: CalendarDialogProps) {
const [name, setName] = useState(initialData?.name || "");
const [color, setColor] = useState(initialData?.color || "#4f46e5");
const [description, setDescription] = useState(initialData?.description || "");
@ -117,6 +118,20 @@ function CalendarDialog({ open, onClose, onSave, initialData }: CalendarDialogPr
}
};
const handleDelete = async () => {
if (!initialData?.id || !onDelete) return;
setIsSubmitting(true);
try {
await onDelete(initialData.id);
resetForm();
} catch (error) {
console.error("Erreur lors de la suppression du calendrier:", error);
} finally {
setIsSubmitting(false);
}
};
const resetForm = () => {
setName("");
setColor("#4f46e5");
@ -229,30 +244,41 @@ function CalendarDialog({ open, onClose, onSave, initialData }: CalendarDialogPr
</div>
<DialogFooter className="mt-6 border-t border-gray-100 pt-4">
<div className="flex gap-3 w-full sm:justify-end">
<Button
type="button"
variant="outline"
onClick={onClose}
disabled={isSubmitting}
className="rounded-lg border-gray-300 text-gray-700 hover:bg-gray-50"
>
<X className="w-4 h-4 mr-2" />
Annuler
</Button>
<Button
type="submit"
disabled={!name || isSubmitting}
className="rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white"
>
<Check className="w-4 h-4 mr-2" />
{isSubmitting
? "Enregistrement..."
: initialData?.id
? "Mettre à jour"
: "Créer"
}
</Button>
<div className="flex justify-between w-full">
{initialData?.id && (
<Button
type="button"
variant="destructive"
onClick={handleDelete}
disabled={isSubmitting}
>
<X className="w-4 h-4 mr-2" />
Supprimer
</Button>
)}
<div className="flex gap-3">
<Button
type="button"
variant="outline"
onClick={onClose}
disabled={isSubmitting}
className="rounded-lg border-gray-300 text-gray-700 hover:bg-gray-50"
>
Annuler
</Button>
<Button
type="submit"
disabled={!name || isSubmitting}
className="rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white"
>
{isSubmitting
? "Enregistrement..."
: initialData?.id
? "Mettre à jour"
: "Créer"
}
</Button>
</div>
</div>
</DialogFooter>
</form>
@ -494,6 +520,33 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
}
};
const handleCalendarDelete = async (calendarId: string) => {
try {
setLoading(true);
const response = await fetch(`/api/calendars/${calendarId}`, {
method: "DELETE",
});
if (!response.ok) {
throw new Error("Failed to delete calendar");
}
await fetchCalendars();
setIsCalendarModalOpen(false);
// If the deleted calendar was selected, select another one
if (selectedCalendarId === calendarId) {
const remainingCalendars = calendars.filter(cal => cal.id !== calendarId);
setSelectedCalendarId(remainingCalendars[0]?.id || "");
}
} catch (error) {
console.error("Error deleting calendar:", error);
setError(error instanceof Error ? error.message : "Failed to delete calendar");
} finally {
setLoading(false);
}
};
const handleDateSelect = (selectInfo: any) => {
const startDate = new Date(selectInfo.start);
const endDate = new Date(selectInfo.end);
@ -730,6 +783,7 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
open={isCalendarModalOpen}
onClose={() => setIsCalendarModalOpen(false)}
onSave={handleCalendarSave}
onDelete={handleCalendarDelete}
initialData={selectedCalendar || undefined}
/>