Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	components/pages/settings/CalendarSettingsPage.tsx
This commit is contained in:
Milan Paunovic
2024-11-01 03:20:51 +01:00
4 changed files with 306 additions and 200 deletions

View File

@ -74,7 +74,7 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
}, [groceries]);
return (
<View marginH-20 marginB-20>
<View marginH-20 marginB-45>
<HeaderTemplate
message={"Welcome to your grocery list"}
isWelcome={false}

View File

@ -16,6 +16,7 @@ import {settingsPageIndex} from "../calendar/atoms";
import CalendarSettingsDialog from "./calendar_components/CalendarSettingsDialog";
import {useClearTokens} from "@/hooks/firebase/useClearTokens";
import {useCalSync} from "@/hooks/useCalSync";
import Feather from "@expo/vector-icons/Feather";
const CalendarSettingsPage = () => {
@ -234,34 +235,6 @@ const CalendarSettingsPage = () => {
color="black"
text70BL
/>
{profileData?.googleAccounts
? Object.keys(profileData?.googleAccounts)?.map((googleMail) => {
const googleToken = profileData?.googleAccounts?.[googleMail]?.accessToken;
return (
googleToken && (
<Button
key={googleMail}
onPress={() => {
showConfirmationDialog("google", googleMail);
}}
label={`Disconnect ${googleMail}`}
labelStyle={styles.addCalLbl}
labelProps={{
numberOfLines: 2,
}}
iconSource={() => (
<View marginR-15>
<GoogleIcon/>
</View>
)}
style={styles.addCalBtn}
color="black"
text70BL
/>
)
);
})
: null}
{!profileData?.appleAccounts && (
<Button
@ -282,33 +255,6 @@ const CalendarSettingsPage = () => {
/>
)}
{profileData?.appleAccounts
? Object.keys(profileData?.appleAccounts)?.map((appleEmail) => {
const appleToken = profileData?.appleAccounts?.[appleEmail!];
return (
appleToken && (
<Button
key={appleEmail}
onPress={() => showConfirmationDialog("apple", appleEmail)}
label={`Disconnect Apple`}
labelStyle={styles.addCalLbl}
labelProps={{
numberOfLines: 2,
}}
iconSource={() => (
<View marginR-15>
<AppleIcon/>
</View>
)}
style={styles.addCalBtn}
color="black"
text70BL
/>
)
);
})
: null}
<Button
onPress={() => handleMicrosoftSignIn()}
label={profileData?.microsoftAccounts ? "Connect another Outlook account" : "Connect Outlook"}
@ -325,37 +271,6 @@ const CalendarSettingsPage = () => {
color="black"
text70BL
/>
{profileData?.microsoftAccounts
? Object.keys(profileData?.microsoftAccounts)?.map(
(microsoftEmail) => {
const microsoftToken =
profileData?.microsoftAccounts?.[microsoftEmail];
return (
microsoftToken && (
<Button
key={microsoftEmail}
onPress={() => {
showConfirmationDialog("outlook", microsoftEmail);
}}
label={`Disconnect ${microsoftEmail}`}
labelStyle={styles.addCalLbl}
labelProps={{
numberOfLines: 2,
}}
iconSource={() => (
<View marginR-15>
<OutlookIcon/>
</View>
)}
style={styles.addCalBtn}
color="black"
text70BL
/>
)
);
}
)
: null}
{(isConnectedToGoogle ||
isConnectedToMicrosoft ||
@ -371,50 +286,62 @@ const CalendarSettingsPage = () => {
Object.keys(profileData?.googleAccounts)?.map(
(googleEmail) => {
const googleToken =
profileData?.googleAccounts?.[googleEmail];
profileData?.googleAccounts?.[googleEmail]?.accessToken;
return (
googleToken && (
<TouchableOpacity
onPress={() =>
fetchAndSaveGoogleEvents({
token: googleToken,
email: googleEmail,
})
}
>
<View row paddingR-20 center>
<Button
disabled={isSyncingGoogle}
onPress={() =>
fetchAndSaveGoogleEvents({
token: googleToken,
email: googleEmail,
})
}
label={`Sync ${googleEmail}`}
labelStyle={styles.addCalLbl}
labelProps={{numberOfLines: 3}}
iconSource={() => (
<View marginR-15>
<GoogleIcon/>
</View>
)}
style={styles.addCalBtn}
color="black"
text70BL
/>
<View row paddingR-5 center>
<View
style={{
backgroundColor: "#ffffff",
marginBottom: 15,
paddingLeft: 15,
}}
color="black"
text70BL
row
centerV
width="100%"
spread
>
{isSyncingGoogle ? (
<ActivityIndicator/>
<View marginR-5>
<ActivityIndicator/>
</View>
) : (
<Ionicons
name={"refresh"}
size={20}
color={"#000000"}
/>
<View marginR-5>
<Button
style={{backgroundColor: "#ffffff"}}
color="black"
onPress={() =>
fetchAndSaveGoogleEvents({
token: googleToken,
email: googleEmail,
})
}
iconSource={() => <Ionicons
name={"refresh"}
size={20}
color={"#000000"}
/>}
/>
</View>
)}
<View marginR-5>
<GoogleIcon/>
</View>
<Text style={styles.addCalLbl}>
{googleEmail}
</Text>
<Button
style={{backgroundColor: "#ffffff", marginRight: 5}}
color="black"
onPress={
() => showConfirmationDialog("google", googleEmail)
}
iconSource={() => <Feather name="x" size={24} />}
/>
</View>
</TouchableOpacity>
</View>
)
);
}
@ -427,46 +354,57 @@ const CalendarSettingsPage = () => {
const appleToken = profileData?.appleAccounts?.[appleEmail];
return (
appleToken && (
<TouchableOpacity
onPress={() =>
fetchAndSaveAppleEvents({
email: appleEmail,
token: appleToken,
})
}
>
<View row paddingR-20 center>
<Button
disabled={isSyncingApple}
onPress={() =>
fetchAndSaveAppleEvents({
email: appleEmail,
token: appleToken,
})
}
label={isSyncingApple ? "Syncing Events from the Apple calendar..." : `Sync Apple`}
labelStyle={styles.addCalLbl}
labelProps={{numberOfLines: 3}}
iconSource={() => (
<View marginR-15>
<AppleIcon/>
</View>
)}
style={styles.addCalBtn}
color="black"
text70BL
/>
<View row paddingR-5 center>
<View
style={{
backgroundColor: "#ffffff",
marginBottom: 15,
paddingLeft: 15,
}}
color="black"
text70BL
row
centerV
width="100%"
spread
>
<View marginR-5>
<AppleIcon/>
</View>
<Text style={styles.addCalLbl}>
{appleEmail}
</Text>
{isSyncingApple ? (
<ActivityIndicator/>
<View marginR-5>
<ActivityIndicator/>
</View>
) : (
<Ionicons
name={"refresh"}
size={20}
color={"#000000"}
/>
<View marginR-5>
<Button
style={{backgroundColor: "#ffffff"}}
color="black"
onPress={() =>
fetchAndSaveAppleEvents({
email: appleEmail,
token: appleToken,
})
}
iconSource={() => <Ionicons
name={"refresh"}
size={20}
color={"#000000"}
/>}
/>
</View>
)}
<Button
style={{backgroundColor: "#ffffff", marginRight: 5}}
color="black"
onPress={() => showConfirmationDialog("apple", appleEmail)}
iconSource={() => <Feather name="x" size={24} />}
/>
</View>
</TouchableOpacity>
</View>
)
);
})}
@ -478,46 +416,59 @@ const CalendarSettingsPage = () => {
profileData?.microsoftAccounts?.[microsoftEmail];
return (
microsoftToken && (
<TouchableOpacity
onPress={() =>
fetchAndSaveOutlookEvents({
token: microsoftToken,
email: microsoftEmail,
})
}
>
<View row paddingR-20 center>
<Button
disabled={isSyncingOutlook}
onPress={() =>
fetchAndSaveOutlookEvents({
token: microsoftToken,
email: microsoftEmail,
})
}
label={`Sync ${microsoftEmail}`}
labelStyle={styles.addCalLbl}
labelProps={{numberOfLines: 3}}
iconSource={() => (
<View marginR-15>
<OutlookIcon/>
</View>
)}
style={styles.addCalBtn}
color="black"
text70BL
/>
<View row paddingR-5 center>
<View
style={{
backgroundColor: "#ffffff",
marginBottom: 15,
paddingLeft: 15,
}}
color="black"
text70BL
row
centerV
width="100%"
spread
>
{isSyncingOutlook ? (
<ActivityIndicator/>
<View marginR-5>
<ActivityIndicator/>
</View>
) : (
<Ionicons
name={"refresh"}
size={20}
color={"#000000"}
/>
<View marginR-5>
<Button
style={{backgroundColor: "#ffffff"}}
color="black"
onPress={() =>
fetchAndSaveOutlookEvents({
token: microsoftToken,
email: microsoftEmail,
})
}
iconSource={() => <Ionicons
name={"refresh"}
size={20}
color={"#000000"}
/>}
/>
</View>
)}
<View marginR-5>
<OutlookIcon/>
</View>
<Text style={styles.addCalLbl}>
{microsoftEmail}
</Text>
<Button
style={{backgroundColor: "#ffffff", marginRight: 5}}
color="black"
onPress={
() => showConfirmationDialog("outlook", microsoftEmail)
}
iconSource={() => <Feather name="x" size={24} />}
/>
</View>
</TouchableOpacity>
</View>
)
);
}
@ -578,10 +529,10 @@ const styles = StyleSheet.create({
fontSize: 16,
fontFamily: "PlusJakartaSan_500Medium",
flexWrap: "wrap",
width: "75%",
width: "70%",
textAlign: "left",
lineHeight: 20,
overflow: "visible",
overflow: "hidden",
},
subTitle: {
fontFamily: "Manrope_600SemiBold",

View File

@ -0,0 +1,128 @@
import React, { useState } from "react";
import { Dialog, Button, Text, View } from "react-native-ui-lib";
import { StyleSheet } from "react-native";
import { Feather } from "@expo/vector-icons";
interface ConfirmationDialogProps {
visible: boolean;
onDismiss: () => void;
onFirstYes: () => void;
onConfirm: () => void;
}
const DeleteProfileDialogs: React.FC<ConfirmationDialogProps> = ({
visible,
onDismiss,
onFirstYes,
onConfirm,
}) => {
const [confirmationDialog, setConfirmationDialog] = useState<boolean>(false);
return (
<>
<Dialog
visible={visible}
onDismiss={onDismiss}
containerStyle={styles.dialog}
>
<View centerH>
<Feather name="alert-triangle" size={70} color="#FF5449" />
</View>
<Text center style={styles.title}>
Are you sure?
</Text>
<Text
style={{
fontSize: 18,
fontFamily: "PlusJakartaSans_700Bold",
color: "#979797",
marginBottom: 20,
}}
center
>
This action will permanently delete all your data, you won't be able
to recover it!
</Text>
<View centerV></View>
<View row right gap-8>
<Button
label="Cancel"
onPress={onDismiss}
style={styles.cancelBtn}
color="#999999"
labelStyle={{ fontFamily: "Poppins_500Medium", fontSize: 13.53 }}
/>
<Button
label="Yes"
onPress={() => {
setTimeout(() => setConfirmationDialog(true), 300);
onFirstYes();
}}
style={styles.confirmBtn}
labelStyle={{ fontFamily: "PlusJakartaSans_500Medium" }}
/>
</View>
</Dialog>
<Dialog
visible={confirmationDialog}
onDismiss={() => setConfirmationDialog(false)}
containerStyle={styles.dialog}
>
<View center paddingH-10 paddingT-15 paddingB-5>
<Text style={styles.title}>
We're sorry to see you go, are you really sure you want to delete
everything?
</Text>
<View row right gap-8 marginT-15>
<Button
label="Cancel"
onPress={() => {
setConfirmationDialog(false);
}}
style={styles.cancelBtn}
color="#999999"
labelStyle={{ fontFamily: "Poppins_500Medium", fontSize: 13.53 }}
/>
<Button
label="Yes"
onPress={() => {
onConfirm();
setConfirmationDialog(false);
}}
style={styles.confirmBtn}
labelStyle={{ fontFamily: "PlusJakartaSans_500Medium" }}
/>
</View>
</View>
</Dialog>
</>
);
};
// Empty stylesheet for future styles
const styles = StyleSheet.create({
confirmBtn: {
backgroundColor: "#FF5449",
},
cancelBtn: {
backgroundColor: "white",
},
dialog: {
backgroundColor: "white",
paddingHorizontal: 25,
paddingTop: 25,
paddingBottom: 17,
borderRadius: 20,
},
title: {
fontFamily: "Manrope_600SemiBold",
fontSize: 22,
marginBottom: 5,
},
text: {
fontFamily: "PlusJakartaSans_400Regular",
fontSize: 16,
marginBottom: 0,
},
});
export default DeleteProfileDialogs;

View File

@ -3,6 +3,7 @@ import { StyleSheet, TouchableOpacity } from "react-native";
import { ScrollView } from "react-native-gesture-handler";
import * as ImagePicker from "expo-image-picker";
import {
Button,
Colors,
Image,
Picker,
@ -18,6 +19,7 @@ import { useAuthContext } from "@/contexts/AuthContext";
import { useUpdateUserData } from "@/hooks/firebase/useUpdateUserData";
import { useChangeProfilePicture } from "@/hooks/firebase/useChangeProfilePicture";
import { colorMap } from "@/constants/colorMap";
import DeleteProfileDialogs from "../user_components/DeleteProfileDialogs";
const MyProfile = () => {
const { user, profileData } = useAuthContext();
@ -32,6 +34,15 @@ const MyProfile = () => {
string | ImagePicker.ImagePickerAsset | null
>(profileData?.pfp || null);
const [showDeleteDialog, setShowDeleteDialog] = useState<boolean>(false);
const handleHideDeleteDialog = () => {
setShowDeleteDialog(false);
};
const handleShowDeleteDialog = () => {
setShowDeleteDialog(true);
};
const { mutateAsync: updateUserData } = useUpdateUserData();
const { mutateAsync: changeProfilePicture } = useChangeProfilePicture();
const isFirstRender = useRef(true);
@ -93,7 +104,7 @@ const MyProfile = () => {
: profileImage;
return (
<ScrollView style={{ paddingBottom: 100, flex: 1 }}>
<ScrollView style={{ paddingBottom: 20, flex: 1 }}>
<View style={styles.card}>
<Text style={styles.subTit}>Your Profile</Text>
<View row spread paddingH-15 centerV marginV-15>
@ -205,6 +216,22 @@ const MyProfile = () => {
</Picker>
</View>
</View>
<Button
size="large"
backgroundColor="#FF5449"
label="Delete Profile"
style={{ marginTop: 10 }}
labelStyle={{ fontFamily: "PlusJakartaSans_500Medium", fontSize: 15 }}
onPress={handleShowDeleteDialog}
/>
<DeleteProfileDialogs
onFirstYes={() => {
setShowDeleteDialog(false);
}}
visible={showDeleteDialog}
onDismiss={handleHideDeleteDialog}
onConfirm={() => {console.log('delete account here')}}
/>
</ScrollView>
);
};