Sherlock / app / (tabs) / (profile) / profile.tsx
profile.tsx
Raw
import { Text, View } from '../../../components/Themed';
import React, { useEffect } from 'react'
import { Dimensions, Pressable, StyleSheet, Touchable, TouchableOpacity } from 'react-native';
import { useIsFocused } from '@react-navigation/native';
import { router, useFocusEffect } from 'expo-router';
import { ArrowRightIcon, Button, ButtonIcon, ButtonText, set, VStack, Tooltip, TooltipContent, TooltipText, Avatar, Box, HStack } from '@gluestack-ui/themed';
import { globalStyles } from '../../../constants/styles';
import GLOBAL from '../../../constants/global'
import constants from 'expo-constants';
import { MaterialCommunityIcons, MaterialIcons } from '@expo/vector-icons';
import Colors from '../../../constants/Colors';
import { getUserAlias, createUser, getUserCounts } from '../../../components/backend';
import { formatnum } from '../../../components/postListView';
import global from '../../../constants/global';
import { ScrollView } from 'react-native-gesture-handler';
import { supabase } from '../../../components/supabase';
import { useSettings } from '../../../components/appSettingsContext';
import { useAuth } from '../../../components/authContext';

export default function index(){
  //Uses state hooks for dynamic displaying
  const [email, setEmail] = React.useState('');
  const [displayName, setDisplayName] = React.useState('');
  const [anonName, setAnonName] = React.useState('');
  const [userCounts, setUserCounts] = React.useState({post_count: 0, comment_count: 0, like_count: 0, verification_score: 0, verifiedpost_count:0, dislike_count: 0});
  const [tooltip, setTooltip] = React.useState(false);
  const settings = useSettings().settings; //Stores app settings
  const auth = useAuth()

  useEffect(() => {
    console.log(tooltip)
  },[tooltip])

  useEffect(() => {
    console.log("PROFILE: GETTING USER INFO")

    setEmail(auth.user?.email??'');
    setDisplayName(auth.displayName??'');
    setAnonName(GLOBAL.alias)
  }, [])//Calls only once when the component is mounted

  //Fetches user stats everytime the screen is focused
  useFocusEffect(
    React.useCallback(()=>{
      console.log('Fetching user stats.')
      
      //Later add logic to limit api calls
      getUserCounts()
        .then((counts) => {
          // console.log("PROFILE: COUNTS: ", counts)
          setUserCounts(counts);
        })
        .catch((err) => {
          console.log("PROFILE: COUNTS ERROR: ", err);
        });
    },[])
  )

  async function signOut() {
    const { error } = await supabase.auth.signOut();
    if (error) {
      console.log("Error signing out: ", error);
    } else {      
      console.log("Sign out successful");
      router.replace("/");
    }
  }

  return (
    <View style={styles.root}>
      <ScrollView
        style={styles.container}
        contentContainerStyle={{ alignItems: "center" }}
      >
        <View style={styles.profileHeader}>
          <View style={styles.profileDetails}>
            <View
              style={[
                styles.avatar,
                {
                  backgroundColor:
                    Colors.map[
                      ("class" + GLOBAL.aliasClass) as keyof typeof Colors.map
                    ],
                },
              ]}
            >
              <Text
                adjustsFontSizeToFit
                numberOfLines={1}
                style={[styles.emoji]}
              >
                {" "}
                {GLOBAL.aliasEmoji}{" "}
              </Text>
            </View>

            <View style={styles.usernames}>
              <Text
                adjustsFontSizeToFit
                numberOfLines={1}
                style={styles.displayName}
              >
                {anonName}
              </Text>
              {settings.showEmail && <Text adjustsFontSizeToFit numberOfLines={1} style={styles.email}>
                {email}
              </Text>}
            </View>
          </View>
          <View style={styles.separator} darkColor="rgba(255,255,255,0.1)" />
        </View>

        <Text style={styles.countTitle}>You have made:</Text>

        <View style={styles.userCountCont}>
          {/* Post count */}
          <Pressable style={styles.counts}
            onPress={()=>{
              router.push('./posts')
            }}
          >
            <Text
              adjustsFontSizeToFit
              numberOfLines={1}
              style={styles.countNum}
            >
              {formatnum(userCounts.post_count)}
            </Text>
            <Text>Post{userCounts.post_count==1?"":"s"}</Text>
          </Pressable>

          <View style={styles.vertSeparator} />

          {/* Comment count */}
          <Pressable style={styles.counts}
            onPress={() => {
              router.push('./comments')
            }}
          >
            <Text
              numberOfLines={1}
              adjustsFontSizeToFit
              style={styles.countNum}
            >
              {formatnum(userCounts.comment_count)}
            </Text>
            <Text>Comment{userCounts.comment_count==1?"":"s"}</Text>
          </Pressable>

          <View style={styles.vertSeparator} />

          {/* Like count  */}
          <View style={styles.counts}>
            <Text
              numberOfLines={1}
              adjustsFontSizeToFit
              style={styles.countNum}
            >
              {formatnum(userCounts.like_count)}
            </Text>
            <Text>Like{userCounts.like_count==1?"":"s"}</Text>
          </View>

          <View style={styles.vertSeparator} />

          {/* Dislike count  */}
          <View style={styles.counts}>
            <Text
              numberOfLines={1}
              adjustsFontSizeToFit
              style={styles.countNum}
            >
              {formatnum(userCounts.dislike_count)}
            </Text>
            <Text>Dislike{userCounts.dislike_count?"":"s"}</Text>
          </View>

          {/* <View style={styles.vertSeparator} />

        <View style={styles.counts}>
          <Text adjustsFontSizeToFit numberOfLines={1} style={styles.countNum}>
            {formatnum(userCounts.verification_score)}
          </Text>
          <Text>V. Score</Text>
        </View> */}
        </View>

        <View style={styles.settings}>
          <VStack style={styles.vlayout}>
            <Text style={styles.sectionHeader}>Preferences</Text>

            <TouchableOpacity style={styles.button}
              onPress={() => {
                router.push("./account");
              }}
            >
              <Text style={styles.buttonText}>Account</Text>
              <MaterialCommunityIcons
                name="chevron-right"
                size={35}
                color={Colors.dark.redBright}
              />
            </TouchableOpacity>
            <View style={styles.separator} />

            <TouchableOpacity style={styles.button}
              onPress={() => {
                router.push("./notifications");
              }}
            >
              <Text style={styles.buttonText}>Notifications</Text>
              <MaterialCommunityIcons
                name="chevron-right"
                size={35}
                color={Colors.dark.redBright}
              />
            </TouchableOpacity>
            <View style={styles.separator} />

            <TouchableOpacity style={styles.button}
              onPress={() => {
                router.push("./settings");
              }}
            >
              <Text style={styles.buttonText}>App Settings</Text>
              <MaterialCommunityIcons
                name="chevron-right"
                size={35}
                color={Colors.dark.redBright}
              />
            </TouchableOpacity>
            <View style={styles.separator} />

            <Text style={styles.sectionHeader}>Help Me</Text>

            <TouchableOpacity style={styles.button}
              onPress={() => {
                router.push({
                  pathname: "./feedback",
                  params: { type: "feedback" },
                })
              }}
            >
              <Text style={styles.buttonText}>Feedback/Suggestions</Text>
              <MaterialCommunityIcons
                name="chevron-right"
                size={35}
                color={Colors.dark.redBright}
              />
            </TouchableOpacity>
            <View style={styles.separator} />

            <TouchableOpacity style={styles.button}
              onPress={() =>{router.push('./donations')}}
            >
              <Text style={styles.buttonText}>Keep the app running 🥺</Text>
              <MaterialCommunityIcons
                name="chevron-right"
                size={35}
                color={Colors.dark.redBright}
              />
            </TouchableOpacity>
            <View style={styles.separator} />

            {/* 
              Disabling this for now as support
              for new locations won't happen
              in a while.
            */}
            {/* <TouchableOpacity style={styles.button}
              onPress={() => {
                router.push({
                  pathname: "./feedback",
                  params: { type: "request" },
                })
              }}
            >
              <Text style={styles.buttonText}>Request Location</Text>
              <MaterialCommunityIcons
                name="chevron-right"
                size={35}
                color={Colors.dark.redBright}
              />
            </TouchableOpacity>
            <View style={styles.separator} /> */}

            <Text style={styles.sectionHeader}>Info</Text>

            <TouchableOpacity style={styles.button}
              onPress={() => {
                router.push("./help");
              }}
            >
              <Text style={styles.buttonText}>Help</Text>
              <MaterialCommunityIcons
                name="chevron-right"
                size={35}
                color={Colors.dark.redBright}
              />
            </TouchableOpacity>
            <View style={styles.separator} />

            <TouchableOpacity style={styles.button}
              onPress={() => {
                router.push("./about");
              }}
            >
              <Text style={styles.buttonText}>About the App</Text>
              <MaterialCommunityIcons
                name="chevron-right"
                size={35}
                color={Colors.dark.redBright}
              />
            </TouchableOpacity>
            <View style={styles.separator} />

            <TouchableOpacity style={styles.button}
              onPress={() => {
                router.push("./contact");
              }}
            >
              <Text style={styles.buttonText}>Contact Me</Text>
              <MaterialCommunityIcons
                name="chevron-right"
                size={35}
                color={Colors.dark.redBright}
              />
            </TouchableOpacity>
            <View style={styles.separator} />

            <Text style={styles.sectionHeader}>Legal Stuff</Text>

            <TouchableOpacity style={styles.button}
              onPress={() => {
                router.push({
                  pathname: "./legal",
                  params: { type: "terms" },
                })
              }}
            >
              <Text style={styles.buttonText}>Terms of Service</Text>
              <MaterialCommunityIcons
                name="chevron-right"
                size={35}
                color={Colors.dark.redBright}
              />
            </TouchableOpacity>
            <View style={styles.separator} />

            <TouchableOpacity style={styles.button}
              onPress={() => {
                router.push({
                  pathname: "./legal",
                  params: { type: "privacy" },
                })
              }}
            >
              <Text style={styles.buttonText}>Privacy Policy</Text>
              <MaterialCommunityIcons
                name="chevron-right"
                size={35}
                color={Colors.dark.redBright}
              />
            </TouchableOpacity>

            <Button
              style={globalStyles.profileButton}
              borderRadius={30}
              size="lg"
              bg="#4fb2ab"
              sx={{
                ":active": {
                  bg: "#00ACB5D5",
                },
              }}
              onPress={() => {
                signOut();
              }}
            >
              <ButtonText flex={1} textAlign="center">
                Sign Out
              </ButtonText>
            </Button>
          </VStack>
        </View>
      </ScrollView>
    </View>
  );
}

