Files
cally/hooks/useFetchAndSaveGoogleEvents.ts
2024-11-01 22:02:36 +01:00

107 lines
4.6 KiB
TypeScript

import { useMutation, useQueryClient } from "react-query";
import { fetchGoogleCalendarEvents } from "@/calendar-integration/google-calendar-utils";
import { useAuthContext } from "@/contexts/AuthContext";
import { useCreateEventsFromProvider } from "@/hooks/firebase/useCreateEvent";
import { useClearTokens } from "@/hooks/firebase/useClearTokens";
import { useUpdateUserData } from "@/hooks/firebase/useUpdateUserData";
export const useFetchAndSaveGoogleEvents = () => {
const queryClient = useQueryClient();
const { profileData } = useAuthContext();
const { mutateAsync: createEventsFromProvider } = useCreateEventsFromProvider();
const { mutateAsync: clearToken } = useClearTokens();
const { mutateAsync: updateUserData } = useUpdateUserData();
return useMutation({
mutationKey: ["fetchAndSaveGoogleEvents", "sync"],
mutationFn: async ({ token, email, date, refreshToken }: { token?: string; refreshToken?: string; email?: string; date?: Date }) => {
const baseDate = date || new Date();
const timeMin = new Date(baseDate.setMonth(baseDate.getMonth() - 1)).toISOString().slice(0, -5) + "Z";
const timeMax = new Date(baseDate.setMonth(baseDate.getMonth() + 2)).toISOString().slice(0, -5) + "Z";
console.log("Token: ", token);
const tryFetchEvents = async (isRetry = false) => {
try {
const response = await fetchGoogleCalendarEvents(
token,
email,
profileData?.familyId,
timeMin,
timeMax
);
if (!response.success) {
await clearToken({ email: email!, provider: "google" });
return; // Stop refetching if clearing the token
}
console.log("Google Calendar events fetched:", response);
const items = response?.googleEvents?.map((item) => {
if (item.allDay) {
item.startDate = new Date(item.startDate.setHours(0, 0, 0, 0));
item.endDate = item.startDate;
}
return item;
}) || [];
await createEventsFromProvider(items);
} catch (error) {
console.error("Error fetching Google Calendar events:", error);
if (!isRetry) {
const refreshedToken = await handleRefreshToken(email, refreshToken);
if (refreshedToken) {
await updateUserData({
newUserData: {
googleAccounts: {
...profileData.googleAccounts,
[email!]: { ...profileData.googleAccounts[email!], accessToken: refreshedToken },
},
},
});
return tryFetchEvents(true); // Retry once after refreshing
} else {
await clearToken({ email: email!, provider: "google" });
console.error(`Token refresh failed; token cleared for ${email}`);
throw error;
}
} else {
console.error(`Retry failed after refreshing token for user ${profileData?.email}:`, error.message);
throw error;
}
}
};
return tryFetchEvents();
},
onSuccess: () => {
queryClient.invalidateQueries(["events"]);
},
});
};
async function handleRefreshToken(email: string, refreshToken: string) {
if (!refreshToken) return null;
try {
const response = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
grant_type: 'refresh_token',
refresh_token: refreshToken,
client_id: "406146460310-2u67ab2nbhu23trp8auho1fq4om29fc0.apps.googleusercontent.com",
}),
});
const data = await response.json();
return data.access_token;
} catch (error) {
console.error("Error refreshing Google token:", error);
return null;
}
}