import { AntDesign, Ionicons } from "@expo/vector-icons"; import React, { useCallback, useState } from "react"; import { Button, Checkbox, Text, View } from "react-native-ui-lib"; import { ScrollView, StyleSheet } from "react-native"; import { colorMap } from "@/contexts/SettingsContext"; import { TouchableOpacity } from "react-native-gesture-handler"; import { fetchGoogleCalendarEvents } from "@/calendar-integration/google-calendar-utils"; import { fetchMicrosoftCalendarEvents } from "@/calendar-integration/microsoft-calendar-utils"; import { useCreateEventFromProvider } from "@/hooks/firebase/useCreateEvent"; import { useAuthContext } from "@/contexts/AuthContext"; import { useUpdateUserData } from "@/hooks/firebase/useUpdateUserData"; import { GoogleSignin } from "@react-native-google-signin/google-signin"; import * as AuthSession from "expo-auth-session"; import debounce from "debounce"; import AppleIcon from "@/assets/svgs/AppleIcon"; import GoogleIcon from "@/assets/svgs/GoogleIcon"; import OutlookIcon from "@/assets/svgs/OutlookIcon"; GoogleSignin.configure({ webClientId: "406146460310-hjadmfa1gg4ptaouira5rkhu0djlo5ut.apps.googleusercontent.com", scopes: ["profile", "email"], // Note: add calendar scope }); const GoogleLogin = async () => { return await GoogleSignin.signIn(); }; const microsoftConfig = { clientId: "13c79071-1066-40a9-9f71-b8c4b138b4af", // Replace with your Microsoft client ID redirectUri: AuthSession.makeRedirectUri({ path: "settings" }), // Generate redirect URI automatically for Expo scopes: [ "openid", "profile", "email", "offline_access", "Calendars.ReadWrite", // Scope for reading calendar events ], authorizationEndpoint: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", tokenEndpoint: "https://login.microsoftonline.com/common/oauth2/v2.0/token", }; const CalendarSettingsPage = (props: { setSelectedPage: (page: number) => void; }) => { const [startDate, setStartDate] = useState(false); const { profileData } = useAuthContext(); const [selectedColor, setSelectedColor] = useState( profileData?.eventColor ?? colorMap.pink ); const [previousSelectedColor, setPreviousSelectedColor] = useState( profileData?.eventColor ?? colorMap.pink ); const { mutateAsync: createEventFromProvider } = useCreateEventFromProvider(); const { mutateAsync: updateUserData } = useUpdateUserData(); const fetchAndSaveGoogleEvents = () => { const timeMin = new Date(new Date().setHours(0, 0, 0, 0)); const timeMax = new Date( new Date(new Date().setHours(0, 0, 0, 0)).setDate(timeMin.getDate() + 30) ); fetchGoogleCalendarEvents( profileData?.googleToken, timeMin.toISOString().slice(0, -5) + "Z", timeMax.toISOString().slice(0, -5) + "Z" ).then((response) => { response?.forEach((item) => saveData(item)); }); }; async function saveData(item: any) { await createEventFromProvider(item); } const fetchAndSaveMicrosoftEvents = () => { const startDateTime = new Date(new Date().setHours(0, 0, 0, 0)); const endDateTime = new Date( new Date(new Date().setHours(0, 0, 0, 0)).setDate( startDateTime.getDate() + 30 ) ); fetchMicrosoftCalendarEvents( profileData?.microsoftToken, startDateTime.toISOString().slice(0, -5) + "Z", endDateTime.toISOString().slice(0, -5) + "Z" ).then((response) => { console.log(response); response?.forEach((item) => saveData(item)); }); }; const handleGoogleLogin = async () => { try { const response = await GoogleLogin(); if (response) { const googleUserData = response.data; let idToken = googleUserData?.idToken; if (idToken) { await updateUserData({ newUserData: { googleToken: idToken } }); } } } catch (apiError) { console.log(apiError || "Something went wrong"); } }; const handleMicrosoftSignIn = async () => { try { console.log("Starting Microsoft sign-in..."); const authRequest = new AuthSession.AuthRequest({ clientId: microsoftConfig.clientId, scopes: microsoftConfig.scopes, redirectUri: microsoftConfig.redirectUri, responseType: AuthSession.ResponseType.Code, usePKCE: true, // Enable PKCE }); console.log("Auth request created:", authRequest); const authResult = await authRequest.promptAsync({ authorizationEndpoint: microsoftConfig.authorizationEndpoint, }); console.log("Auth result:", authResult); if (authResult.type === "success" && authResult.params?.code) { const code = authResult.params.code; console.log("Authorization code received:", code); // Exchange authorization code for tokens const tokenResponse = await fetch(microsoftConfig.tokenEndpoint, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", }, body: `client_id=${ microsoftConfig.clientId }&redirect_uri=${encodeURIComponent( microsoftConfig.redirectUri )}&grant_type=authorization_code&code=${code}&code_verifier=${ authRequest.codeVerifier }&scope=${encodeURIComponent( "https://graph.microsoft.com/Calendars.ReadWrite offline_access" )}`, }); console.log("Token response status:", tokenResponse.status); if (!tokenResponse.ok) { console.error("Token exchange failed:", await tokenResponse.text()); return; } const tokenData = await tokenResponse.json(); console.log("Token data received:", tokenData); if (tokenData?.id_token) { console.log("ID token received, updating user data..."); await updateUserData({ newUserData: { microsoftToken: tokenData.access_token }, }); console.log("User data updated successfully."); } } else { console.warn("Authentication was not successful:", authResult); } } catch (error) { console.error("Error during Microsoft sign-in:", error); } }; const debouncedUpdateUserData = useCallback( debounce(async (color: string) => { try { await updateUserData({ newUserData: { eventColor: color, }, }); } catch (error) { console.error("Failed to update color:", error); setSelectedColor(previousSelectedColor); } }, 500), [] ); const handleChangeColor = (color: string) => { setPreviousSelectedColor(selectedColor); setSelectedColor(color); debouncedUpdateUserData(color); }; return ( props.setSelectedPage(0)}> Return to main settings Calendar settings Event Color Preference handleChangeColor(colorMap.pink)}> {selectedColor == colorMap.pink && ( )} handleChangeColor(colorMap.orange)} > {selectedColor == colorMap.orange && ( )} handleChangeColor(colorMap.green)}> {selectedColor == colorMap.green && ( )} handleChangeColor(colorMap.teal)}> {selectedColor == colorMap.teal && ( )} handleChangeColor(colorMap.purple)} > {selectedColor == colorMap.purple && ( )} Weekly Start Date setStartDate(true)} /> Sundays {" "} (default) setStartDate(false)} /> Mondays Add Calendar