Agenda refactor

This commit is contained in:
alma 2026-01-15 18:16:15 +01:00
parent 986f66ac92
commit d8846524f0
3 changed files with 132 additions and 50 deletions

View File

@ -647,6 +647,37 @@ export default async function CalendarPage() {
}
});
// Sort calendars: "Mon Calendrier" first, then synced, then groups, then missions
calendars = calendars.sort((a, b) => {
const aIsMonCalendrier = a.name === "Mon Calendrier";
const bIsMonCalendrier = b.name === "Mon Calendrier";
const aIsSynced = a.syncConfig?.syncEnabled && a.syncConfig?.mailCredential;
const bIsSynced = b.syncConfig?.syncEnabled && b.syncConfig?.mailCredential;
const aIsGroup = a.name?.startsWith("Groupe:");
const bIsGroup = b.name?.startsWith("Groupe:");
const aIsMission = a.name?.startsWith("Mission:");
const bIsMission = b.name?.startsWith("Mission:");
// "Mon Calendrier" always first
if (aIsMonCalendrier && !bIsMonCalendrier) return -1;
if (!aIsMonCalendrier && bIsMonCalendrier) return 1;
// Synced calendars second
if (aIsSynced && !bIsSynced) return -1;
if (!aIsSynced && bIsSynced) return 1;
// Groups third
if (aIsGroup && !bIsGroup && !bIsSynced) return -1;
if (!aIsGroup && bIsGroup && !aIsSynced) return 1;
// Missions fourth
if (aIsMission && !bIsMission && !bIsGroup && !bIsSynced) return -1;
if (!aIsMission && bIsMission && !aIsGroup && !aIsSynced) return 1;
// Same type, sort by name
return (a.name || '').localeCompare(b.name || '');
});
const now = new Date();
const nextWeek = add(now, { days: 7 });

View File

