Move to modals for user feedback

This commit is contained in:
Keannu Bernasol 2023-08-14 21:13:46 +08:00
parent 529a7a75fd
commit ff114b496c
10 changed files with 203 additions and 82 deletions

48
App.tsx
View file

@ -24,6 +24,8 @@ import UserInfoPage from "./src/routes/UserInfoPage/UserInfoPage";
import SubjectsPage from "./src/routes/SubjectsPage/SubjectsPage"; import SubjectsPage from "./src/routes/SubjectsPage/SubjectsPage";
import Loading from "./src/routes/Loading/Loading"; import Loading from "./src/routes/Loading/Loading";
import StartStudying from "./src/routes/StartStudying/StartStudying"; import StartStudying from "./src/routes/StartStudying/StartStudying";
import { ToastProvider } from "react-native-toast-notifications";
import AppIcon from "./src/icons/AppIcon/AppIcon";
const Drawer = createDrawerNavigator(); const Drawer = createDrawerNavigator();
@ -58,28 +60,30 @@ export default function App() {
} }
}, [initialRoute]); }, [initialRoute]);
return ( return (
<QueryClientProvider client={queryClient}> <ToastProvider icon={<AppIcon size={64} />}>
<Provider store={store}> <QueryClientProvider client={queryClient}>
<StatusBar style="light" /> <Provider store={store}>
<StatusBar style="light" />
<NavigationContainer linking={linking} fallback={<Loading />}> <NavigationContainer linking={linking} fallback={<Loading />}>
<Drawer.Navigator <Drawer.Navigator
initialRouteName="Revalidation" initialRouteName="Revalidation"
drawerContent={CustomDrawerContent} drawerContent={CustomDrawerContent}
screenOptions={DrawerScreenSettings} screenOptions={DrawerScreenSettings}
> >
<Drawer.Screen name="Home" component={Home} /> <Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="Login" component={Login} /> <Drawer.Screen name="Login" component={Login} />
<Drawer.Screen name="Register" component={Register} /> <Drawer.Screen name="Register" component={Register} />
<Drawer.Screen name="Onboarding" component={Onboarding} /> <Drawer.Screen name="Onboarding" component={Onboarding} />
<Drawer.Screen name="Revalidation" component={Revalidation} /> <Drawer.Screen name="Revalidation" component={Revalidation} />
<Drawer.Screen name="Activation" component={Activation} /> <Drawer.Screen name="Activation" component={Activation} />
<Drawer.Screen name="User Info" component={UserInfoPage} /> <Drawer.Screen name="User Info" component={UserInfoPage} />
<Drawer.Screen name="Subjects" component={SubjectsPage} /> <Drawer.Screen name="Subjects" component={SubjectsPage} />
<Drawer.Screen name="Start Studying" component={StartStudying} /> <Drawer.Screen name="Start Studying" component={StartStudying} />
</Drawer.Navigator> </Drawer.Navigator>
</NavigationContainer> </NavigationContainer>
</Provider> </Provider>
</QueryClientProvider> </QueryClientProvider>
</ToastProvider>
); );
} }

10
package-lock.json generated
View file

@ -36,6 +36,7 @@
"react-native-screens": "~3.20.0", "react-native-screens": "~3.20.0",
"react-native-select-dropdown": "^3.3.4", "react-native-select-dropdown": "^3.3.4",
"react-native-svg": "13.4.0", "react-native-svg": "13.4.0",
"react-native-toast-notifications": "^3.3.1",
"react-query": "^3.39.3", "react-query": "^3.39.3",
"react-redux": "^8.1.1", "react-redux": "^8.1.1",
"redux": "^4.2.1" "redux": "^4.2.1"
@ -12453,6 +12454,15 @@
"react-native": "*" "react-native": "*"
} }
}, },
"node_modules/react-native-toast-notifications": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/react-native-toast-notifications/-/react-native-toast-notifications-3.3.1.tgz",
"integrity": "sha512-yc1Q2nOdIYvAf0GAIlmg8q42hiwpEHnLxkxJ6P+tN6jpcKZ1qzMXlgnmNdyF9cm9VOyHQexEP8952IKNAv1Olw==",
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native/node_modules/promise": { "node_modules/react-native/node_modules/promise": {
"version": "8.3.0", "version": "8.3.0",
"resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",

