From 2ca1dd13ca7f7d1892192aa265e88305de0fb267 Mon Sep 17 00:00:00 2001 From: Keannu Bernasol Date: Mon, 14 Aug 2023 21:57:52 +0800 Subject: [PATCH] Finalize changes to using modals for user feedback --- App.tsx | 7 +++- src/components/Api/Api.tsx | 2 +- src/routes/Activation/Activation.tsx | 28 ++++++++----- src/routes/Home/Home.tsx | 16 +++---- src/routes/Login/Login.tsx | 13 +++--- src/routes/Onboarding/Onboarding.tsx | 32 ++++++++++++-- src/routes/Register/Register.tsx | 4 +- src/routes/Revalidation/Revalidation.tsx | 12 +++--- src/routes/StartStudying/StartStudying.tsx | 18 ++++---- src/routes/SubjectsPage/SubjectsPage.tsx | 49 ++++++++++------------ src/routes/UserInfoPage/UserInfoPage.tsx | 28 ++++++------- 11 files changed, 119 insertions(+), 90 deletions(-) diff --git a/App.tsx b/App.tsx index 92d2b63..7130bbe 100644 --- a/App.tsx +++ b/App.tsx @@ -1,5 +1,5 @@ import "react-native-gesture-handler"; -import { Text } from "react-native"; +import styles from "./src/styles"; import { NavigationContainer } from "@react-navigation/native"; import { createDrawerNavigator } from "@react-navigation/drawer"; import { Provider } from "react-redux"; @@ -60,7 +60,10 @@ export default function App() { } }, [initialRoute]); return ( - }> + } + textStyle={{ ...styles.text_white_tiny_bold }} + > diff --git a/src/components/Api/Api.tsx b/src/components/Api/Api.tsx index 54fb465..4564ee4 100644 --- a/src/components/Api/Api.tsx +++ b/src/components/Api/Api.tsx @@ -28,7 +28,7 @@ const instance = axios.create({ timeout: 1000, }); -console.log(backendURL); +console.log("Using backend API:", backendURL); // 3rd Party APIs export const urlProvider = diff --git a/src/routes/Activation/Activation.tsx b/src/routes/Activation/Activation.tsx index 10aab6a..c2846c2 100644 --- a/src/routes/Activation/Activation.tsx +++ b/src/routes/Activation/Activation.tsx @@ -6,6 +6,7 @@ import { useNavigation, useRoute } from "@react-navigation/native"; import { useEffect, useState } from "react"; import { UserActivate } from "../../components/Api/Api"; import { RootDrawerParamList } from "../../interfaces/Interfaces"; +import { useToast } from "react-native-toast-notifications"; interface ActivationRouteParams { uid?: string; @@ -16,9 +17,7 @@ export default function Activation() { const route = useRoute(); const { uid, token } = (route.params as ActivationRouteParams) || ""; const navigation = useNavigation(); - const [state, setState] = useState( - "Activating with UID " + uid + " and Token " + token - ); + const toast = useToast(); const [loading, setLoading] = useState(true); useEffect(() => { @@ -28,16 +27,22 @@ export default function Activation() { token: String(token), }); if (result) { - setTimeout(() => { - setState("Activation successful!"); - }, 1000); + toast.show("Activation successful", { + type: "success", + placement: "top", + duration: 4000, + animationType: "slide-in", + }); setTimeout(() => { navigation.navigate("Login"); }, 2000); } else { - setTimeout(() => { - setState("Activation unsuccessful\nPlease contact support"); - }, 1000); + toast.show("Activation unsuccessful. Please contact support", { + type: "warning", + placement: "top", + duration: 4000, + animationType: "slide-in", + }); } setLoading(false); } @@ -63,8 +68,9 @@ export default function Activation() { size={96} color={colors.secondary_1} /> - {state} - {uid + "\n" + token} + + {"Activating with UID: " + uid + "\nToken: " + token} + ); diff --git a/src/routes/Home/Home.tsx b/src/routes/Home/Home.tsx index aad9597..759eef4 100644 --- a/src/routes/Home/Home.tsx +++ b/src/routes/Home/Home.tsx @@ -1,5 +1,5 @@ import styles, { Viewport, colors } from "../../styles"; -import { View, Text, ToastAndroid } from "react-native"; +import { View, Text } from "react-native"; import AnimatedContainer from "../../components/AnimatedContainer/AnimatedContainer"; import { useState, useEffect } from "react"; import MapView, { Callout, Marker, UrlTile } from "react-native-maps"; @@ -46,8 +46,8 @@ export default function Home() { "Location permission was denied. Please allow in order to use StudE", { type: "warning", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", } ); @@ -129,18 +129,18 @@ export default function Home() { onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["user"] }); queryClient.invalidateQueries({ queryKey: ["user_status"] }); - toast.show("You are no longer studying " + subject, { + toast.show("You are no longer studying \n" + subject, { type: "success", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); }, onError: () => { toast.show("Server error. Unable to update student status", { type: "warning", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); }, diff --git a/src/routes/Login/Login.tsx b/src/routes/Login/Login.tsx index 5050439..aad5f4c 100644 --- a/src/routes/Login/Login.tsx +++ b/src/routes/Login/Login.tsx @@ -8,7 +8,6 @@ import { TextInputChangeEventData, } from "react-native"; import { useDispatch } from "react-redux"; -import { colors } from "../../styles"; import { useState } from "react"; import LoginIcon from "../../icons/LoginIcon/LoginIcon"; import Button from "../../components/Button/Button"; @@ -89,16 +88,16 @@ export default function Login() { navigation.navigate("Onboarding"); toast.show("Successfully logged in", { type: "success", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); } else { dispatch(unsetOnboarding()); toast.show("Successfully logged in", { type: "success", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); navigation.navigate("Home"); @@ -108,8 +107,8 @@ export default function Login() { console.log(ParseLoginError(JSON.stringify(result[1]))); toast.show(JSON.stringify(result[1]), { type: "warning", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); } diff --git a/src/routes/Onboarding/Onboarding.tsx b/src/routes/Onboarding/Onboarding.tsx index 9aef47e..0d52063 100644 --- a/src/routes/Onboarding/Onboarding.tsx +++ b/src/routes/Onboarding/Onboarding.tsx @@ -48,6 +48,14 @@ export default function Onboarding() { })); setSemesters(semesters); }, + onError: () => { + toast.show("Server error: Unable to query available semesters", { + type: "warning", + placement: "top", + duration: 2000, + animationType: "slide-in", + }); + }, }); // Year Level const [selected_yearlevel, setSelectedYearLevel] = useState(""); @@ -66,6 +74,14 @@ export default function Onboarding() { })); setYearLevels(year_levels); }, + onError: () => { + toast.show("Server error: Unable to query available year levels", { + type: "warning", + placement: "top", + duration: 2000, + animationType: "slide-in", + }); + }, }); // Course const [selected_course, setSelectedCourse] = useState(""); @@ -87,6 +103,14 @@ export default function Onboarding() { })); setCourses(courses); }, + onError: () => { + toast.show("Server error: Unable to query available courses", { + type: "warning", + placement: "top", + duration: 2000, + animationType: "slide-in", + }); + }, }); if (yearlevel_query.error || semester_query.error || course_query.error) { return ( @@ -230,8 +254,8 @@ export default function Onboarding() { dispatch(setUser(result[1])); toast.show("Changes applied successfully", { type: "success", - placement: "bottom", - duration: 6000, + placement: "top", + duration: 2000, animationType: "slide-in", }); navigation.navigate("Home"); @@ -241,8 +265,8 @@ export default function Onboarding() { "An error has occured\nChanges have not been saved", { type: "warning", - placement: "bottom", - duration: 6000, + placement: "top", + duration: 2000, animationType: "slide-in", } ); diff --git a/src/routes/Register/Register.tsx b/src/routes/Register/Register.tsx index f9d50cf..37f3a0f 100644 --- a/src/routes/Register/Register.tsx +++ b/src/routes/Register/Register.tsx @@ -146,7 +146,7 @@ export default function Register() { "Success! An email has been sent to activate your account", { type: "success", - placement: "bottom", + placement: "top", duration: 6000, animationType: "slide-in", } @@ -157,7 +157,7 @@ export default function Register() { } else { toast.show(JSON.stringify(result[1]), { type: "warning", - placement: "bottom", + placement: "top", duration: 6000, animationType: "slide-in", }); diff --git a/src/routes/Revalidation/Revalidation.tsx b/src/routes/Revalidation/Revalidation.tsx index 9d8bd93..c633f99 100644 --- a/src/routes/Revalidation/Revalidation.tsx +++ b/src/routes/Revalidation/Revalidation.tsx @@ -37,8 +37,8 @@ export default function Revalidation() { dispatch(setOnboarding()); toast.show("Previous session restored", { type: "success", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); await setTimeout(() => { @@ -48,8 +48,8 @@ export default function Revalidation() { dispatch(unsetOnboarding()); toast.show("Previous session restored", { type: "success", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); await setTimeout(() => { @@ -60,8 +60,8 @@ export default function Revalidation() { await setState("Session expired"); toast.show("Session expired. Please login again", { type: "warning", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); await setTimeout(() => { diff --git a/src/routes/StartStudying/StartStudying.tsx b/src/routes/StartStudying/StartStudying.tsx index 265b23e..fb46b29 100644 --- a/src/routes/StartStudying/StartStudying.tsx +++ b/src/routes/StartStudying/StartStudying.tsx @@ -40,9 +40,9 @@ export default function StartStudying({ route }: any) { }, onError: () => { toast.show("Server error: Unable to query available subjects", { - type: "error", - placement: "bottom", - duration: 4000, + type: "warning", + placement: "top", + duration: 2000, animationType: "slide-in", }); }, @@ -53,19 +53,19 @@ export default function StartStudying({ route }: any) { onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["user"] }); queryClient.invalidateQueries({ queryKey: ["user_status"] }); - toast.show("You are now studying " + selected_subject, { + toast.show("You are now studying \n" + selected_subject, { type: "success", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); navigation.navigate("Home"); }, onError: () => { toast.show("A server error has occured. Please try again", { - type: "error", - placement: "bottom", - duration: 4000, + type: "warning", + placement: "top", + duration: 2000, animationType: "slide-in", }); }, diff --git a/src/routes/SubjectsPage/SubjectsPage.tsx b/src/routes/SubjectsPage/SubjectsPage.tsx index 2db5e3b..68b5bd5 100644 --- a/src/routes/SubjectsPage/SubjectsPage.tsx +++ b/src/routes/SubjectsPage/SubjectsPage.tsx @@ -1,45 +1,28 @@ import * as React from "react"; import styles from "../../styles"; +import { View, Text } from "react-native"; +import { useState } from "react"; import { - View, - Text, - TextInput, - NativeSyntheticEvent, - TextInputChangeEventData, -} from "react-native"; -import { useEffect, useState } from "react"; -import { - SemesterParams, UserInfoParams, - Semester, SubjectParams, Subject, - YearLevel, - Course, OptionType, - Subjects, } from "../../interfaces/Interfaces"; import Button from "../../components/Button/Button"; import { Image } from "react-native"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; -import { - GetCourses, - GetSemesters, - GetSubjects, - GetYearLevels, - PatchUserInfo, - UserInfo, -} from "../../components/Api/Api"; +import { GetSubjects, PatchUserInfo, UserInfo } from "../../components/Api/Api"; import { colors } from "../../styles"; import DropDownPicker from "react-native-dropdown-picker"; import AnimatedContainerNoScroll from "../../components/AnimatedContainer/AnimatedContainerNoScroll"; import { useSelector } from "react-redux"; import { RootState } from "../../features/redux/Store/Store"; +import { useToast } from "react-native-toast-notifications"; export default function SubjectsPage() { const logged_in_user = useSelector((state: RootState) => state.user.user); const queryClient = useQueryClient(); - const [feedback, setFeedback] = useState(""); + const toast = useToast(); // User Info const [user, setUser] = useState({ first_name: "", @@ -72,7 +55,12 @@ export default function SubjectsPage() { setSelectedSubjects(data[1].subjects); }, onError: () => { - setFeedback("Unable to query user info"); + toast.show("Server Error: Unable to query user info", { + type: "warning", + placement: "top", + duration: 2000, + animationType: "slide-in", + }); }, }); const mutation = useMutation({ @@ -81,7 +69,12 @@ export default function SubjectsPage() { queryClient.invalidateQueries({ queryKey: ["user"] }); queryClient.invalidateQueries({ queryKey: ["subjects"] }); setSelectedSubjects([]); - setFeedback("Changes applied successfully"); + toast.show("Changes applied successfully", { + type: "success", + placement: "top", + duration: 2000, + animationType: "slide-in", + }); }, }); @@ -106,7 +99,12 @@ export default function SubjectsPage() { } }, onError: () => { - setFeedback("Unable to query subject info"); + toast.show("Server Error: Unable to query subject info", { + type: "warning", + placement: "top", + duration: 2000, + animationType: "slide-in", + }); }, }); @@ -189,7 +187,6 @@ export default function SubjectsPage() { Save Changes - {feedback} diff --git a/src/routes/UserInfoPage/UserInfoPage.tsx b/src/routes/UserInfoPage/UserInfoPage.tsx index 3be501b..6292c11 100644 --- a/src/routes/UserInfoPage/UserInfoPage.tsx +++ b/src/routes/UserInfoPage/UserInfoPage.tsx @@ -58,16 +58,16 @@ export default function UserInfoPage() { queryClient.invalidateQueries({ queryKey: ["user_status"] }); toast.show("Changes applied successfully", { type: "success", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); }, onError: () => { toast.show("An error has occured\nChanges have not been saved", { type: "warning", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); }, @@ -112,7 +112,7 @@ export default function UserInfoPage() { toast.show("Server Error: Unable to query user info", { type: "warning", placement: "bottom", - duration: 4000, + duration: 2000, animationType: "slide-in", }); }, @@ -130,7 +130,7 @@ export default function UserInfoPage() { toast.show("Changes applied successfully", { type: "success", placement: "bottom", - duration: 4000, + duration: 2000, animationType: "slide-in", }); dispatch(setUserinState(user)); @@ -139,7 +139,7 @@ export default function UserInfoPage() { toast.show("An error has occured\nChanges have not been saved", { type: "warning", placement: "bottom", - duration: 4000, + duration: 2000, animationType: "slide-in", }); }, @@ -164,8 +164,8 @@ export default function UserInfoPage() { onError: () => { toast.show("Server Error: Unable to query semester info", { type: "warning", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); }, @@ -188,8 +188,8 @@ export default function UserInfoPage() { onError: () => { toast.show("Server Error: Unable to query year level info", { type: "warning", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); }, @@ -212,8 +212,8 @@ export default function UserInfoPage() { onError: () => { toast.show("Server Error: Unable to query course info", { type: "warning", - placement: "bottom", - duration: 4000, + placement: "top", + duration: 2000, animationType: "slide-in", }); }, @@ -426,7 +426,7 @@ export default function UserInfoPage() { Irregular