- Convert hasSharingRef from useRef to useState in useCalendars so refetchInterval reacts immediately when sharing is detected (P-01) - Add extra="forbid" to ReorderItem schema to prevent mass-assignment (S-03) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
54 lines
1.8 KiB
TypeScript
54 lines
1.8 KiB
TypeScript
import { useState, useMemo } from 'react';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import api from '@/lib/api';
|
|
import type { Calendar, SharedCalendarMembership } from '@/types';
|
|
|
|
interface UseCalendarsOptions {
|
|
pollingEnabled?: boolean;
|
|
}
|
|
|
|
export function useCalendars({ pollingEnabled = false }: UseCalendarsOptions = {}) {
|
|
const ownedQuery = useQuery({
|
|
queryKey: ['calendars'],
|
|
queryFn: async () => {
|
|
const { data } = await api.get<Calendar[]>('/calendars');
|
|
return data;
|
|
},
|
|
});
|
|
|
|
// AS-4: Gate shared-calendar polling on whether user participates in sharing.
|
|
// Saves ~12 API calls/min for personal-only users.
|
|
// Uses useState (not useRef) so changes trigger a re-render and the
|
|
// refetchInterval picks up the new value immediately.
|
|
const [hasSharing, setHasSharing] = useState(false);
|
|
const ownsShared = (ownedQuery.data ?? []).some((c) => c.is_shared);
|
|
if (ownsShared && !hasSharing) setHasSharing(true);
|
|
|
|
const sharedQuery = useQuery({
|
|
queryKey: ['calendars', 'shared'],
|
|
queryFn: async () => {
|
|
const { data } = await api.get<SharedCalendarMembership[]>('/shared-calendars');
|
|
return data;
|
|
},
|
|
refetchInterval: pollingEnabled && hasSharing ? 5_000 : false,
|
|
staleTime: 3_000,
|
|
});
|
|
|
|
// Also latch if user is a member of others' shared calendars
|
|
if ((sharedQuery.data ?? []).length > 0 && !hasSharing) setHasSharing(true);
|
|
|
|
const allCalendarIds = useMemo(() => {
|
|
const owned = (ownedQuery.data ?? []).map((c) => c.id);
|
|
const shared = (sharedQuery.data ?? []).map((m) => m.calendar_id);
|
|
return new Set([...owned, ...shared]);
|
|
}, [ownedQuery.data, sharedQuery.data]);
|
|
|
|
return {
|
|
data: ownedQuery.data ?? [],
|
|
sharedData: sharedQuery.data ?? [],
|
|
allCalendarIds,
|
|
isLoading: ownedQuery.isLoading,
|
|
isLoadingShared: sharedQuery.isLoading,
|
|
};
|
|
}
|