Neah/hooks/use-calendar-events.ts
2025-05-02 18:19:46 +02:00

122 lines
3.6 KiB
TypeScript

import { useState, useEffect } from "react";
import { useSession } from "next-auth/react";
export interface CalendarEvent {
id: string;
title: string;
start: Date | string;
end: Date | string;
isAllDay: boolean;
calendarId?: string;
calendarName?: string;
calendarColor?: string;
}
export interface UseCalendarEventsOptions {
limit?: number;
includeAllDay?: boolean;
includeMultiDay?: boolean;
filterCalendarIds?: string[];
}
export function useCalendarEvents({
limit = 10,
includeAllDay = true,
includeMultiDay = true,
filterCalendarIds
}: UseCalendarEventsOptions = {}) {
const [events, setEvents] = useState<CalendarEvent[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [refreshTrigger, setRefreshTrigger] = useState(0);
const { status } = useSession();
const refresh = () => {
setRefreshTrigger(prev => prev + 1);
};
useEffect(() => {
const fetchEvents = async () => {
if (status !== "authenticated") {
return;
}
setLoading(true);
setError(null);
try {
const response = await fetch('/api/calendars');
if (!response.ok) {
throw new Error('Failed to fetch events');
}
const calendarsData = await response.json();
// Get current date at the start of the day
const now = new Date();
now.setHours(0, 0, 0, 0);
// Extract and process events from all calendars
const allEvents = calendarsData.flatMap((calendar: any) =>
// Skip calendars if filtering is applied
(filterCalendarIds && !filterCalendarIds.includes(calendar.id)) ? [] :
(calendar.events || []).map((event: any) => ({
id: event.id,
title: event.title,
start: new Date(event.start),
end: new Date(event.end),
isAllDay: event.isAllDay || false,
calendarId: calendar.id,
calendarName: calendar.name,
calendarColor: calendar.color
}))
);
// Filter for upcoming events
const upcomingEvents = allEvents
.filter((event: CalendarEvent) => {
// Skip past events
if (new Date(event.start) < now) {
return false;
}
// Filter all-day events if not included
if (!includeAllDay && event.isAllDay) {
return false;
}
// Filter multi-day events if not included
if (!includeMultiDay) {
const startDate = new Date(event.start);
const endDate = new Date(event.end);
// Check if the event spans multiple days
startDate.setHours(0, 0, 0, 0);
endDate.setHours(0, 0, 0, 0);
if (startDate.getTime() !== endDate.getTime()) {
return false;
}
}
return true;
})
.sort((a: CalendarEvent, b: CalendarEvent) =>
new Date(a.start).getTime() - new Date(b.start).getTime()
);
setEvents(limit ? upcomingEvents.slice(0, limit) : upcomingEvents);
setError(null);
} catch (error) {
setError(error instanceof Error ? error.message : 'Failed to fetch events');
} finally {
setLoading(false);
}
};
fetchEvents();
}, [status, limit, includeAllDay, includeMultiDay, filterCalendarIds, refreshTrigger]);
return { events, loading, error, refresh };
}