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.
73 lines
2.4 KiB
TypeScript
73 lines
2.4 KiB
TypeScript
"use client"
|
|
|
|
import { useMemo } from "react"
|
|
import { useQueries } from "@tanstack/react-query"
|
|
import { format } from "date-fns"
|
|
import { expandApiEvents } from "@/lib/agenda/agenda-events"
|
|
import { parseIcsFeed } from "@/lib/agenda/agenda-ical-parser"
|
|
import type { AgendaEvent } from "@/lib/agenda/agenda-types"
|
|
import type { AgendaExternalCalendar as ExternalCalendarConfig } from "@/lib/agenda/agenda-settings-types"
|
|
import { externalCalendarToAgendaCalendar } from "@/lib/agenda/agenda-calendar-visibility"
|
|
|
|
export function externalIcsQueryKey(calendarId: string, from: string, to: string) {
|
|
return ["agenda", "external-ics", calendarId, from, to] as const
|
|
}
|
|
|
|
async function fetchExternalIcs(url: string): Promise<string> {
|
|
const res = await fetch(`/api/agenda/ical?url=${encodeURIComponent(url)}`)
|
|
if (!res.ok) {
|
|
throw new Error("Impossible de charger le calendrier externe")
|
|
}
|
|
return res.text()
|
|
}
|
|
|
|
export function useExternalAgendaEvents(
|
|
externalCalendars: ExternalCalendarConfig[],
|
|
rangeStart: Date,
|
|
rangeEnd: Date,
|
|
) {
|
|
const from = format(rangeStart, "yyyy-MM-dd")
|
|
const to = format(rangeEnd, "yyyy-MM-dd")
|
|
|
|
const results = useQueries({
|
|
queries: externalCalendars.map((cal) => ({
|
|
queryKey: externalIcsQueryKey(cal.id, from, to),
|
|
staleTime: 5 * 60_000,
|
|
queryFn: async () => {
|
|
const raw = await fetchExternalIcs(cal.url)
|
|
return parseIcsFeed(raw)
|
|
},
|
|
})),
|
|
})
|
|
|
|
const isLoading = results.some((r) => r.isLoading)
|
|
const isError = results.some((r) => r.isError)
|
|
|
|
const rangeStartMs = rangeStart.getTime()
|
|
const rangeEndMs = rangeEnd.getTime()
|
|
|
|
const resultsFingerprint = useMemo(
|
|
() =>
|
|
externalCalendars
|
|
.map((cal, i) => {
|
|
const r = results[i]
|
|
return `${cal.id}:${r?.dataUpdatedAt ?? 0}:${r?.fetchStatus ?? "idle"}`
|
|
})
|
|
.join("|"),
|
|
[externalCalendars, results],
|
|
)
|
|
|
|
const events: AgendaEvent[] = useMemo(() => {
|
|
const all: AgendaEvent[] = []
|
|
externalCalendars.forEach((config, i) => {
|
|
const data = results[i]?.data
|
|
if (!data) return
|
|
const calendar = externalCalendarToAgendaCalendar(config)
|
|
all.push(...expandApiEvents(calendar, data, rangeStart, rangeEnd))
|
|
})
|
|
return all.sort((a, b) => a.start.getTime() - b.start.getTime())
|
|
}, [externalCalendars, results, rangeStartMs, rangeEndMs, resultsFingerprint])
|
|
|
|
return { events, isLoading, isError }
|
|
}
|