ultisuite-client/lib/api/hooks/use-calendar-mutations.ts
R3D347HR4Y 3bbf3691b0
Some checks failed
E2E / Playwright e2e (push) Has been cancelled
bordel c'est beau
2026-06-11 10:10:39 +02:00

159 lines
4.3 KiB
TypeScript

"use client"
import { useMutation, useQueryClient } from "@tanstack/react-query"
import { apiClient } from "@/lib/api/client"
import { formatICSDateOnly, formatICSDateTimeUTC } from "@/lib/agenda/agenda-date"
import type { AgendaApiEvent, AgendaEventDraft } from "@/lib/agenda/agenda-types"
function eventApiPath(davPath: string): string {
return `/calendar/events/${davPath.replace(/^\/+/, "")}`
}
/** Convertit un brouillon UI en payload API (dates ICS). */
export function draftToApiEvent(
draft: AgendaEventDraft,
existing?: AgendaApiEvent,
): Partial<AgendaApiEvent> {
const start = draft.allDay
? formatICSDateOnly(draft.start)
: formatICSDateTimeUTC(draft.start)
const end = draft.allDay
? formatICSDateOnly(draft.end)
: formatICSDateTimeUTC(draft.end)
return {
uid: existing?.uid,
summary: draft.title.trim() || "(Sans titre)",
description: draft.description ?? existing?.description ?? "",
location: draft.location ?? existing?.location ?? "",
start,
end,
all_day: draft.allDay,
attendees: draft.attendees ?? existing?.attendees ?? [],
organizer: existing?.organizer,
meet_url: existing?.meet_url,
color: draft.color ?? existing?.color,
rrule: draft.rrule ?? existing?.rrule ?? "",
exdates: existing?.exdates,
}
}
function useInvalidateAgenda() {
const queryClient = useQueryClient()
return () => {
void queryClient.invalidateQueries({ queryKey: ["agenda", "events"] })
}
}
export function useCreateAgendaEvent() {
const invalidate = useInvalidateAgenda()
return useMutation({
mutationFn: ({
calendarId,
event,
}: {
calendarId: string
event: Partial<AgendaApiEvent>
}) =>
apiClient.post(`/calendar/${encodeURIComponent(calendarId)}/events`, event),
onSuccess: invalidate,
})
}
export function useUpdateAgendaEvent() {
const invalidate = useInvalidateAgenda()
return useMutation({
mutationFn: ({
path,
etag,
event,
}: {
path: string
etag: string
event: Partial<AgendaApiEvent>
}) =>
apiClient.put<{ etag: string }>(eventApiPath(path), event, {
"If-Match": etag || "*",
}),
onSuccess: invalidate,
})
}
export function useDeleteAgendaEvent() {
const invalidate = useInvalidateAgenda()
return useMutation({
mutationFn: ({ path }: { path: string }) => apiClient.delete(eventApiPath(path)),
onSuccess: invalidate,
})
}
export function useRespondAgendaInvitation() {
const invalidate = useInvalidateAgenda()
return useMutation({
mutationFn: ({
path,
response,
etag,
}: {
path: string
response: "accepted" | "declined" | "tentative"
etag?: string
}) =>
apiClient.post<{ etag: string }>(
`/calendar/events/response/${path.replace(/^\/+/, "")}`,
{ response, if_match: etag ?? "" },
),
onSuccess: invalidate,
})
}
export function useCreateAgendaMeetLink() {
const invalidate = useInvalidateAgenda()
return useMutation({
mutationFn: ({ path, etag }: { path: string; etag?: string }) =>
apiClient.post<{ meet_url: string; etag: string }>(
`/calendar/events/meet-link/${path.replace(/^\/+/, "")}`,
{ if_match: etag ?? "" },
),
onSuccess: invalidate,
})
}
export function useCreateAgendaCalendar() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: (input: { display_name: string; color?: string }) =>
apiClient.post<{ id: string }>("/calendar", input),
onSuccess: () => {
void queryClient.invalidateQueries({ queryKey: ["agenda", "calendars"] })
},
})
}
export function useUpdateAgendaCalendar() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: ({
id,
...input
}: {
id: string
display_name?: string
color?: string
}) => apiClient.patch(`/calendar/${encodeURIComponent(id)}`, input),
onSuccess: () => {
void queryClient.invalidateQueries({ queryKey: ["agenda"] })
},
})
}
export function useDeleteAgendaCalendar() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: ({ id }: { id: string }) =>
apiClient.delete(`/calendar/${encodeURIComponent(id)}`),
onSuccess: () => {
void queryClient.invalidateQueries({ queryKey: ["agenda"] })
},
})
}