Sherlock / app / (tabs) / (profile) / account.tsx
account.tsx
Raw
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import Colors from '../../../constants/Colors';
import constants from 'expo-constants';
import global from '../../../constants/global';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { ButtonIcon, ButtonText, HStack, Modal, ModalBackdrop, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, set, Toast, ToastTitle, useToast, VStack } from '@gluestack-ui/themed';
import { Button } from '@gluestack-ui/themed';
import { deleteUser } from '../../../components/backend';
import { router } from 'expo-router';
import { sendRecovery } from '../../../components/authHelpers';
import { useEffect } from 'react';
import { ToastDescription } from '@gluestack-ui/themed';
import { Pressable } from '@gluestack-ui/themed';
import relativeTime from 'dayjs/plugin/relativeTime';
import dayjs from 'dayjs';
import { useSettings } from '../../../components/appSettingsContext';
import { useAuth } from '../../../components/authContext';

dayjs.extend(relativeTime);

const Account = () => {
    const [confirmModalVisible, setConfirmModalVisible] = React.useState(false);
    const [changePasswordModalVisible, setChangePasswordModalVisible] = React.useState(false);
    const [changeEmailModalVisible, setChangeEmailModalVisible] = React.useState(false);
    const [deleteVisible, setDeleteVisible] = React.useState(false);
    const [showAlert, setShowAlert] = React.useState(false);
    const [alertMessage, setAlertMessage] = React.useState("");
    const toast = useToast();
    const [waitTime, setWaitTime] = React.useState(0);
    const [expoToken, setToken] = React.useState('');
    const settings = useSettings().settings; //Stores app settings
    const auth = useAuth()

    useEffect(() => {
        if(changePasswordModalVisible){
            setWaitTime(60);
            const interval = setInterval(() => {
                setWaitTime((prev) => {
                    if (prev <= 0) {
                        clearInterval(interval);
                        return 0;
                    }
                    return prev - 1;
                });
            }, 1000);
        }
    }, [changePasswordModalVisible]);

    useEffect(() => {
        if (showAlert) {
            setChangePasswordModalVisible(false);
            setConfirmModalVisible(false);
            toast.show({
                placement: 'bottom',
                duration: 8000,
                render: ({id}) => {
                    const toastId = 'toast-' + id;
                    return (
                        <Toast
                            nativeID={toastId}
                            action='warning'
                            variant='accent'

                            style={{
                                backgroundColor: Colors.dark.redPastelClicked,
                                borderRadius: 10,
                                padding: 10,
                                marginBottom: constants.statusBarHeight + 20,
                            }}
                        >
                            <VStack>
                            <HStack>
                                <MaterialCommunityIcons name="alert" size={24} color={Colors.dark.text} />
                                <ToastTitle 
                                    style={{
                                        color: Colors.dark.text,
                                        fontSize: 20,
                                        fontWeight: 'bold',
                                        marginLeft: 10,
                                    }}
                                >Hmmmm</ToastTitle>

                                <Pressable
                                    style={{
                                        marginLeft: 'auto',
                                    }}
                                    onPress={() => {
                                        console.log('Toast closed');
                                        toast.close(id);
                                    }}
                                >
                                    <MaterialCommunityIcons
                                        name="close"
                                        size={24}
                                        color={Colors.dark.cyan}
                                        style={{
                                            marginLeft: 'auto',
                                            marginRight: 5,
                                        }}
                                    />
                                </Pressable>
                            </HStack>
                            <ToastDescription
                                style={{
                                    color: Colors.dark.text,
                                    fontSize: 16,
                                    marginTop: 5,
                                }}
                            >{alertMessage}</ToastDescription>
                            </VStack>

                        </Toast>
                    );
                },
            });
            setShowAlert(false);
        }
    },[alertMessage]);

    return (
        <View style={styles.container}>

            <Modal
                isOpen={confirmModalVisible}
                onClose={() => {setConfirmModalVisible(false);setDeleteVisible(false);setChangePasswordModalVisible(false);setChangeEmailModalVisible(false)}}
                closeOnOverlayClick={true}
                style={{
                    shadowColor: 'transparent',
                }}
                
            >
                <ModalBackdrop />

                {/* Delete Modal */}
                {deleteVisible&&<ModalContent style={styles.confirmModal}>
                    <ModalHeader>
                        <Text style={styles.modalTitle}>
                            Confirmation
                        </Text>
                        <ModalCloseButton></ModalCloseButton>
                    </ModalHeader>

                    <ModalBody>
                        <Text style={styles.modalText}>
                            Please confirm your account deletion.
                        
                            {'\n\n'}All of your data will be permanently deleted and cannot be undone.
                        </Text>
                    </ModalBody>

                    <ModalFooter>
                        <HStack style={styles.confirmfooter}>
                            <Button
                                style={styles.cancelButton}
                                onPress={() => {
                                    setDeleteVisible(false);
                                    setConfirmModalVisible(false)
                                }}
                            >

                                <ButtonText
                                style={{alignSelf:'center'}}
                                
                                >
                                    Cancel
                                </ButtonText>                            
                            </Button>
                            
                            <Button
                            style={styles.deleteButton}
                                onPress={() => {
                                    deleteUser().then(() => {
                                        console.log('User deleted');
                                        global.aliasClass = "";

                                        router.replace('/')
                                    }).catch((error) => {
                                        console.log('Error deleting user: ', error);
                                        throw error;
                                    })

                                    setDeleteVisible(false);
                                    setConfirmModalVisible(false);
                                }}
                            >
                                <MaterialCommunityIcons
                                    name="delete"
                                    size={22}
                                    color={Colors.dark.redBright}/>

                                <ButtonText
                                >
                                    Delete
                                </ButtonText>
                            </Button>
                        </HStack>
                    </ModalFooter>
                </ModalContent>}

                {/* Change Password Modal */}
                {changePasswordModalVisible&&<ModalContent style={styles.confirmModal}>
                    <ModalHeader>
                        <Text style={styles.modalTitle}>
                            Password Reset
                        </Text>
                    </ModalHeader>
                    <ModalBody>
                        <Text style={styles.modalText}>
                            A password reset link has been sent to your email address.
                            {'\n\n'}If you do not receive the email, please check your spam folder or try again.
                        </Text>
                    </ModalBody>
                    <ModalFooter>
                        <Button
                            style={styles.modalButton}
                            onPress={() => {setChangePasswordModalVisible(false);setConfirmModalVisible(false)}}
                        >
                            <ButtonText
                            style={{alignSelf:'center'}}
                            >
                                Okay, bet.
                            </ButtonText>                            
                        </Button>
                    </ModalFooter>  
                </ModalContent>}
            </Modal>

            <View style={[styles.card, styles.information]}>
                <Text style={styles.title}>Account Information</Text>
                <View style={styles.infoContainer}>
                    <Text style={styles.label}>UUID:</Text>
                    <Text style={styles.value}>{auth.user?.id}</Text>
                </View>
                <View style={styles.infoContainer}>
                    <Text style={styles.label}>Expo Token:</Text>
                    <Text style={styles.value}>{global.expoToken}</Text>
                </View>

                <View style={styles.infoContainer}>
                    <Text style={styles.label}>Created:</Text>
                    <Text style={styles.value}>{new Date(auth.user?.created_at??'').toLocaleString()} ({dayjs(auth.user?.created_at??'').fromNow()})</Text>
                </View>

                <View style={styles.infoContainer}>
                    <Text style={styles.label}>Current alias:</Text>
                    <Text style={styles.value}>{global.alias}</Text>
                </View>

                <View style={styles.infoContainer}>
                    <Text style={styles.label}>Jurisdiction:</Text>
                    {/* Hardcoded jurisdiction atm */}
                    <Text style={styles.value}>Knoxville</Text>
                </View>

            </View>
            
            <View style={[styles.card, styles.information]}>
                <Text style={styles.title}>Email Information</Text>

                <View style={styles.infoContainer}>
                    <Text style={styles.label}>Email:</Text>
                    <Text style={styles.value}>{auth.user?.email??''}</Text>

                    {/* <TouchableOpacity
                        style={styles.changeButton}
                        onPress={() => setChangeEmailModalVisible(true)}
                    >
                        <MaterialCommunityIcons
                            name="pencil"
                            size={22}
                            color={Colors.dark.redBright}/>
                    </TouchableOpacity> */}
                </View>

                <View style={styles.infoContainer}>
                    <Text style={styles.label}>Confirmation Status:</Text>
                    <Text style={styles.value}>{auth.verified?"Confirmed":"Awaiting"}</Text>
                    {auth.verified&&<MaterialCommunityIcons style={{marginLeft:5}} name="check-bold" color={'green'} size={15} />}
                    {!auth.verified&&<MaterialCommunityIcons style={{marginLeft:5}} name="close" color={Colors.dark.redBright} size={15} />}
                </View>
            </View>

            <View style={[styles.card, styles.information]}>
                <Text style={styles.title}>Security</Text>
                
                <View style={styles.infoContainer}>
                    <Text style={styles.label}>Current password:</Text>
                    <Text style={styles.value}>********</Text>

                    <TouchableOpacity
                        style={styles.changeButton}
                        onPress={() => {
                            if(waitTime>0){
                                setShowAlert(true);
                                setAlertMessage("Please wait " + waitTime + " seconds before sending another password reset email.");
                                console.log('Please wait for', waitTime, 'seconds');
                                return;
                            }

                            setChangePasswordModalVisible(true);
                            setConfirmModalVisible(true)

                            if(auth.user?.email != undefined){
                                sendRecovery(auth.user.email).catch((error) => {
                                    setShowAlert(true);
                                    setAlertMessage(error.message);
                                })
                            }
                        }}
                    >
                        <MaterialCommunityIcons
                            name="pencil"
                            size={22}
                            color={Colors.dark.redBright}/>
                    </TouchableOpacity>
                </View>
            </View>



            <VStack>
                <TouchableOpacity
                    style={styles.button}
                    onPress={() => {setDeleteVisible(true);setConfirmModalVisible(true)}}
                >
                    <Text style={styles.buttonText}>
                        Delete account
                    </Text>
                    <MaterialCommunityIcons
                        name="delete"
                        size={24}
                        color={Colors.dark.redBright}/>
                </TouchableOpacity>
            </VStack>
        </View>
    );
};

