Syncing rework

This commit is contained in:
Milan Paunovic
2024-11-26 21:13:54 +01:00
parent 5cfdc84055
commit f2af60111b
14 changed files with 960 additions and 595 deletions

View File

@ -3,10 +3,16 @@ import { useAuthContext } from "@/contexts/AuthContext";
import { useAtomValue } from "jotai";
import { useFetchAndSaveGoogleEvents } from "./useFetchAndSaveGoogleEvents";
import { useFetchAndSaveAppleEvents } from "./useFetchAndSaveAppleEvents";
import { useFetchAndSaveOutlookEvents } from "./useFetchAndSaveOutlookEvents";
import { useFetchAndSaveMicrosoftEvents } from "./useFetchAndSaveOutlookEvents";
import { selectedDateAtom } from "@/components/pages/calendar/atoms";
import { addDays, subDays, isBefore, isAfter, format } from "date-fns";
interface SyncResponse {
success: boolean;
eventCount?: number;
error?: string;
}
export const useSyncEvents = () => {
const { profileData } = useAuthContext();
const selectedDate = useAtomValue(selectedDateAtom);
@ -15,12 +21,18 @@ export const useSyncEvents = () => {
const [lowerBoundDate, setLowerBoundDate] = useState<Date>(subDays(selectedDate, 6 * 30));
const [upperBoundDate, setUpperBoundDate] = useState<Date>(addDays(selectedDate, 6 * 30));
const [isSyncing, setIsSyncing] = useState(false);
const [error, setError] = useState(null);
const [error, setError] = useState<Error | null>(null);
const [syncStats, setSyncStats] = useState<{
total: number;
success: number;
failed: number;
events: number;
}>({ total: 0, success: 0, failed: 0, events: 0 });
const syncedRanges = useState<Set<string>>(new Set())[0];
const { mutateAsync: fetchAndSaveGoogleEvents } = useFetchAndSaveGoogleEvents();
const { mutateAsync: fetchAndSaveOutlookEvents } = useFetchAndSaveOutlookEvents();
const { mutateAsync: fetchAndSaveOutlookEvents } = useFetchAndSaveMicrosoftEvents();
const { mutateAsync: fetchAndSaveAppleEvents } = useFetchAndSaveAppleEvents();
const generateRangeKey = (startDate: Date, endDate: Date) => {
@ -41,26 +53,71 @@ export const useSyncEvents = () => {
}
if (isBefore(selectedDate, lowerBoundDate) || isAfter(selectedDate, upperBoundDate)) {
const results: SyncResponse[] = [];
const stats = { total: 0, success: 0, failed: 0, events: 0 };
try {
const googleEvents = Object.entries(profileData?.googleAccounts || {}).map(([email, { accessToken }]) =>
fetchAndSaveGoogleEvents({ token: accessToken, email, date: selectedDate })
);
if (profileData?.googleAccounts) {
for (const [email] of Object.entries(profileData.googleAccounts)) {
try {
stats.total++;
const result = await fetchAndSaveGoogleEvents({ email }) as SyncResponse;
if (result.success) {
stats.success++;
stats.events += result.eventCount || 0;
} else {
stats.failed++;
}
results.push(result);
} catch (err) {
stats.failed++;
console.error(`Failed to sync Google calendar for ${email}:`, err);
}
}
}
const outlookEvents = Object.entries(profileData?.microsoftAccounts || {}).map(([email, token]) =>
fetchAndSaveOutlookEvents({ token, email, date: selectedDate })
);
if (profileData?.microsoftAccounts) {
for (const [email] of Object.entries(profileData.microsoftAccounts)) {
try {
stats.total++;
const result = await fetchAndSaveOutlookEvents({ email });
if (result.success) {
stats.success++;
stats.events += result.eventCount || 0;
} else {
stats.failed++;
}
results.push(result);
} catch (err) {
stats.failed++;
console.error(`Failed to sync Microsoft calendar for ${email}:`, err);
}
}
}
const appleEvents = Object.entries(profileData?.appleAccounts || {}).map(([email, token]) =>
fetchAndSaveAppleEvents({ token, email, date: selectedDate })
);
await Promise.all([...googleEvents, ...outlookEvents, ...appleEvents]);
if (profileData?.appleAccounts) {
for (const [email] of Object.entries(profileData.appleAccounts)) {
try {
stats.total++;
const result = await fetchAndSaveAppleEvents({ email });
} catch (err) {
stats.failed++;
console.error(`Failed to sync Apple calendar for ${email}:`, err);
}
}
}
setSyncStats(stats);
setLastSyncDate(selectedDate);
setLowerBoundDate(newLowerBound);
setUpperBoundDate(newUpperBound);
syncedRanges.add(rangeKey);
} catch (err) {
if (stats.failed > 0) {
throw new Error(`Failed to sync ${stats.failed} calendars`);
}
} catch (err: any) {
console.error("Error syncing events:", err);
setError(err);
} finally {
@ -69,7 +126,16 @@ export const useSyncEvents = () => {
} else {
setIsSyncing(false);
}
}, [selectedDate, lowerBoundDate, upperBoundDate, profileData, fetchAndSaveGoogleEvents, fetchAndSaveOutlookEvents, fetchAndSaveAppleEvents, syncedRanges]);
}, [
selectedDate,
lowerBoundDate,
upperBoundDate,
profileData,
fetchAndSaveGoogleEvents,
fetchAndSaveOutlookEvents,
fetchAndSaveAppleEvents,
syncedRanges
]);
useEffect(() => {
syncEvents();
@ -81,5 +147,6 @@ export const useSyncEvents = () => {
lastSyncDate,
lowerBoundDate,
upperBoundDate,
syncStats,
};
};