@ -169,18 +169,49 @@ export async function GET(req: NextRequest) {
new Map(calendars.map(cal => [cal.id, cal])).values()
);
// Sort calendars: "Mon Calendrier" first, then synced, then groups, then missions
const sortedCalendars = uniqueCalendars.sort((a, b) => {
const aIsMonCalendrier = a.name === "Mon Calendrier";
const bIsMonCalendrier = b.name === "Mon Calendrier";
const aIsSynced = a.syncConfig?.syncEnabled && a.syncConfig?.mailCredential;
const bIsSynced = b.syncConfig?.syncEnabled && b.syncConfig?.mailCredential;
const aIsGroup = a.name?.startsWith("Groupe:");
const bIsGroup = b.name?.startsWith("Groupe:");
const aIsMission = a.name?.startsWith("Mission:");
const bIsMission = b.name?.startsWith("Mission:");
// "Mon Calendrier" always first
if (aIsMonCalendrier && !bIsMonCalendrier) return -1;
if (!aIsMonCalendrier && bIsMonCalendrier) return 1;
// Synced calendars second
if (aIsSynced && !bIsSynced) return -1;
if (!aIsSynced && bIsSynced) return 1;
// Groups third
if (aIsGroup && !bIsGroup && !bIsSynced) return -1;
if (!aIsGroup && bIsGroup && !aIsSynced) return 1;
// Missions fourth
if (aIsMission && !bIsMission && !bIsGroup && !bIsSynced) return -1;
if (!aIsMission && bIsMission && !aIsGroup && !aIsSynced) return 1;
// Same type, sort by name
return (a.name || '').localeCompare(b.name || '');
});
logger.debug('[CALENDAR] Fetched calendars with events', {
userId: session.user.id,
personalCount: filteredPersonalCalendars.length,
missionCount: missionCalendars.length,
totalCount: uniqueCalendars.length,
totalCount: sortedCalendars.length,
filteredOut: personalCalendars.length - filteredPersonalCalendars.length,
});
// Cache the results
await cacheCalendarData(session.user.id, uniqueCalendars);
await cacheCalendarData(session.user.id, sortedCalendars);
return NextResponse.json(uniqueCalendars);
return NextResponse.json(sortedCalendars);
} catch (error) {
logger.error('[CALENDAR] Erreur lors de la récupération des calendriers', {
error: error instanceof Error ? error.message : String(error),

View File

@ -255,15 +255,16 @@ function CalendarDialog({ open, onClose, onSave, onDelete, onSyncSetup, initialD
setIsSubmitting(true);
try {
// Only update color, preserve name and description from initialData
await onSave({
id: initialData?.id,
name,
color,
description
name: initialData?.name || name, // Keep original name
color, // Only color can be changed
description: initialData?.description || description // Keep original description
});
resetForm();
} catch (error) {
console.error("Erreur lors de la création du calendrier:", error);
console.error("Erreur lors de la mise à jour du calendrier:", error);
} finally {
setIsSubmitting(false);
}
@ -301,24 +302,36 @@ function CalendarDialog({ open, onClose, onSave, onDelete, onSyncSetup, initialD
<DialogHeader>
<DialogTitle className="flex items-center text-xl font-semibold text-gray-900">
<CalendarIcon className="w-5 h-5 mr-2 text-indigo-600" />
{initialData?.id ? "Modifier le calendrier" : "Créer un nouveau calendrier"}
{initialData?.id ? "Paramètres du calendrier" : "Créer un nouveau calendrier"}
</DialogTitle>
</DialogHeader>
<form onSubmit={handleSubmit}>
<div className="space-y-5 py-4">
<div className="space-y-2">
<Label htmlFor="calendar-name" className="text-gray-700">Nom</Label>
<Input
id="calendar-name"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Nom du calendrier"
required
disabled={isMainCalendar || isMissionOrGroupCalendar}
className="rounded-lg border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 bg-white text-gray-900"
/>
</div>
{/* Display calendar name (read-only) */}
{initialData?.id && (
<div className="space-y-2">
<Label className="text-gray-700">Nom</Label>
<div className="px-3 py-2 bg-gray-50 rounded-lg text-gray-900 border border-gray-200">
{initialData?.name || name}
</div>
</div>
)}
{/* Name input only for new calendars */}
{!initialData?.id && (
<div className="space-y-2">
<Label htmlFor="calendar-name" className="text-gray-700">Nom</Label>
<Input
id="calendar-name"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Nom du calendrier"
required
className="rounded-lg border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 bg-white text-gray-900"
/>
</div>
)}
<div className="space-y-3">
<Label className="text-gray-700">Couleur</Label>
@ -384,20 +397,32 @@ function CalendarDialog({ open, onClose, onSave, onDelete, onSyncSetup, initialD
)}
</div>
<div className="space-y-2">
<Label htmlFor="calendar-description" className="text-gray-700">
Description (optionnelle)
</Label>
<Textarea
id="calendar-description"
value={description}
onChange={(e) => setDescription(e.target.value)}
placeholder="Description du calendrier"
rows={3}
disabled={isMissionOrGroupCalendar}
className="rounded-lg border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 bg-white text-gray-900"
/>
</div>
{/* Display description (read-only) for existing calendars */}
{initialData?.id && initialData?.description && (
<div className="space-y-2">
<Label className="text-gray-700">Description</Label>
<div className="px-3 py-2 bg-gray-50 rounded-lg text-gray-700 border border-gray-200 text-sm">
{initialData?.description || description}
</div>
</div>
)}
{/* Description input only for new calendars */}
{!initialData?.id && (
<div className="space-y-2">
<Label htmlFor="calendar-description" className="text-gray-700">
Description (optionnelle)
</Label>
<Textarea
id="calendar-description"
value={description}
onChange={(e) => setDescription(e.target.value)}
placeholder="Description du calendrier"
rows={3}
className="rounded-lg border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 bg-white text-gray-900"
/>
</div>
)}
{/* Sync Section for Private Calendars */}
{isPrivateCalendar && initialData?.id && (
@ -532,18 +557,7 @@ function CalendarDialog({ open, onClose, onSave, onDelete, onSyncSetup, initialD
</div>
<DialogFooter className="mt-6 border-t border-gray-100 pt-4">
<div className="flex justify-between w-full">
{initialData?.id && !isMainCalendar && !isMissionOrGroupCalendar && (
<Button
type="button"
variant="destructive"
onClick={handleDelete}
disabled={isSubmitting || isMainCalendar || isMissionOrGroupCalendar}
>
<X className="w-4 h-4 mr-2" />
Supprimer
</Button>
)}
<div className="flex justify-end w-full">
<div className="flex gap-3">
<Button
type="button"
@ -556,13 +570,13 @@ function CalendarDialog({ open, onClose, onSave, onDelete, onSyncSetup, initialD
</Button>
<Button
type="submit"
disabled={!name || isSubmitting || isMainCalendar || isMissionOrGroupCalendar}
disabled={isSubmitting || (initialData?.id ? false : !name)}
className="rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white"
>
{isSubmitting
? "Enregistrement..."
: initialData?.id
? "Mettre à jour"
? "Mettre à jour la couleur"
: "Créer"
}
</Button>
@ -720,10 +734,12 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
});
};
// Sort calendars: synced (courrier) first, then groups, then missions
// Sort calendars: "Mon Calendrier" first, then synced (courrier), then groups, then missions
const sortCalendars = (cals: typeof initialCalendars) => {
const filtered = filterCalendars(cals);
return [...filtered].sort((a, b) => {
const aIsMonCalendrier = a.name === "Mon Calendrier";
const bIsMonCalendrier = b.name === "Mon Calendrier";
const aIsSynced = a.syncConfig?.syncEnabled && a.syncConfig?.mailCredential;
const bIsSynced = b.syncConfig?.syncEnabled && b.syncConfig?.mailCredential;
const aIsGroup = a.name?.startsWith("Groupe:");
@ -731,7 +747,11 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
const aIsMission = a.name?.startsWith("Mission:");
const bIsMission = b.name?.startsWith("Mission:");
// Synced calendars first
// "Mon Calendrier" always first
if (aIsMonCalendrier && !bIsMonCalendrier) return -1;
if (!aIsMonCalendrier && bIsMonCalendrier) return 1;
// Synced calendars second
if (aIsSynced && !bIsSynced) return -1;
if (!aIsSynced && bIsSynced) return 1;