import React, { useState, useEffect } from "react";
import {
View,
Text,
StyleSheet,
Image,
Button,
ScrollView,
TouchableOpacity,
} from "react-native";
import ScrollViewWrapper from "./ScrollViewWrapper";
import AsyncStorage from "@react-native-async-storage/async-storage";
/* image imports */
import Welcomeicon from "../assets/welcomeIcon.png";
import RankIcon from "../assets/rankIcon.png";
import UpArrow from "../assets/upArrow.png";
import StoreIcon from "../assets/storeIcon.png";
import { MaterialIcons } from "@expo/vector-icons";
import { useFonts } from "expo-font";
import * as SplashScreen from "expo-splash-screen";
import { useSelector } from "react-redux";
/**
* The home screen contains a summary of the users's points and ranking.
* The user may navigate to the leaderboard or the prize store from this screen.
*
* @param {Object} navigation the navigation prop passed to the screen
*
* @returns {JSX.Element} The home screen
*/
export default function HomeScreen({ navigation }) {
const user = useSelector((state) => state.userData);
let grade = [];
let allGrades = [];
useSelector((state) => state.usersData).forEach((element) => {
allGrades.push(element);
});
useSelector((state) => state.usersData).forEach((element) => {
if (element.grade == user.grade) grade.push(element);
});
grade.sort(function (a, b) {
return a.points > b.points ? -1 : 1;
});
allGrades.sort(function (a, b) {
return a.points > b.points ? -1 : 1;
});
let idx = -1;
for (let i = 0; i < grade.length; ++i) {
if (grade[i].id === user.id) {
idx = i;
break;
}
}
let allGradesIdx = -1;
for (let i = 0; i < allGrades.length; ++i) {
if (allGrades[i].id === user.id) {
allGradesIdx = i;
break;
}
}
return (
<View style={styles.container}>
<ScrollViewWrapper
contentContainerStyle={styles.container}
>
<Summary user={user} />
<Rank
user={user}
navigation={navigation}
gradesLength={grade.length}
idx={idx + 1}
allGradesLength={allGrades.length}
allGradesIdx={allGradesIdx + 1}
/>
<Prize navigation={navigation} />
</ScrollViewWrapper>
</View>
);
}
/**
* Component displays welcome and user's points.
*
* @param {Object} user the user's data
*
* @returns {JSX.Element} the summary component
*/
function Summary({ user }) {
return (
<View style={[styles.box, { height: "29%" }]}>
<View style={styles.row}>
<Image style={styles.icon} source={Welcomeicon} />
<Text style={styles.h1}>
Welcome,{" "}
{user.username.length > 10
? user.username.substring(0, 9) + "-"
: user.username}
!
</Text>
</View>
<Text style={styles.text}>Total Points:</Text>
<View style={[styles.row, { marginTop: "5%" }]}>
<Text style={styles.number1}>{user.points}</Text>
</View>
</View>
);
}
/**
* Component displays the user's rank among their grade and all users.
* Can be clicked to navigate to the leaderboard.
*
* @param {Object} user the user's data
* @param {Object} navigation the navigation prop passed to the screen
* @param {Number} idx the user's rank among their grade
* @param {Number} gradesLength the number of users in the user's grade
* @param {Number} allGradesLength the number of users in the school
* @param {Number} allGradesIdx the user's rank among all users
*
* @returns {JSX.Element} the rank component
*/
function Rank({
user,
navigation,
idx,
gradesLength,
allGradesLength,
allGradesIdx,
}) {
return (
<TouchableOpacity
style={[styles.box, { height: "44%" }, { marginTop: "0%" }]}
onPress={() => navigation.navigate("Rank")}
>
<View style={styles.rank}>
<Image style={styles.icon} source={RankIcon} />
<Text style={styles.h1}>Rank</Text>
<MaterialIcons
name="keyboard-arrow-right"
size={30}
color="black"
style={styles.arrow}
/>
</View>
<Text style={styles.text}>Among grade {user.grade}s:</Text>
<View style={[styles.row, { marginTop: "3%" }]}>
<Text style={styles.number1}>{idx}</Text>
<Text style={styles.number2}>of {gradesLength}</Text>
</View>
<Text style={styles.text}>Among all grades:</Text>
<View style={[styles.row, { marginTop: "3%" }]}>
<Text style={styles.number1}>{allGradesIdx}</Text>
<Text style={styles.number2}>of {allGradesLength}</Text>
</View>
</TouchableOpacity>
);
}
/**
* Component displays the prize store icon. Can be clicked to navigate to the prize store.
*
* @param {Object} navigation the navigation prop passed to the screen
*
* @returns {JSX.Element} the prize component
*/
function Prize({ navigation }) {
return (
<TouchableOpacity
style={[styles.box, { height: "12%" }, { marginTop: "0%" }]}
onPress={() => navigation.navigate("Prizes")}
>
<View style={styles.rank}>
<Image style={styles.icon} source={StoreIcon} />
<Text style={styles.h1}>Prizes</Text>
<MaterialIcons
name="keyboard-arrow-right"
size={30}
color="black"
style={styles.arrow}
/>
</View>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
h1: {
fontSize: 25,
fontWeight: "bold",
marginBottom: "10%",
color: "#1D1E25",
marginTop: "5%",
},
text: {
fontSize: 14,
fontWeight: "normal",
color: "#808d9e",
marginLeft: "5%",
},
number1: {
fontSize: 60,
fontWeight: "bold",
color: "#1D1E25",
marginLeft: "5%",
marginBottom: '5%'
},
number2: {
fontSize: 18,
fontWeight: "bold",
color: "#808d9e",
marginTop: "8%",
marginLeft: "5%",
},
percent: {
fontSize: 25,
fontWeight: "bold",
color: "#009c35",
marginTop: "7%",
marginLeft: "0%",
},
container: {
flexGrow: 1,
backgroundColor: "#fafafa",
},
box: {
margin: "5%",
width: "90%",
borderRadius: 8,
backgroundColor: "#ffffff",
flexDirection: "column",
justifyContent: "flex-start",
alignItems: "flex-start",
},
shopBox: {
margin: "5%",
width: "90%",
borderRadius: 8,
backgroundColor: "#ffe9e9",
flexDirection: "column",
justifyContent: "flex-start",
alignItems: "flex-start",
marginTop: 0,
},
row: {
flexDirection: "row",
},
icon: {
height: 36,
width: 36,
margin: "5%",
},
arrow: {
marginTop: "5%",
marginLeft: "50%",
},
rank: {
flexDirection: "row",
width: "100%",
},
});