Some checks are pending
E2E / Playwright e2e (push) Waiting to run
- Introduced turbopack alias for canvas in next.config.mjs. - Updated package.json scripts for development and branding tasks. - Added new dependencies for Tiptap extensions. - Implemented new demo layouts for agenda, contacts, drive, and mail applications. - Enhanced globals.css for improved theming and splash screen animations. - Added OAuth callback handling for drive mounts. - Updated layout components to integrate new demo shells and improve structure.
69 lines
2.2 KiB
TypeScript
69 lines
2.2 KiB
TypeScript
import { addDays, addMilliseconds, differenceInCalendarDays, startOfDay } from "date-fns"
|
|
import { formatICSDateOnly, formatICSDateTimeUTC } from "@/lib/agenda/agenda-date"
|
|
import type { AgendaApiEvent, AgendaEvent, AgendaEventDraft } from "@/lib/agenda/agenda-types"
|
|
|
|
/** Calcule les nouvelles dates après déplacement (durée conservée). */
|
|
export function shiftedEventRange(
|
|
event: AgendaEvent,
|
|
targetStart: Date,
|
|
): { start: Date; end: Date } {
|
|
if (event.allDay || isAllDaySpan(event)) {
|
|
const spanDays = Math.max(
|
|
1,
|
|
differenceInCalendarDays(startOfDay(event.end), startOfDay(event.start)),
|
|
)
|
|
const start = startOfDay(targetStart)
|
|
return { start, end: addDays(start, spanDays) }
|
|
}
|
|
|
|
const durationMs = event.end.getTime() - event.start.getTime()
|
|
return { start: targetStart, end: addMilliseconds(targetStart, durationMs) }
|
|
}
|
|
|
|
function isAllDaySpan(event: AgendaEvent): boolean {
|
|
return (
|
|
event.start.getHours() === 0 &&
|
|
event.start.getMinutes() === 0 &&
|
|
event.end.getHours() === 0 &&
|
|
event.end.getMinutes() === 0 &&
|
|
event.end.getTime() - event.start.getTime() >= 24 * 3600 * 1000
|
|
)
|
|
}
|
|
|
|
/** Payload minimal pour un déplacement — le backend merge avec l'événement existant. */
|
|
export function eventRescheduleApiPayload(
|
|
event: AgendaEvent,
|
|
start: Date,
|
|
end: Date,
|
|
): Partial<AgendaApiEvent> {
|
|
const allDay = event.allDay || isAllDaySpan(event)
|
|
const eventStart = allDay ? startOfDay(start) : start
|
|
return {
|
|
uid: event.uid || event.master.uid,
|
|
summary: event.title.trim() || "(Sans titre)",
|
|
start: allDay ? formatICSDateOnly(eventStart) : formatICSDateTimeUTC(eventStart),
|
|
end: allDay ? formatICSDateOnly(end) : formatICSDateTimeUTC(end),
|
|
all_day: allDay,
|
|
}
|
|
}
|
|
|
|
/** Brouillon UI (legacy — préférer eventRescheduleApiPayload pour l'API). */
|
|
export function eventMoveDraft(
|
|
event: AgendaEvent,
|
|
start: Date,
|
|
end: Date,
|
|
): AgendaEventDraft {
|
|
return {
|
|
title: event.title === "(Sans titre)" ? "" : event.title,
|
|
start,
|
|
end,
|
|
allDay: event.allDay,
|
|
calendarId: event.calendarId,
|
|
description: event.description,
|
|
location: event.location,
|
|
attendees: event.attendees,
|
|
rrule: event.rrule,
|
|
color: event.master.color,
|
|
}
|
|
}
|