const styles = StyleSheet.create({
    container: {
        flex: 1,
        padding: 20,
        backgroundColor: Colors.dark.tabBg,
        rowGap: 15,
    },
    information:{
        alignSelf: 'center',
    },
    card:{
        borderRadius: 10,
        backgroundColor: Colors.dark.background,
        padding:10,
        width: global.width*0.95,
    },
    title: {
        fontSize: 24,
        fontWeight: 'bold',
        marginBottom: 5,
        color: Colors.dark.cyan,
    },
    infoContainer: {
        flexDirection: 'row',
        marginBottom: 10,
        alignItems: 'center',
    },
    label: {
        fontWeight: 'bold',
        marginRight: 2,
        color: Colors.dark.text,
    },
    value: {
        color: Colors.dark.darkText,
    },
    changeButton: {
        marginLeft: 'auto',
    },
    button:{
        borderRadius: 50,
        backgroundColor: Colors.dark.alertBackground,
        borderColor: Colors.dark.redPastelClicked,
        borderWidth: 1,
        flexDirection: 'row',
        justifyContent: 'space-between',
        padding: 10,
    },
    buttonText:{
        color: Colors.dark.red,
        fontSize: 18,
        fontWeight: 'bold',
        marginLeft: 10,
    },
    confirmModal:{
        backgroundColor: Colors.dark.background,
    },
    modalTitle:{
        color:Colors.dark.redBright,
        fontWeight:'bold',
        fontSize: 25,
        marginLeft:'auto',
        marginRight:'auto',
    },
    modalText:{
        color:Colors.dark.text,
        fontSize: 16,
        textAlign:'center',
        
    },
    confirmfooter:{
        justifyContent:'space-between',
        alignItems:'center',
        width:'100%',
    },
    deleteButton:{
        backgroundColor: Colors.dark.redPastelClicked,
        borderRadius: 10,
        padding: 10,
        justifyContent:'space-between',
        alignItems:'center',
    },
    cancelButton:{
        backgroundColor: Colors.dark.cyan,
        borderRadius: 10,
        padding: 10,
        justifyContent:'space-between',
        alignItems:'center',    
        alignContent:'center',
    },
    cancelButtonText:{
        textAlignVertical: 'center',
        alignSelf: 'center',

    },
    modalButton:{  
        marginLeft:'auto',
        marginRight:'auto',
        backgroundColor: Colors.dark.cyan,
    }
    

});

export default Account;