Agenda Sync refactor

This commit is contained in:
alma 2026-01-14 14:02:54 +01:00
parent 603b8ff718
commit 3de29f94e1
2 changed files with 78 additions and 11 deletions

View File

@ -44,7 +44,7 @@ export default async function CalendarPage() {
const userId = session.user.username || session.user.email || ''; const userId = session.user.username || session.user.email || '';
// Get all calendars for the user with mission relation // Get all calendars for the user with mission relation and sync configuration
let calendars = await prisma.calendar.findMany({ let calendars = await prisma.calendar.findMany({
where: { where: {
userId: session?.user?.id || '', userId: session?.user?.id || '',
@ -59,6 +59,17 @@ export default async function CalendarPage() {
include: { include: {
missionUsers: true missionUsers: true
} }
},
syncConfig: {
include: {
mailCredential: {
select: {
id: true,
email: true,
display_name: true,
}
}
}
} }
} }
}); });

View File

@ -72,6 +72,21 @@ interface CalendarWithMission extends Calendar {
role: string; role: string;
}>; }>;
} | null; } | null;
syncConfig?: {
id: string;
provider: string;
externalCalendarId: string | null;
externalCalendarUrl: string | null;
syncEnabled: boolean;
lastSyncAt: Date | null;
syncFrequency: number;
lastSyncError: string | null;
mailCredential?: {
id: string;
email: string;
display_name: string | null;
} | null;
} | null;
} }
interface CalendarClientProps { interface CalendarClientProps {
@ -827,6 +842,23 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
} }
}; };
const getCalendarDisplayName = (calendar: CalendarWithMission) => {
// If calendar is synced to an external account, show the account label
if (calendar.syncConfig && calendar.syncConfig.mailCredential) {
const accountLabel =
calendar.syncConfig.mailCredential.display_name ||
calendar.syncConfig.mailCredential.email;
return accountLabel || (calendar.name === "Default" ? "Privée" : calendar.name);
}
// Legacy default name
if (calendar.name === "Default") {
return "Privée";
}
return calendar.name;
};
// Update CalendarSelector to handle visibility - displayed as a left column // Update CalendarSelector to handle visibility - displayed as a left column
const CalendarSelector = () => ( const CalendarSelector = () => (
<div className="flex flex-col gap-2 mb-4"> <div className="flex flex-col gap-2 mb-4">
@ -847,7 +879,14 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
className="w-3 h-3 rounded-full" className="w-3 h-3 rounded-full"
style={{ backgroundColor: calendar.color }} style={{ backgroundColor: calendar.color }}
/> />
<span>{calendar.name === "Default" ? "Privée" : calendar.name}</span> <span className="flex items-center gap-1">
{getCalendarDisplayName(calendar as CalendarWithMission)}
{calendar.syncConfig?.syncEnabled && (
<Badge variant="outline" className="text-[10px] px-1 py-0.5 border-blue-400 text-blue-600">
Sync
</Badge>
)}
</span>
<div className="ml-auto"> <div className="ml-auto">
{visibleCalendarIds.includes(calendar.id) ? ( {visibleCalendarIds.includes(calendar.id) ? (
<Check className="h-4 w-4" /> <Check className="h-4 w-4" />
@ -951,14 +990,23 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
{/* Display selected calendar name */} {/* Display selected calendar name */}
{(() => { {(() => {
const selectedCal = calendars.find(cal => visibleCalendarIds.includes(cal.id) && visibleCalendarIds.length === 1); const selectedCal = calendars.find(
cal => visibleCalendarIds.includes(cal.id) && visibleCalendarIds.length === 1
) as CalendarWithMission | undefined;
const displayName = selectedCal const displayName = selectedCal
? (selectedCal.name === "Default" ? "Privée" : selectedCal.name) ? getCalendarDisplayName(selectedCal)
: "Tous les calendriers"; : "Tous les calendriers";
return ( return (
<h2 className="text-lg font-semibold text-gray-900"> <div className="flex items-center gap-2">
{displayName} <h2 className="text-lg font-semibold text-gray-900">
</h2> {displayName}
</h2>
{selectedCal?.syncConfig?.syncEnabled && (
<Badge variant="outline" className="text-[10px] px-1.5 py-0.5 border-blue-400 text-blue-600">
Synchronisé
</Badge>
)}
</div>
); );
})()} })()}
{(() => { {(() => {
@ -1275,7 +1323,10 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
<div className="space-y-2"> <div className="space-y-2">
<Label className="text-base font-semibold text-gray-800">Calendrier</Label> <Label className="text-base font-semibold text-gray-800">Calendrier</Label>
<div className="grid grid-cols-2 gap-2"> <div className="grid grid-cols-2 gap-2">
{calendars.map((cal) => ( {calendars.map((cal) => {
const calWithMission = cal as CalendarWithMission;
const label = getCalendarDisplayName(calWithMission);
return (
<button <button
key={cal.id} key={cal.id}
type="button" type="button"
@ -1300,10 +1351,15 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
? 'font-medium text-gray-900' ? 'font-medium text-gray-900'
: 'text-gray-700' : 'text-gray-700'
}`}> }`}>
{cal.name} {label}
</span> </span>
{calWithMission.syncConfig?.syncEnabled && (
<Badge variant="outline" className="ml-auto text-[10px] px-1 py-0.5 border-blue-400 text-blue-600">
Sync
</Badge>
)}
</button> </button>
))} );})}
</div> </div>
</div> </div>