View file

@ -37,6 +37,7 @@
"react-native-screens": "~3.20.0", "react-native-screens": "~3.20.0",
"react-native-select-dropdown": "^3.3.4", "react-native-select-dropdown": "^3.3.4",
"react-native-svg": "13.4.0", "react-native-svg": "13.4.0",
"react-native-toast-notifications": "^3.3.1",
"react-query": "^3.39.3", "react-query": "^3.39.3",
"react-redux": "^8.1.1", "react-redux": "^8.1.1",
"redux": "^4.2.1" "redux": "^4.2.1"

View file

@ -18,6 +18,7 @@ import {
urlProvider, urlProvider,
} from "../../components/Api/Api"; } from "../../components/Api/Api";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useToast } from "react-native-toast-notifications";
export default function Home() { export default function Home() {
// Switch this condition to see the main map when debugging // Switch this condition to see the main map when debugging
@ -29,6 +30,7 @@ export default function Home() {
"To continue, please allow Stud-E permission to location services" "To continue, please allow Stud-E permission to location services"
); );
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const toast = useToast();
const ustpCoords = { const ustpCoords = {
latitude: 8.4857, latitude: 8.4857,
@ -40,9 +42,14 @@ export default function Home() {
const { status } = await Location.requestForegroundPermissionsAsync(); const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") { if (status !== "granted") {
setFeedback("Allow location permissions to continue"); setFeedback("Allow location permissions to continue");
ToastAndroid.show( toast.show(
"Location permission was denied. Please allow in order to use StudE", "Location permission was denied. Please allow in order to use StudE",
ToastAndroid.SHORT {
type: "warning",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
}
); );
return; return;
} }
@ -122,16 +129,20 @@ export default function Home() {
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["user"] }); queryClient.invalidateQueries({ queryKey: ["user"] });
queryClient.invalidateQueries({ queryKey: ["user_status"] }); queryClient.invalidateQueries({ queryKey: ["user_status"] });
ToastAndroid.show( toast.show("You are no longer studying " + subject, {
"You are no longer studying " + subject, type: "success",
ToastAndroid.SHORT placement: "bottom",
); duration: 4000,
animationType: "slide-in",
});
}, },
onError: () => { onError: () => {
ToastAndroid.show( toast.show("Server error. Unable to update student status", {
"Server error. Unable to update student status", type: "warning",
ToastAndroid.SHORT placement: "bottom",
); duration: 4000,
animationType: "slide-in",
});
}, },
}); });
function CustomCallout() { function CustomCallout() {
@ -139,7 +150,7 @@ export default function Home() {
if (studying) { if (studying) {
return ( return (
<Callout> <Callout>
<Text style={styles.text_black_medium}> <Text style={styles.text_black_tiny}>
You are here {"\n"} You are here {"\n"}
X: {Math.round(location.coords.longitude) + "\n"} X: {Math.round(location.coords.longitude) + "\n"}
Z: {Math.round(location.coords.latitude) + "\n"} Z: {Math.round(location.coords.latitude) + "\n"}

View file

@ -23,6 +23,7 @@ import {
setOnboarding, setOnboarding,
unsetOnboarding, unsetOnboarding,
} from "../../features/redux/slices/StatusSlice/StatusSlice"; } from "../../features/redux/slices/StatusSlice/StatusSlice";
import { useToast } from "react-native-toast-notifications";
export default function Login() { export default function Login() {
const navigation = useNavigation<RootDrawerParamList>(); const navigation = useNavigation<RootDrawerParamList>();
@ -31,7 +32,7 @@ export default function Login() {
username: "", username: "",
password: "", password: "",
}); });
const [error, setError] = useState(""); const toast = useToast();
return ( return (
<View style={styles.background}> <View style={styles.background}>
<AnimatedContainer> <AnimatedContainer>
@ -66,8 +67,6 @@ export default function Login() {
setCreds({ ...creds, password: e.nativeEvent.text }); setCreds({ ...creds, password: e.nativeEvent.text });
}} }}
/> />
<View style={{ paddingVertical: 2 }} />
<Text style={styles.text_white_small}>{error}</Text>
<View style={{ paddingVertical: 4 }} /> <View style={{ paddingVertical: 4 }} />
<Button <Button
onPress={async () => { onPress={async () => {
@ -88,14 +87,31 @@ export default function Login() {
) { ) {
dispatch(setOnboarding()); dispatch(setOnboarding());
navigation.navigate("Onboarding"); navigation.navigate("Onboarding");
toast.show("Successfully logged in", {
type: "success",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
} else { } else {
dispatch(unsetOnboarding()); dispatch(unsetOnboarding());
toast.show("Successfully logged in", {
type: "success",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
navigation.navigate("Home"); navigation.navigate("Home");
} }
console.log(JSON.stringify(user_info)); console.log(JSON.stringify(user_info));
} else { } else {
console.log(ParseLoginError(JSON.stringify(result[1]))); console.log(ParseLoginError(JSON.stringify(result[1])));
setError(ParseLoginError(JSON.stringify(result[1]))); toast.show(JSON.stringify(result[1]), {
type: "warning",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
} }
}); });
}} }}

View file

@ -25,11 +25,12 @@ import { unsetOnboarding } from "../../features/redux/slices/StatusSlice/StatusS
import { setUser } from "../../features/redux/slices/UserSlice/UserSlice"; import { setUser } from "../../features/redux/slices/UserSlice/UserSlice";
import AnimatedContainer from "../../components/AnimatedContainer/AnimatedContainer"; import AnimatedContainer from "../../components/AnimatedContainer/AnimatedContainer";
import AnimatedContainerNoScroll from "../../components/AnimatedContainer/AnimatedContainerNoScroll"; import AnimatedContainerNoScroll from "../../components/AnimatedContainer/AnimatedContainerNoScroll";
import { useToast } from "react-native-toast-notifications";
export default function Onboarding() { export default function Onboarding() {
const navigation = useNavigation<RootDrawerParamList>(); const navigation = useNavigation<RootDrawerParamList>();
const dispatch = useDispatch(); const dispatch = useDispatch();
// const creds = useSelector((state: RootState) => state.auth.creds); // const creds = useSelector((state: RootState) => state.auth.creds);
const [error, setError] = useState(""); const toast = useToast();
// Semesters // Semesters
const [selected_semester, setSelectedSemester] = useState(""); const [selected_semester, setSelectedSemester] = useState("");
const [semesterOpen, setSemesterOpen] = useState(false); const [semesterOpen, setSemesterOpen] = useState(false);
@ -196,7 +197,6 @@ export default function Onboarding() {
dropDownContainerStyle={{ backgroundColor: colors.primary_2 }} dropDownContainerStyle={{ backgroundColor: colors.primary_2 }}
/> />
</MotiView> </MotiView>
<Text style={styles.text_white_small}>{error}</Text>
<MotiView <MotiView
from={{ from={{
opacity: 0, opacity: 0,
@ -227,11 +227,25 @@ export default function Onboarding() {
setSelectedCourse(""); setSelectedCourse("");
setSelectedYearLevel(""); setSelectedYearLevel("");
setSelectedSemester(""); setSelectedSemester("");
setError("Success!");
dispatch(setUser(result[1])); dispatch(setUser(result[1]));
toast.show("Changes applied successfully", {
type: "success",
placement: "bottom",
duration: 6000,
animationType: "slide-in",
});
navigation.navigate("Home"); navigation.navigate("Home");
} else { } else {
setError(result[1]); dispatch(setUser(result[1]));
toast.show(
"An error has occured\nChanges have not been saved",
{
type: "warning",
placement: "bottom",
duration: 6000,
animationType: "slide-in",
}
);
} }
}} }}
> >

View file

@ -17,9 +17,11 @@ import { UserRegister } from "../../components/Api/Api";
import IsNumber from "../../components/IsNumber/IsNumber"; import IsNumber from "../../components/IsNumber/IsNumber";
import ParseError from "../../components/ParseError/ParseError"; import ParseError from "../../components/ParseError/ParseError";
import AnimatedContainer from "../../components/AnimatedContainer/AnimatedContainer"; import AnimatedContainer from "../../components/AnimatedContainer/AnimatedContainer";
import { useToast } from "react-native-toast-notifications";
export default function Register() { export default function Register() {
const navigation = useNavigation<RootDrawerParamList>(); const navigation = useNavigation<RootDrawerParamList>();
const toast = useToast();
// const dispatch = useDispatch(); // const dispatch = useDispatch();
// const creds = useSelector((state: RootState) => state.auth.creds); // const creds = useSelector((state: RootState) => state.auth.creds);
const [user, setUser] = useState({ const [user, setUser] = useState({
@ -29,7 +31,6 @@ export default function Register() {
username: "", username: "",
email: "", email: "",
password: "", password: "",
feedback: "",
}); });
return ( return (
<View style={styles.background}> <View style={styles.background}>
@ -120,8 +121,6 @@ export default function Register() {
}} }}
/> />
<View style={{ paddingVertical: 4 }} /> <View style={{ paddingVertical: 4 }} />
<Text style={styles.text_white_small}>{user.feedback}</Text>
<View style={{ paddingVertical: 4 }} />
<Button <Button
onPress={async () => { onPress={async () => {
await UserRegister({ await UserRegister({
@ -142,16 +141,25 @@ export default function Register() {
username: "", username: "",
email: "", email: "",
password: "", password: "",
feedback:
"Success! An email has been sent to activate your account",
}); });
toast.show(
"Success! An email has been sent to activate your account",
{
type: "success",
placement: "bottom",
duration: 6000,
animationType: "slide-in",
}
);
setTimeout(() => { setTimeout(() => {
navigation.navigate("Login"); navigation.navigate("Login");
}, 10000); }, 10000);
} else { } else {
setUser({ toast.show(JSON.stringify(result[1]), {
...user, type: "warning",
feedback: ParseError(JSON.stringify(result[1])), placement: "bottom",
duration: 6000,
animationType: "slide-in",
}); });
} }
}); });

View file

@ -15,11 +15,13 @@ import AnimatedContainer from "../../components/AnimatedContainer/AnimatedContai
import { setUser } from "../../features/redux/slices/UserSlice/UserSlice"; import { setUser } from "../../features/redux/slices/UserSlice/UserSlice";
import { setOnboarding } from "../../features/redux/slices/StatusSlice/StatusSlice"; import { setOnboarding } from "../../features/redux/slices/StatusSlice/StatusSlice";
import AsyncStorage from "@react-native-async-storage/async-storage"; import AsyncStorage from "@react-native-async-storage/async-storage";
import { useToast } from "react-native-toast-notifications";
export default function Revalidation() { export default function Revalidation() {
const dispatch = useDispatch(); const dispatch = useDispatch();
const navigation = useNavigation<RootDrawerParamList>(); const navigation = useNavigation<RootDrawerParamList>();
const [state, setState] = useState("Checking for existing session"); const [state, setState] = useState("Checking for existing session");
const toast = useToast();
useEffect(() => { useEffect(() => {
setState("Previous session found"); setState("Previous session found");
TokenRefresh().then(async (response) => { TokenRefresh().then(async (response) => {
@ -33,17 +35,35 @@ export default function Revalidation() {
!user_info[1].semester !user_info[1].semester
) { ) {
dispatch(setOnboarding()); dispatch(setOnboarding());
toast.show("Previous session restored", {
type: "success",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
await setTimeout(() => { await setTimeout(() => {
navigation.navigate("Onboarding"); navigation.navigate("Onboarding");
}, 700); }, 700);
} else { } else {
dispatch(unsetOnboarding()); dispatch(unsetOnboarding());
toast.show("Previous session restored", {
type: "success",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
await setTimeout(() => { await setTimeout(() => {
navigation.navigate("Home"); navigation.navigate("Home");
}, 700); }, 700);
} }
} else { } else {
await setState("Session expired"); await setState("Session expired");
toast.show("Session expired. Please login again", {
type: "warning",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
await setTimeout(() => { await setTimeout(() => {
AsyncStorage.clear(); AsyncStorage.clear();
navigation.navigate("Login"); navigation.navigate("Login");

View file

@ -16,11 +16,13 @@ import AnimatedContainerNoScroll from "../../components/AnimatedContainer/Animat
import { urlProvider } from "../../components/Api/Api"; import { urlProvider } from "../../components/Api/Api";
import MapView, { UrlTile, Marker } from "react-native-maps"; import MapView, { UrlTile, Marker } from "react-native-maps";
import { useNavigation } from "@react-navigation/native"; import { useNavigation } from "@react-navigation/native";
import { useToast } from "react-native-toast-notifications";
export default function StartStudying({ route }: any) { export default function StartStudying({ route }: any) {
const { location } = route.params; const { location } = route.params;
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const navigation = useNavigation<RootDrawerParamList>(); const navigation = useNavigation<RootDrawerParamList>();
const toast = useToast();
// Subject choices // Subject choices
const [selected_subject, setSelectedSubject] = useState(""); const [selected_subject, setSelectedSubject] = useState("");
@ -37,10 +39,12 @@ export default function StartStudying({ route }: any) {
setSubjects(subjects); setSubjects(subjects);
}, },
onError: () => { onError: () => {
ToastAndroid.show( toast.show("Server error: Unable to query available subjects", {
"Server error: Unable to query available subjects", type: "error",
ToastAndroid.SHORT placement: "bottom",
); duration: 4000,
animationType: "slide-in",
});
}, },
}); });
@ -49,17 +53,21 @@ export default function StartStudying({ route }: any) {
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["user"] }); queryClient.invalidateQueries({ queryKey: ["user"] });
queryClient.invalidateQueries({ queryKey: ["user_status"] }); queryClient.invalidateQueries({ queryKey: ["user_status"] });
ToastAndroid.show( toast.show("You are now studying " + selected_subject, {
"You are now studying " + selected_subject, type: "success",
ToastAndroid.SHORT placement: "bottom",
); duration: 4000,
animationType: "slide-in",
});
navigation.navigate("Home"); navigation.navigate("Home");
}, },
onError: () => { onError: () => {
ToastAndroid.show( toast.show("A server error has occured. Please try again", {
"A server error has occured. Please try again", type: "error",
ToastAndroid.SHORT placement: "bottom",
); duration: 4000,
animationType: "slide-in",
});
}, },
}); });

View file

@ -42,12 +42,13 @@ import { useDispatch } from "react-redux";
import { setUser as setUserinState } from "../../features/redux/slices/UserSlice/UserSlice"; import { setUser as setUserinState } from "../../features/redux/slices/UserSlice/UserSlice";
import * as ImagePicker from "expo-image-picker"; import * as ImagePicker from "expo-image-picker";
import * as FileSystem from "expo-file-system"; import * as FileSystem from "expo-file-system";
import { useToast } from "react-native-toast-notifications";
export default function UserInfoPage() { export default function UserInfoPage() {
const logged_in_user = useSelector((state: RootState) => state.user.user); const logged_in_user = useSelector((state: RootState) => state.user.user);
const dispatch = useDispatch(); const dispatch = useDispatch();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [feedback, setFeedback] = useState(""); const toast = useToast();
// Student Status // Student Status
const studentstatus_mutation = useMutation({ const studentstatus_mutation = useMutation({
@ -55,10 +56,20 @@ export default function UserInfoPage() {
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["user"] }); queryClient.invalidateQueries({ queryKey: ["user"] });
queryClient.invalidateQueries({ queryKey: ["user_status"] }); queryClient.invalidateQueries({ queryKey: ["user_status"] });
setFeedback("Changes applied successfully"); toast.show("Changes applied successfully", {
type: "success",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
}, },
onError: () => { onError: () => {
setFeedback("An error has occured\nChanges have not been saved"); toast.show("An error has occured\nChanges have not been saved", {
type: "warning",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
}, },
}); });
@ -98,7 +109,12 @@ export default function UserInfoPage() {
dispatch(setUserinState(data[1])); dispatch(setUserinState(data[1]));
}, },
onError: () => { onError: () => {
setFeedback("Unable to query user info"); toast.show("Server Error: Unable to query user info", {
type: "warning",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
}, },
}); });
@ -111,11 +127,21 @@ export default function UserInfoPage() {
studentstatus_mutation.mutate({ studentstatus_mutation.mutate({
active: false, active: false,
}); });
setFeedback("Changes applied successfully"); toast.show("Changes applied successfully", {
type: "success",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
dispatch(setUserinState(user)); dispatch(setUserinState(user));
}, },
onError: () => { onError: () => {
setFeedback("An error has occured\nChanges have not been saved"); toast.show("An error has occured\nChanges have not been saved", {
type: "warning",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
}, },
}); });
@ -136,7 +162,12 @@ export default function UserInfoPage() {
setSemesters(semestersData); setSemesters(semestersData);
}, },
onError: () => { onError: () => {
setFeedback("Unable to query semester info"); toast.show("Server Error: Unable to query semester info", {
type: "warning",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
}, },
}); });
@ -155,7 +186,12 @@ export default function UserInfoPage() {
setYearLevels(year_levels); setYearLevels(year_levels);
}, },
onError: () => { onError: () => {
setFeedback("Unable to query year level info"); toast.show("Server Error: Unable to query year level info", {
type: "warning",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
}, },
}); });
@ -174,7 +210,12 @@ export default function UserInfoPage() {
setCourses(courses); setCourses(courses);
}, },
onError: () => { onError: () => {
setFeedback("Unable to query course info"); toast.show("Server Error: Unable to query course info", {
type: "warning",
placement: "bottom",
duration: 4000,
animationType: "slide-in",
});
}, },
}); });
@ -242,7 +283,6 @@ export default function UserInfoPage() {
e: NativeSyntheticEvent<TextInputChangeEventData> e: NativeSyntheticEvent<TextInputChangeEventData>
): void => { ): void => {
setUser({ ...user, first_name: e.nativeEvent.text }); setUser({ ...user, first_name: e.nativeEvent.text });
setFeedback("");
}} }}
value={user.first_name} value={user.first_name}
/> />
@ -259,7 +299,6 @@ export default function UserInfoPage() {
e: NativeSyntheticEvent<TextInputChangeEventData> e: NativeSyntheticEvent<TextInputChangeEventData>
): void => { ): void => {
setUser({ ...user, last_name: e.nativeEvent.text }); setUser({ ...user, last_name: e.nativeEvent.text });
setFeedback("");
}} }}
value={user.last_name} value={user.last_name}
/> />
@ -281,9 +320,6 @@ export default function UserInfoPage() {
setCourseOpen(false); setCourseOpen(false);
}} }}
setValue={setSelectedYearLevel} setValue={setSelectedYearLevel}
onChangeValue={() => {
setFeedback("");
}}
placeholder={user.year_level} placeholder={user.year_level}
placeholderStyle={{ placeholderStyle={{
...styles.text_white_tiny_bold, ...styles.text_white_tiny_bold,
@ -319,9 +355,6 @@ export default function UserInfoPage() {
setCourseOpen(false); setCourseOpen(false);
}} }}
setValue={setSelectedSemester} setValue={setSelectedSemester}
onChangeValue={() => {
setFeedback("");
}}
placeholder={user.semester} placeholder={user.semester}
placeholderStyle={{ placeholderStyle={{
...styles.text_white_tiny_bold, ...styles.text_white_tiny_bold,
@ -357,9 +390,6 @@ export default function UserInfoPage() {
setCourseOpen(open); setCourseOpen(open);
}} }}
setValue={setSelectedCourse} setValue={setSelectedCourse}
onChangeValue={() => {
setFeedback("");
}}
placeholder={user.course} placeholder={user.course}
placeholderStyle={{ placeholderStyle={{
...styles.text_white_tiny_bold, ...styles.text_white_tiny_bold,
@ -412,7 +442,6 @@ export default function UserInfoPage() {
<Text style={styles.text_white_small}>Save Changes</Text> <Text style={styles.text_white_small}>Save Changes</Text>
</Button> </Button>
<View style={styles.padding} /> <View style={styles.padding} />
<Text style={styles.text_white_small}>{feedback}</Text>
</View> </View>
</AnimatedContainerNoScroll> </AnimatedContainerNoScroll>
</View> </View>