From 8edb8f47f280bc13af8b68fc42497296ed91a5b6 Mon Sep 17 00:00:00 2001 From: Milan Paunovic Date: Thu, 31 Oct 2024 19:57:06 +0100 Subject: [PATCH 01/12] Small fixes, calendar token refresh for google --- calendar-integration/apple-calendar-utils.js | 11 +- calendar-integration/google-calendar-utils.js | 4 +- components/pages/grocery/AddGroceryItem.tsx | 12 +- components/pages/main/SignInPage.tsx | 396 ++--- .../pages/settings/CalendarSettingsPage.tsx | 1582 ++++++++--------- firebase/functions/index.js | 48 +- hooks/firebase/useClearTokens.ts | 39 + hooks/firebase/useCreateEvent.ts | 23 +- hooks/useFetchAndSaveGoogleEvents.ts | 9 +- 9 files changed, 1092 insertions(+), 1032 deletions(-) create mode 100644 hooks/firebase/useClearTokens.ts diff --git a/calendar-integration/apple-calendar-utils.js b/calendar-integration/apple-calendar-utils.js index 779a4ab..099c8dc 100644 --- a/calendar-integration/apple-calendar-utils.js +++ b/calendar-integration/apple-calendar-utils.js @@ -2,8 +2,9 @@ import * as Calendar from 'expo-calendar'; export async function fetchiPhoneCalendarEvents(familyId, email, startDate, endDate) { try { - const {status} = await Calendar.requestCalendarPermissionsAsync(); - if (status !== 'granted') { + const {granted} = await Calendar.requestCalendarPermissionsAsync(); + + if (!granted) { throw new Error("Calendar permission not granted"); } @@ -22,7 +23,11 @@ export async function fetchiPhoneCalendarEvents(familyId, email, startDate, endD return events.map((event) => { let isAllDay = event.allDay || false; const startDateTime = new Date(event.startDate); - const endDateTime = new Date(event.endDate); + let endDateTime = new Date(event.endDate); + + if (isAllDay) { + endDateTime = startDateTime + } return { id: event.id, diff --git a/calendar-integration/google-calendar-utils.js b/calendar-integration/google-calendar-utils.js index 982ab4e..c68b7b1 100644 --- a/calendar-integration/google-calendar-utils.js +++ b/calendar-integration/google-calendar-utils.js @@ -8,7 +8,9 @@ export async function fetchGoogleCalendarEvents(token, email, familyId, startDat }, ); + const data = await response.json(); + const googleEvents = []; data.items?.forEach((item) => { let isAllDay = false; @@ -49,5 +51,5 @@ export async function fetchGoogleCalendarEvents(token, email, familyId, startDat googleEvents.push(googleEvent); }); - return googleEvents; + return {googleEvents, success: response.ok}; } diff --git a/components/pages/grocery/AddGroceryItem.tsx b/components/pages/grocery/AddGroceryItem.tsx index ec5c7f2..c177d2c 100644 --- a/components/pages/grocery/AddGroceryItem.tsx +++ b/components/pages/grocery/AddGroceryItem.tsx @@ -1,10 +1,12 @@ -import {StyleSheet} from "react-native"; +import {Dimensions, StyleSheet} from "react-native"; import React from "react"; import {Button, View,} from "react-native-ui-lib"; import {useGroceryContext} from "@/contexts/GroceryContext"; import {FontAwesome6} from "@expo/vector-icons"; import PlusIcon from "@/assets/svgs/PlusIcon"; +const { width } = Dimensions.get("screen"); + const AddGroceryItem = () => { const {setIsAddingGrocery} = useGroceryContext(); @@ -65,8 +67,14 @@ const styles = StyleSheet.create({ marginVertical: 10, }, btnContainer: { - width: "100%", + position:"absolute", + bottom: 30, + width: width, + padding: 20, + paddingBottom: 0, justifyContent: "center", + alignItems:"center", + zIndex: 10, }, finishShopBtn: { width: "100%", diff --git a/components/pages/main/SignInPage.tsx b/components/pages/main/SignInPage.tsx index b7d9160..f18d0c5 100644 --- a/components/pages/main/SignInPage.tsx +++ b/components/pages/main/SignInPage.tsx @@ -1,218 +1,214 @@ -import { - Button, - ButtonSize, - Dialog, - Text, - TextField, - TextFieldRef, - View, -} from "react-native-ui-lib"; -import React, { useRef, useState } from "react"; -import { useSignIn } from "@/hooks/firebase/useSignIn"; -import { StyleSheet } from "react-native"; +import {Button, ButtonSize, Dialog, Text, TextField, TextFieldRef, View,} from "react-native-ui-lib"; +import React, {useRef, useState} from "react"; +import {useSignIn} from "@/hooks/firebase/useSignIn"; +import {StyleSheet} from "react-native"; import Toast from "react-native-toast-message"; -import { useLoginWithQrCode } from "@/hooks/firebase/useLoginWithQrCode"; -import { Camera, CameraView } from "expo-camera"; +import {useLoginWithQrCode} from "@/hooks/firebase/useLoginWithQrCode"; +import {Camera, CameraView} from "expo-camera"; const SignInPage = ({ - setTab, -}: { - setTab: React.Dispatch< - React.SetStateAction<"register" | "login" | "reset-password"> - >; + setTab, + }: { + setTab: React.Dispatch< + React.SetStateAction<"register" | "login" | "reset-password"> + >; }) => { - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); - const [hasPermission, setHasPermission] = useState(null); - const [showCameraDialog, setShowCameraDialog] = useState(false); - const passwordRef = useRef(null); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [hasPermission, setHasPermission] = useState(null); + const [showCameraDialog, setShowCameraDialog] = useState(false); + const passwordRef = useRef(null); - const { mutateAsync: signIn, error, isError } = useSignIn(); - const { mutateAsync: signInWithQrCode } = useLoginWithQrCode(); + const {mutateAsync: signIn, error, isError} = useSignIn(); + const {mutateAsync: signInWithQrCode} = useLoginWithQrCode(); - const handleSignIn = async () => { - await signIn({ email, password }); - if (!isError) { - Toast.show({ - type: "success", - text1: "Login successful!", - }); - } else { - Toast.show({ - type: "error", - text1: "Error logging in", - text2: `${error}`, - }); - } - }; + const handleSignIn = async () => { + await signIn({email, password}); + if (!isError) { + Toast.show({ + type: "success", + text1: "Login successful!", + }); + } else { + Toast.show({ + type: "error", + text1: "Error logging in", + text2: `${error}`, + }); + } + }; - const handleQrCodeScanned = async ({ data }: { data: string }) => { - setShowCameraDialog(false); - try { - await signInWithQrCode({ userId: data }); - Toast.show({ - type: "success", - text1: "Login successful with QR code!", - }); - } catch (err) { - Toast.show({ - type: "error", - text1: "Error logging in with QR code", - text2: `${err}`, - }); - } - }; + const handleQrCodeScanned = async ({data}: { data: string }) => { + setShowCameraDialog(false); + try { + await signInWithQrCode({userId: data}); + Toast.show({ + type: "success", + text1: "Login successful with QR code!", + }); + } catch (err) { + Toast.show({ + type: "error", + text1: "Error logging in with QR code", + text2: `${err}`, + }); + } + }; - const getCameraPermissions = async (callback: () => void) => { - const { status } = await Camera.requestCameraPermissionsAsync(); - setHasPermission(status === "granted"); - if (status === "granted") { - callback(); - } - }; + const getCameraPermissions = async (callback: () => void) => { + const {status} = await Camera.requestCameraPermissionsAsync(); + setHasPermission(status === "granted"); + if (status === "granted") { + callback(); + } + }; - return ( - - { - // Move focus to the description field - passwordRef.current?.focus(); - }} - /> - - + - - {selectedStatus === ProfileType.FAMILY_DEVICE - ? "Device Name" - : "First Name"} - - { - lNameRef.current?.focus(); - }} - blurOnSubmit={false} - returnKeyType="next" - /> + setShowAddUserDialog(false)} + center + marginT-30 + > + Return to user settings + + + - {selectedStatus !== ProfileType.FAMILY_DEVICE && ( - <> - Last Name - { - emailRef.current?.focus(); - }} - blurOnSubmit={false} - returnKeyType="next" - /> - - )} + setOnNewUserClick(false)} + > + + + + + + New User Information + + { + setOnNewUserClick(false); + }} + > + + + + - {selectedStatus !== ProfileType.FAMILY_DEVICE && ( - <> - Email Address (Optional) - - - )} + + {pfpUri ? ( + + ) : ( + + } + backgroundColor={Colors.grey60} + style={{borderRadius: 25}} + center + /> + )} - - - ); + {pfpUri ? ( + + + Clear user photo + + + ) : ( + + + Upload User Profile Photo + + + )} + + + + Member Status + + setSelectedStatus(item)} + showSearch + floatingPlaceholder + style={styles.inViewPicker} + trailingAccessory={ + + + + } + > + + + + + + + + + {selectedStatus === ProfileType.FAMILY_DEVICE + ? "Device Name" + : "First Name"} + + { + lNameRef.current?.focus(); + }} + blurOnSubmit={false} + returnKeyType="next" + /> + + {selectedStatus !== ProfileType.FAMILY_DEVICE && ( + <> + Last Name + { + emailRef.current?.focus(); + }} + blurOnSubmit={false} + returnKeyType="next" + /> + + )} + + {selectedStatus !== ProfileType.FAMILY_DEVICE && ( + <> + Email Address (Optional) + + + )} + +