const width = global.width;
const height = global.height;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: Colors.dark.tabBg,
    marginTop: constants.statusBarHeight,
  },
  root:{
    flex:1,
    backgroundColor: Colors.dark.tabBg,
  },
  displayName: {
    fontSize: 25,
    fontWeight: "bold",
    color: Colors.dark.cyan,
  },
  button:{
    width:'100%',
    height:global.height*0.08,
    flexDirection:'row',
    justifyContent:'space-between',
    alignItems:'center'

  },
  buttonText:{
    color:Colors.dark.text,
    fontWeight:'bold',
    fontSize:18,
    marginLeft:20
  },
  sectionHeader:{
    fontWeight:'bold',
    fontSize:22,
    marginLeft:15,
    textAlign:'left',
    width:'100%',
    color:Colors.dark.cyan,
    marginTop:5
  },
  separator: {
    height: 1,
    width: "85%",
    marginLeft: "auto",
    marginRight: "auto",
    marginTop: 0,
    backgroundColor:Colors.dark.backgroundModal
  },
  profileHeader: {
    backgroundColor: Colors.dark.tabBg,
    top: 0,
    width: Dimensions.get("window").width,
    alignItems: "center",
    justifyContent: "flex-start",
    display: "flex",
    flexDirection: "row",
    flexWrap: "wrap",
    padding: 20,
    paddingBottom: 0,
  },
  profileDetails: {
    display: "flex",
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    width: "100%",
    padding:10,
    backgroundColor: Colors.dark.tabBg,
    alignContent: "center",
    borderRadius: 10,
    columnGap: 10,
  },
  profileAvatar: {
    marginTop: 30,
    alignSelf: "center",
    backgroundColor: Colors.dark.backgroundModal,
    borderRadius: 50,
  },
  email: {
    fontSize: 14,
    textAlign: "left",
  },
  usernames: {
    marginTop: 10,
    width: width * 0.6,
    backgroundColor: Colors.dark.tabBg,
  },
  crimeAliasContainer: {
    marginLeft: "auto",
    marginRight: "auto",
    width: "100%",
    justifyContent: "center",
    alignItems: "center",
  },
  crimeAlias: {
    fontSize: 18,
    fontStyle: "italic",
    fontWeight: "bold",
    textAlign: "center",
    alignSelf: "center",
    marginLeft: "auto",
    marginRight: "auto",
    color: Colors.dark.cyan,
  },
  crimeAliasLabel: {},
  settings: {
    backgroundColor: Colors.dark.background,
    width: Dimensions.get("window").width,
    height: "100%",
    borderTopLeftRadius: 13,
    borderTopRightRadius: 13,
    padding: 20,
    marginBottom:75
    
  },
  vlayout: {
    width: "100%",
    justifyContent: "center",
    alignItems: "center",
    rowGap: 5,
    overflow:'scroll'
  },
  avatar: {
    justifyContent: "center",
    alignItems: "center",
    height: GLOBAL.height * 0.13,
    width: GLOBAL.height * 0.13,
    borderWidth: 5,
    borderColor: Colors.dark.backgroundProfile,
    borderRadius: 30,
    padding: 5,
  },
  emoji: {
    fontSize: 40,
  },
  userCountCont: {
    flexDirection: "row",
    justifyContent: "space-evenly",
    height: GLOBAL.height * 0.1,
    padding: 10,
    backgroundColor: Colors.dark.tabBg,
  },
  counts: {
    flexDirection: "column",
    alignItems: "center",
    padding: 10,
    justifyContent: "center",
    rowGap: 3,
    backgroundColor: Colors.dark.tabBg,
  },
  vertSeparator: {
    width: 1,
    marginTop: "auto",
    marginBottom: "auto",
    height: "90%",
    backgroundColor: "rgba(255,255,255,0.1)",
  },
  countNum:{
    fontSize: 25,
    fontWeight: "bold",
    color: Colors.dark.cyan,
    backgroundColor: Colors.dark.tabBg,
  },
  countTitle:{
    fontSize: 15,
    fontWeight: "bold",
    color: Colors.dark.text,
    marginTop: 10,
  },
});