Home Manual Reference Source

src/screens/Profile.jsx


/**
 * @file Profile.jsx
 * @desc This file contains the Profile screen component.
 * The Profile screen displays user information such as name, email, profession, investment profile, and a list of investments.
 * Users can also view and change their profile picture.
 */

import React, { useEffect, useState } from 'react';
import { View, StatusBar, Text, StyleSheet, TouchableOpacity, ScrollView, Image, Modal, RefreshControl } from 'react-native';
import { Feather, MaterialIcons } from '@expo/vector-icons';
import DBStorage from '../database/firebaseDBMethods';
import { useLoading } from '../Context';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { FontAwesome } from '@expo/vector-icons';
import Toast from 'react-native-toast-message';

/**
 * @function Perfil
 * @desc Profile screen component
 * @param {object} navigation - Navigation object for navigating between screens
 * @returns {JSX.Element} Profile screen component
 */
export default function Perfil({ navigation }) {
  const [refreshing, setRefreshing] = useState(false);

  const [modalVisible, setModalVisible] = useState(false);

  const [profilePic, setProfilePic] = useState(null);
  const [showProfilePic, setShowProfilePic] = useState(false);

  const { showLoading, hideLoading, setShouldRefresh } = useLoading();
  const [dados, setDados] = useState({
    email: "",
    name: "",
    perfilInvestimento: "",
    profissao: ""
  });
  const [investimentos, setInvestimentos] = useState([{
    label: "",
    status: 0,
    value: "",
    interest: true
  }]);

  const [refreshProf, setRefreshProf] = useState(false);

  /**
   * @function getAllData
   * @desc Fetches user data and investments from AsyncStorage and Firestore
   */
  useEffect(() => {
    const getAllData = async () => {
      reloadPic();
      const doc = await AsyncStorage.getItem('userDoc');
      const fr = new DBStorage(doc);

      try {
        showLoading();
        let res = await fr.getFullDoc();
        if (res) {
          let uD = res.userData;
          let inv = res.investments;
          let invs = []
          if (inv) {
            inv.forEach(element => {
              invs.push({
                interest: element.interest,
                label: element.label,
                status: element.status, // 1=queda, 0=crescimento
                value: parseFloat(element.value).toFixed(2)
              })
            });
          }
          setDados(uD);
          setInvestimentos(invs);
        } else {
          console.log(res)
        }
        setShouldRefresh(false);
      } catch (err) { console.log(err); } finally { hideLoading(); }
    };

    getAllData().catch(console.error);
  }, [refreshProf, profilePic]);

  const reloadPic = async () => {
    const profPic = await AsyncStorage.getItem('profilePic');
    if (profPic) {
      setProfilePic(profPic);
      setShowProfilePic(true);
    }
  }

  const onRefresh = async () => {
    setRefreshing(true);
    await reloadPic();
    setTimeout(() => {
      setRefreshing(false);
    }, 2000);
  };


  return (
    <View>
      <ScrollView refreshControl={
        <RefreshControl
          refreshing={refreshing}
          onRefresh={onRefresh}
          colors={['#0000ff']}
          tintColor="#0000ff" />}>
        <View style={{ height: '100%', marginTop: statusBarHeight }} >
          <View style={styles.container}>
            <View style={styles.content}>
              <Text
                style={styles.userName}
                from={{ translateX: -300 }}
                animate={{ translateX: 0 }}
                transition={{ type: 'timing', duration: 1000, delay: 300 }}>
                {dados.name + '\n'}
                <Text style={styles.label}>{dados.email}</Text>
              </Text>

              <TouchableOpacity
                activeOpacity={0.9}
                style={styles.btnUser}
                onPress={() => {
                  setModalVisible(true);
                }}>
                {showProfilePic ?
                  <Image source={{ uri: profilePic }} style={styles.header_profilePic} /> :
                  <Feather name="user" size={27} color={'#fff'} />}

                <Modal animationType="slide-up" transparent={true} visible={modalVisible} 
                  style={styles.modal} onRequestClose={() => { setModalVisible(!modalVisible); }}>
                  <TouchableOpacity style={styles.modalBackground} activeOpacity={1} onPressOut={() => setModalVisible(!modalVisible)} >
                    <View style={styles.modalContent}>
                      
                      <TouchableOpacity style={styles.modalOpt} onPress={() => {
                        setModalVisible(false);
                        navigation.navigate("SeePicture", { photoUrl: profilePic })
                      }}>
                        <Text style={styles.modalOptTxt}>Ver foto</Text>
                      </TouchableOpacity>
                      
                      <TouchableOpacity style={styles.modalOpt} onPress={() => { setModalVisible(false); navigation.navigate("TypeOfPic") }}>
                        <Text style={styles.modalOptTxt}>Alterar foto</Text>
                      </TouchableOpacity>
                      
                      <TouchableOpacity onPress={() => setModalVisible(!modalVisible)} style={styles.close}>
                        <FontAwesome style={styles.closeButtonText} name="close" size={28} color="darkblue" />
                      </TouchableOpacity>
                    </View>
                  </TouchableOpacity>
                </Modal>
              </TouchableOpacity>
            </View>
          </View>

          <View style={styles.data}>
            <Text style={styles.text}>
              Profissão:
              <Text style={styles.insiderText}>{' ' + dados.profissao}</Text>
            </Text>

            <Text style={styles.text}>
              Perfil de investimento:
              <Text style={styles.insiderText}>
                {' ' + dados.perfilInvestimento}
              </Text>
            </Text>

            <View style={{ marginTop: 10 }}>
              <Text style={styles.text}>Ações de Interesse </Text>

              <ScrollView>
                {investimentos.map((item, index) => (
                  item.interest ?
                    <View style={styles.inv_container} key={index}>
                      <View style={styles.inv_content} key={index}>
                        <Text style={styles.inv_label} key={index}>{item.label}</Text>
                        <View>
                          <Text key={index}
                            style={
                              item.status == 0
                                ? styles.inv_value
                                : styles.inv_expenses
                            }>
                            {item.status == 0
                              ? `${item.value}%`
                              : `-${item.value}%`}
                          </Text>
                        </View>
                      </View>
                    </View> : <View key={index}></View>
                ))}
              </ScrollView>

              <View
                style={{ marginTop: 30, flexDirection: 'row' }}>
                <TouchableOpacity onPress={() => {
                  navigation.navigate("checkbox",
                    { invs: investimentos, refreshProfile: () => { setRefreshProf(!refreshProf); } })
                }}>
                  <View style={styles.addView}>
                    <Text style={{ paddingRight: 8, paddingTop: 3, fontSize: 12 }}>
                      Alterar
                    </Text>

                    <Feather name="refresh-cw" size={18} color="darkblue" />
                  </View>
                </TouchableOpacity>
              </View>
            </View>
          </View>

        </View>
      </ScrollView>
      <View style={styles._homeBtnView}>
        <TouchableOpacity
          style={styles._homeBtn}
          onPress={() => {
            navigation.navigate('Home');
          }}>
          <MaterialIcons name="home" size={30} color="#fff" />
        </TouchableOpacity>
      </View>
      <Toast />
    </View>
  );
}

const styles = StyleSheet.create({
  closeButtonText: {
    textAlign: 'right'
  },
  modalOptTxt: {
    fontSize: 20,
    color: 'darkblue'
  },
  modalBackground: {
    flex: 0,
    justifyContent: 'center',
    alignItems: 'flex-end',
    zIndex: 999,
  },
  modalContent: {
    borderRadius: 10,
    width: 200,
    elevation: 100,
    position: 'absolute',
    right: 40,
    top: 70
  },
  modalOpt: {
    borderBottomWidth: 1,
    borderBottomColor: '#c5c5c5',
    paddingVertical: 8,
    paddingHorizontal: 5,
    backgroundColor: 'rgba(166, 166, 166, 0.8)',
    borderRadius: 6,
    marginBottom: 5
  },

  header_profilePic: {
    width: 60,
    height: 60,
    borderRadius: 100,
    borderWidth: 1,
  },
  addView: {
    flexDirection: 'row',
    borderWidth: 1,
    borderColor: 'darkblue',
    borderRadius: 5,
    paddingVertical: 5,
    paddingHorizontal: 12,
    alignContent: 'center',
    alignItems: 'center',
  },
  text: {
    fontWeight: 'bold',
    fontSize: 20,
    paddingTop: 5,
    paddingBottom: 5,
    marginBottom: 10,
    color: 'darkblue',
  },
  insiderText: {
    color: '#000',
    fontWeight: 'normal',
  },
  container: {
    backgroundColor: 'darkblue',
    flexDirection: 'row',
    paddingVertical: 40,
    paddingHorizontal: 24,
  },
  content: {
    flex: 1,
    alignItems: 'center',
    flexDirection: 'row',
    justifyContent: 'space-between',
  },
  userName: {
    fontSize: 18,
    color: '#fff',
    fontWeight: 'bold',
    marginTop: 5,
  },
  btnUser: {
    width: 44,
    height: 44,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 44 / 2,
  },
  data: {
    color: '#dadada',
    padding: 15,
  },
  label: {
    fontWeight: 'bold',
    fontSize: 14,
    paddingTop: 5,
    marginTop: 5,
  },
  list: {
    marginStart: 14,
    marginEnd: 14,
  },
  _homeBtnView: {
    marginHorizontal: 30,
    flexDirection: 'row',
    justifyContent: 'space-between',
    position: 'absolute',
    bottom: -200,
    right: 10,
  },
  _homeBtn: {
    padding: 10,
    borderRadius: 100,
    backgroundColor: 'darkblue',
  },

  inv_container: {
    flex: 1,
    marginBottom: 12,
    borderBottomWidth: 0.5,
    borderBottomColor: '#dadada',
  },
  inv_content: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    marginTop: 2,
    marginBottom: 8,
  },
  inv_data: {
    color: '#dadada',
    fontWeight: 'bold',
  },
  inv_label: {
    fontWeight: 'bold',
    fontSize: 16,
  },
  inv_value: {
    fontSize: 15,
    color: '#2ecc71',
    fontWeight: 'bold',
  },
  inv_expenses: {
    fontSize: 15,
    color: '#e74c3c',
    fontWeight: 'bold',
  },
});