mirror of
https://github.com/lemeow125/StudE-Frontend.git
synced 2024-11-17 06:19:25 +08:00
Merge branch 'master' into initial-frontend
This commit is contained in:
commit
22d4aa4a29
21 changed files with 762 additions and 166 deletions
33
App.tsx
33
App.tsx
|
@ -18,6 +18,7 @@ import Revalidation from "./src/routes/Revalidation/Revalidation";
|
|||
import Activation from "./src/routes/Activation/Activation";
|
||||
import UserInfo from "./src/routes/UserInfo/UserInfo";
|
||||
import { useState, useEffect } from "react";
|
||||
import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
|
||||
|
||||
const Drawer = createDrawerNavigator();
|
||||
|
||||
|
@ -36,6 +37,8 @@ const linking = {
|
|||
},
|
||||
};
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
export default function App() {
|
||||
const [initialRoute, setInitialRoute] = useState<string | null>(null);
|
||||
useEffect(() => {
|
||||
|
@ -51,21 +54,23 @@ export default function App() {
|
|||
}, [initialRoute]);
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<NavigationContainer linking={linking}>
|
||||
<Drawer.Navigator
|
||||
initialRouteName="Revalidation"
|
||||
drawerContent={CustomDrawerContent}
|
||||
screenOptions={DrawerScreenSettings}
|
||||
>
|
||||
<Drawer.Screen name="Home" component={Home} />
|
||||
<Drawer.Screen name="Login" component={Login} />
|
||||
<Drawer.Screen name="Register" component={Register} />
|
||||
<Drawer.Screen name="Onboarding" component={Onboarding} />
|
||||
<Drawer.Screen name="Revalidation" component={Revalidation} />
|
||||
<Drawer.Screen name="Activation" component={Activation} />
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<NavigationContainer linking={linking}>
|
||||
<Drawer.Navigator
|
||||
initialRouteName="Revalidation"
|
||||
drawerContent={CustomDrawerContent}
|
||||
screenOptions={DrawerScreenSettings}
|
||||
>
|
||||
<Drawer.Screen name="Home" component={Home} />
|
||||
<Drawer.Screen name="Login" component={Login} />
|
||||
<Drawer.Screen name="Register" component={Register} />
|
||||
<Drawer.Screen name="Onboarding" component={Onboarding} />
|
||||
<Drawer.Screen name="Revalidation" component={Revalidation} />
|
||||
<Drawer.Screen name="Activation" component={Activation} />
|
||||
<Drawer.Screen name="UserInfo" component={UserInfo} />
|
||||
</Drawer.Navigator>
|
||||
</NavigationContainer>
|
||||
</Drawer.Navigator>
|
||||
</NavigationContainer>
|
||||
</QueryClientProvider>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
|
|
10
app.json
10
app.json
|
@ -26,6 +26,14 @@
|
|||
},
|
||||
"web": {
|
||||
"favicon": "./assets/favicon.png"
|
||||
}
|
||||
},
|
||||
"plugins": [
|
||||
[
|
||||
"expo-location",
|
||||
{
|
||||
"locationAlwaysAndWhenInUsePermission": "Allow Stud-E to use your location."
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
76
package-lock.json
generated
76
package-lock.json
generated
|
@ -13,9 +13,12 @@
|
|||
"@react-navigation/native": "^6.1.7",
|
||||
"@react-navigation/native-stack": "^6.9.13",
|
||||
"@reduxjs/toolkit": "^1.9.5",
|
||||
"@tanstack/react-query": "^4.29.19",
|
||||
"axios": "^1.4.0",
|
||||
"expo": "~48.0.18",
|
||||
"expo-intent-launcher": "~10.5.2",
|
||||
"expo-linking": "~4.0.1",
|
||||
"expo-location": "~15.1.1",
|
||||
"expo-status-bar": "~1.4.4",
|
||||
"moti": "^0.25.3",
|
||||
"react": "18.2.0",
|
||||
|
@ -24,6 +27,7 @@
|
|||
"react-native-gesture-handler": "~2.9.0",
|
||||
"react-native-image-picker": "^5.6.0",
|
||||
"react-native-modal": "^13.0.1",
|
||||
"react-native-maps": "1.3.2",
|
||||
"react-native-reanimated": "~2.14.4",
|
||||
"react-native-safe-area-context": "4.5.0",
|
||||
"react-native-screens": "~3.20.0",
|
||||
|
@ -5206,6 +5210,46 @@
|
|||
"@sinonjs/commons": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/query-core": {
|
||||
"version": "4.29.19",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.29.19.tgz",
|
||||
"integrity": "sha512-uPe1DukeIpIHpQi6UzIgBcXsjjsDaLnc7hF+zLBKnaUlh7jFE/A+P8t4cU4VzKPMFB/C970n/9SxtpO5hmIRgw==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-query": {
|
||||
"version": "4.29.19",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.29.19.tgz",
|
||||
"integrity": "sha512-XiTIOHHQ5Cw1WUlHaD4fmVUMhoWjuNJlAeJGq7eM4BraI5z7y8WkZO+NR8PSuRnQGblpuVdjClQbDFtwxTtTUw==",
|
||||
"dependencies": {
|
||||
"@tanstack/query-core": "4.29.19",
|
||||
"use-sync-external-store": "^1.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-native": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
},
|
||||
"react-native": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@types/geojson": {
|
||||
"version": "7946.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
|
||||
"integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA=="
|
||||
},
|
||||
"node_modules/@types/hammerjs": {
|
||||
"version": "2.0.41",
|
||||
"resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.41.tgz",
|
||||
|
@ -7413,6 +7457,14 @@
|
|||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-intent-launcher": {
|
||||
"version": "10.5.2",
|
||||
"resolved": "https://registry.npmjs.org/expo-intent-launcher/-/expo-intent-launcher-10.5.2.tgz",
|
||||
"integrity": "sha512-qFIanCkLlTvqYTtJQJocZuZesi6b8lAdY9xF3oLFsdaTXKIMrfQfWI67zwBJvaNqgiV9MbbYnBHsFoOAzhBTKA==",
|
||||
"peerDependencies": {
|
||||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-keep-awake": {
|
||||
"version": "12.0.1",
|
||||
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-12.0.1.tgz",
|
||||
|
@ -7433,6 +7485,14 @@
|
|||
"url-parse": "^1.5.9"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-location": {
|
||||
"version": "15.1.1",
|
||||
"resolved": "https://registry.npmjs.org/expo-location/-/expo-location-15.1.1.tgz",
|
||||
"integrity": "sha512-hoKRlmi6Ya+NeZ72Zt385SDcSsIDpJI60TCBVO+Hc9xfKA9Hyminyyo5WiwI8J03igmPTCl8Y37MxBNKY9AWkg==",
|
||||
"peerDependencies": {
|
||||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-modules-autolinking": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-1.2.0.tgz",
|
||||
|
@ -12289,6 +12349,22 @@
|
|||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": ">=0.65.0"
|
||||
"node_modules/react-native-maps": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-maps/-/react-native-maps-1.3.2.tgz",
|
||||
"integrity": "sha512-NB7HGRZOgxxXCWzrhIVucx/bsrEWANvk3DLci1ov4P9MQnEVQYQCCkTxsnaEvO191GeBOCRDyYn6jckqbfMtmg==",
|
||||
"dependencies": {
|
||||
"@types/geojson": "^7946.0.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">= 17.0.1",
|
||||
"react-native": ">= 0.64.3",
|
||||
"react-native-web": ">= 0.11"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-native-web": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-reanimated": {
|
||||
|
|
|
@ -14,9 +14,12 @@
|
|||
"@react-navigation/native": "^6.1.7",
|
||||
"@react-navigation/native-stack": "^6.9.13",
|
||||
"@reduxjs/toolkit": "^1.9.5",
|
||||
"@tanstack/react-query": "^4.29.19",
|
||||
"axios": "^1.4.0",
|
||||
"expo": "~48.0.18",
|
||||
"expo-linking": "~4.0.1",
|
||||
"expo-intent-launcher": "~10.5.2",
|
||||
"expo-location": "~15.1.1",
|
||||
"expo-status-bar": "~1.4.4",
|
||||
"moti": "^0.25.3",
|
||||
"react": "18.2.0",
|
||||
|
@ -32,7 +35,8 @@
|
|||
"react-native-svg": "13.4.0",
|
||||
"react-query": "^3.39.3",
|
||||
"react-redux": "^8.1.1",
|
||||
"redux": "^4.2.1"
|
||||
"redux": "^4.2.1",
|
||||
"react-native-maps": "1.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
|
|
|
@ -1,21 +1,35 @@
|
|||
import * as React from "react";
|
||||
import { View, Text } from "react-native";
|
||||
import { View, Text, ScrollView } from "react-native";
|
||||
import styles from "../../styles";
|
||||
import { colors } from "../../styles";
|
||||
import { MotiView } from "moti";
|
||||
import { MotiView, MotiScrollView } from "moti";
|
||||
export interface props {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function AnimatedContainer(props: props) {
|
||||
return (
|
||||
<MotiView
|
||||
style={styles.container}
|
||||
from={{ opacity: 0, backgroundColor: colors.orange_1 }}
|
||||
animate={{ opacity: 1, backgroundColor: colors.blue_2 }}
|
||||
<MotiScrollView
|
||||
contentContainerStyle={styles.container}
|
||||
from={{
|
||||
borderRadius: 0,
|
||||
backgroundColor: colors.orange_2,
|
||||
paddingTop: 4,
|
||||
paddingBottom: 4,
|
||||
marginHorizontal: "4%",
|
||||
marginVertical: "5%",
|
||||
}}
|
||||
animate={{
|
||||
borderRadius: 15,
|
||||
backgroundColor: colors.blue_2,
|
||||
paddingTop: 16,
|
||||
paddingBottom: 16,
|
||||
marginHorizontal: "4%",
|
||||
marginVertical: "5%",
|
||||
}}
|
||||
transition={{ type: "timing", duration: 300 }}
|
||||
>
|
||||
{props.children}
|
||||
</MotiView>
|
||||
</MotiScrollView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import AsyncStorage from "@react-native-async-storage/async-storage";
|
|||
import {
|
||||
ActivationParams,
|
||||
LoginParams,
|
||||
OnboardingParams,
|
||||
RegistrationParams,
|
||||
} from "../../interfaces/Interfaces";
|
||||
|
||||
|
@ -51,7 +52,10 @@ export function UserRegister(register: RegistrationParams) {
|
|||
return [true, response.status];
|
||||
})
|
||||
.catch((error) => {
|
||||
return [false, error.response.status, error.response.data];
|
||||
let error_message = "";
|
||||
if (error.response) error_message = error.response.data;
|
||||
else error_message = "Unable to reach servers";
|
||||
return [false, error_message];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -70,8 +74,10 @@ export function UserLogin(user: LoginParams) {
|
|||
return [true];
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("Login Failed:" + JSON.stringify(error.response.data));
|
||||
return [false, error.response.data];
|
||||
let error_message = "";
|
||||
if (error.response) error_message = error.response.data;
|
||||
else error_message = "Unable to reach servers";
|
||||
return [false, error_message];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -88,11 +94,14 @@ export async function TokenRefresh() {
|
|||
"Token refresh success! New Access Token",
|
||||
response.data.access
|
||||
);*/
|
||||
return [true];
|
||||
return true;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("Refresh Failed: " + JSON.stringify(error.response.data));
|
||||
return [false, error.response.data];
|
||||
let error_message = "";
|
||||
if (error.response) error_message = error.response.data;
|
||||
else error_message = "Unable to reach servers";
|
||||
console.log("Token Refresh error:", error_message);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
export async function UserInfo() {
|
||||
|
@ -105,11 +114,13 @@ export async function UserInfo() {
|
|||
})
|
||||
.then((response) => {
|
||||
// console.log(JSON.stringify(response.data));
|
||||
return response.data;
|
||||
return [true, response.data];
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("User Info Error", error.response.data);
|
||||
return [false, error.response.data];
|
||||
let error_message = "";
|
||||
if (error.response) error_message = error.response.data;
|
||||
else error_message = "Unable to reach servers";
|
||||
return [false, error_message];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -125,3 +136,86 @@ export function UserActivate(activation: ActivationParams) {
|
|||
}
|
||||
|
||||
// App APIs
|
||||
|
||||
export async function GetCourses() {
|
||||
const accessToken = await getAccessToken();
|
||||
return instance
|
||||
.get("/api/v1/courses/", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
// console.log(JSON.stringify(response.data));
|
||||
return response.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
let error_message = "";
|
||||
if (error.response) error_message = error.response.data;
|
||||
else error_message = "Unable to reach servers";
|
||||
console.log("Error getting courses", error_message);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetSemesters() {
|
||||
const accessToken = await getAccessToken();
|
||||
return instance
|
||||
.get("/api/v1/semesters/", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
// console.log(JSON.stringify(response.data));
|
||||
return response.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
let error_message = "";
|
||||
if (error.response) error_message = error.response.data;
|
||||
else error_message = "Unable to reach servers";
|
||||
console.log("Error getting semesters", error_message);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetYearLevels() {
|
||||
const accessToken = await getAccessToken();
|
||||
return instance
|
||||
.get("/api/v1/year_levels/", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
// console.log(JSON.stringify(response.data));
|
||||
return response.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
let error_message = "";
|
||||
if (error.response) error_message = error.response.data;
|
||||
else error_message = "Unable to reach servers";
|
||||
console.log("Error getting year levels", error_message);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
export async function OnboardingUpdateStudentInfo(info: OnboardingParams) {
|
||||
const accessToken = await getAccessToken();
|
||||
const headers = {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
};
|
||||
return instance
|
||||
.patch("/api/v1/accounts/users/me/", info, { headers })
|
||||
.then((response) => {
|
||||
console.log(JSON.stringify(response.data));
|
||||
return [true, response.data];
|
||||
})
|
||||
.catch((error) => {
|
||||
let error_message = "";
|
||||
if (error.response) error_message = error.response.data;
|
||||
else error_message = "Unable to reach servers";
|
||||
console.log("Error updating onboarding info", error_message);
|
||||
return [false, error_message];
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,15 +6,24 @@ export interface props {
|
|||
children: React.ReactNode;
|
||||
onPress: (event: GestureResponderEvent) => void;
|
||||
color: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export default function Button(props: props) {
|
||||
export default function Button({ disabled = false, ...props }: props) {
|
||||
const rgb = props.color.match(/\d+/g);
|
||||
return (
|
||||
<Pressable
|
||||
disabled={disabled}
|
||||
onPress={props.onPress}
|
||||
style={{
|
||||
...styles.button_template,
|
||||
...{ backgroundColor: props.color, width: "50%" },
|
||||
...{
|
||||
backgroundColor: disabled
|
||||
? rgb
|
||||
? `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, 0.3)`
|
||||
: "rgba(0, 0, 0, 0)"
|
||||
: props.color,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
|
|
|
@ -14,17 +14,41 @@ import DrawerButton from "../Button/DrawerButton";
|
|||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { RootState } from "../../features/redux/Store/Store";
|
||||
import LogoutIcon from "../../icons/LogoutIcon/LogoutIcon";
|
||||
import { clear } from "../../features/redux/slices/AuthSlice/AuthSlice";
|
||||
import { logout } from "../../features/redux/slices/StatusSlice/StatusSlice";
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
import UserIcon from "../../icons/UserIcon/UserIcon";
|
||||
|
||||
export default function CustomDrawerContent(props: {}) {
|
||||
const navigation = useNavigation<RootDrawerParamList>();
|
||||
const logged_in = useSelector(
|
||||
(state: RootState) => state.auth.creds.logged_in
|
||||
);
|
||||
const status = useSelector((state: RootState) => state.status);
|
||||
const dispatch = useDispatch();
|
||||
if (logged_in) {
|
||||
if (status.logged_in && status.onboarding) {
|
||||
return (
|
||||
<DrawerContentScrollView {...props}>
|
||||
<View
|
||||
style={{
|
||||
...styles.flex_row,
|
||||
...{ justifyContent: "center" },
|
||||
}}
|
||||
>
|
||||
<AppIcon size={32} />
|
||||
<Text style={styles.text_white_medium}>Stud-E</Text>
|
||||
</View>
|
||||
|
||||
<DrawerButton
|
||||
color={colors.blue_2}
|
||||
onPress={async () => {
|
||||
dispatch(logout());
|
||||
await AsyncStorage.clear();
|
||||
navigation.navigate("Login");
|
||||
}}
|
||||
>
|
||||
<LogoutIcon size={32} />
|
||||
<Text style={styles.text_white_medium}>Logout</Text>
|
||||
</DrawerButton>
|
||||
</DrawerContentScrollView>
|
||||
);
|
||||
} else if (status.logged_in) {
|
||||
return (
|
||||
<DrawerContentScrollView {...props}>
|
||||
<View
|
||||
|
@ -57,7 +81,7 @@ export default function CustomDrawerContent(props: {}) {
|
|||
<DrawerButton
|
||||
color={colors.blue_2}
|
||||
onPress={async () => {
|
||||
dispatch(await clear());
|
||||
dispatch(logout());
|
||||
await AsyncStorage.clear();
|
||||
navigation.navigate("Login");
|
||||
}}
|
||||
|
@ -79,15 +103,6 @@ export default function CustomDrawerContent(props: {}) {
|
|||
<AppIcon size={32} />
|
||||
<Text style={styles.text_white_medium}>Stud-E</Text>
|
||||
</View>
|
||||
<DrawerButton
|
||||
color={colors.blue_2}
|
||||
onPress={() => {
|
||||
navigation.navigate("Home");
|
||||
}}
|
||||
>
|
||||
<HomeIcon size={32} />
|
||||
<Text style={styles.text_white_medium}>Home</Text>
|
||||
</DrawerButton>
|
||||
<DrawerButton
|
||||
color={colors.blue_2}
|
||||
onPress={() => {
|
||||
|
@ -100,7 +115,6 @@ export default function CustomDrawerContent(props: {}) {
|
|||
<DrawerButton
|
||||
color={colors.blue_2}
|
||||
onPress={() => {
|
||||
dispatch(clear());
|
||||
navigation.navigate("Register");
|
||||
}}
|
||||
>
|
||||
|
|
23
src/components/GetDistance/GetDistance.tsx
Normal file
23
src/components/GetDistance/GetDistance.tsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
export default function GetDistance(
|
||||
lat1: number,
|
||||
lon1: number,
|
||||
lat2: number,
|
||||
lon2: number
|
||||
) {
|
||||
var R = 6371; // km
|
||||
var dLat = toRad(lat2 - lat1);
|
||||
var dLon = toRad(lon2 - lon1);
|
||||
var lat1 = toRad(lat1);
|
||||
var lat2 = toRad(lat2);
|
||||
|
||||
var a =
|
||||
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
|
||||
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
var distance = R * c;
|
||||
return distance;
|
||||
}
|
||||
|
||||
export function toRad(value: number) {
|
||||
return (value * Math.PI) / 180;
|
||||
}
|
3
src/components/IsStringEmpty/IsStringEmpty.tsx
Normal file
3
src/components/IsStringEmpty/IsStringEmpty.tsx
Normal file
|
@ -0,0 +1,3 @@
|
|||
export default function isStringEmpty(str: string) {
|
||||
return str === "" || str === null || str === undefined;
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
import { configureStore } from "@reduxjs/toolkit";
|
||||
import AuthReducer from "../slices/AuthSlice/AuthSlice";
|
||||
import StatusReducer from "../slices/StatusSlice/StatusSlice";
|
||||
import UserReducer from "../slices/UserSlice/UserSlice";
|
||||
|
||||
const store = configureStore({
|
||||
reducer: {
|
||||
auth: AuthReducer,
|
||||
status: StatusReducer,
|
||||
user: UserReducer,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
export const AuthSlice = createSlice({
|
||||
name: "Auth",
|
||||
initialState: {
|
||||
creds: {
|
||||
email: "",
|
||||
uid: "",
|
||||
username: "",
|
||||
full_name: "",
|
||||
logged_in: false,
|
||||
},
|
||||
},
|
||||
reducers: {
|
||||
login: (state) => {
|
||||
state.creds.logged_in = true;
|
||||
},
|
||||
setUser: (state, action) => {
|
||||
state.creds = {
|
||||
email: action.payload.email,
|
||||
uid: action.payload.uid,
|
||||
username: action.payload.username,
|
||||
full_name: action.payload.full_name,
|
||||
logged_in: true,
|
||||
};
|
||||
},
|
||||
clear: (state) => {
|
||||
state.creds = {
|
||||
email: "",
|
||||
uid: "",
|
||||
username: "",
|
||||
full_name: "",
|
||||
logged_in: false,
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Action creators are generated for each case reducer function
|
||||
export const { login, setUser, clear } = AuthSlice.actions;
|
||||
|
||||
export default AuthSlice.reducer;
|
29
src/features/redux/slices/StatusSlice/StatusSlice.tsx
Normal file
29
src/features/redux/slices/StatusSlice/StatusSlice.tsx
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
export const StatusSlice = createSlice({
|
||||
name: "Status",
|
||||
initialState: {
|
||||
logged_in: false,
|
||||
onboarding: false,
|
||||
},
|
||||
reducers: {
|
||||
login: (state) => {
|
||||
state.logged_in = true;
|
||||
},
|
||||
logout: (state) => {
|
||||
state.logged_in = false;
|
||||
},
|
||||
setOnboarding: (state) => {
|
||||
state.onboarding = true;
|
||||
},
|
||||
unsetOnboarding: (state) => {
|
||||
state.onboarding = false;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Action creators are generated for each case reducer function
|
||||
export const { login, logout, setOnboarding, unsetOnboarding } =
|
||||
StatusSlice.actions;
|
||||
|
||||
export default StatusSlice.reducer;
|
51
src/features/redux/slices/UserSlice/UserSlice.tsx
Normal file
51
src/features/redux/slices/UserSlice/UserSlice.tsx
Normal file
|
@ -0,0 +1,51 @@
|
|||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
export const UserSlice = createSlice({
|
||||
name: "User",
|
||||
initialState: {
|
||||
user: {
|
||||
email: "",
|
||||
uid: "",
|
||||
username: "",
|
||||
first_name: "",
|
||||
last_name: "",
|
||||
full_name: "",
|
||||
year_level: "",
|
||||
semester: " ",
|
||||
course: "",
|
||||
},
|
||||
},
|
||||
reducers: {
|
||||
setUser: (state, action) => {
|
||||
state.user = {
|
||||
email: action.payload.email,
|
||||
uid: action.payload.uid,
|
||||
username: action.payload.username,
|
||||
first_name: action.payload.first_name,
|
||||
last_name: action.payload.last_name,
|
||||
full_name: action.payload.first_name + " " + action.payload.last_name,
|
||||
year_level: action.payload.year_level,
|
||||
semester: action.payload.semester,
|
||||
course: action.payload.course,
|
||||
};
|
||||
},
|
||||
clear: (state) => {
|
||||
state.user = {
|
||||
email: "",
|
||||
uid: "",
|
||||
username: "",
|
||||
first_name: "",
|
||||
last_name: "",
|
||||
full_name: "",
|
||||
year_level: "",
|
||||
semester: " ",
|
||||
course: "",
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Action creators are generated for each case reducer function
|
||||
export const { setUser, clear } = UserSlice.actions;
|
||||
|
||||
export default UserSlice.reducer;
|
|
@ -46,3 +46,27 @@ export interface ActivationParams {
|
|||
uid: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
export interface SemesterParams {
|
||||
id: string;
|
||||
name: string;
|
||||
shortname: string;
|
||||
}
|
||||
|
||||
export interface YearLevelParams {
|
||||
id: string;
|
||||
name: string;
|
||||
shortname: string;
|
||||
}
|
||||
|
||||
export interface CourseParams {
|
||||
id: string;
|
||||
name: string;
|
||||
shortname: string;
|
||||
}
|
||||
|
||||
export interface OnboardingParams {
|
||||
year_level: string;
|
||||
course: string;
|
||||
semester: string;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,112 @@
|
|||
import * as React from "react";
|
||||
import styles from "../../styles";
|
||||
import { View, Text } from "react-native";
|
||||
import { useSelector } from "react-redux";
|
||||
import { RootState } from "../../features/redux/Store/Store";
|
||||
import AnimatedContainer from "../../components/AnimatedContainer/AnimatedContainer";
|
||||
import { useState, useEffect } from "react";
|
||||
import MapView, { Marker, UrlTile } from "react-native-maps";
|
||||
import * as Location from "expo-location";
|
||||
import GetDistance from "../../components/GetDistance/GetDistance";
|
||||
import Button from "../../components/Button/Button";
|
||||
import { colors } from "../../styles";
|
||||
import { startActivityAsync, ActivityAction } from "expo-intent-launcher";
|
||||
|
||||
type LocationType = Location.LocationObject;
|
||||
export default function Home() {
|
||||
const creds = useSelector((state: RootState) => state.auth.creds);
|
||||
const [location, setLocation] = useState<LocationType | null>(null);
|
||||
const [dist, setDist] = useState<number | null>(null);
|
||||
const [feedback, setFeedback] = useState(
|
||||
"To continue, please allow Stud-E permission to location services"
|
||||
);
|
||||
|
||||
async function requestLocation() {
|
||||
let { status } = await Location.requestForegroundPermissionsAsync();
|
||||
if (status === "granted") {
|
||||
getLocation();
|
||||
return;
|
||||
} else if (status === "denied") {
|
||||
setFeedback("Stud-E requires location services to function");
|
||||
setTimeout(() => {
|
||||
startActivityAsync(ActivityAction.LOCATION_SOURCE_SETTINGS);
|
||||
}, 3000);
|
||||
console.log("Location Permission denied");
|
||||
}
|
||||
}
|
||||
|
||||
async function getLocation() {
|
||||
let location = await Location.getCurrentPositionAsync({});
|
||||
setLocation(location);
|
||||
let dist = GetDistance(
|
||||
location.coords.latitude,
|
||||
location.coords.longitude,
|
||||
8.4857,
|
||||
124.6565
|
||||
);
|
||||
setDist(Math.round(dist));
|
||||
}
|
||||
useEffect(() => {
|
||||
requestLocation();
|
||||
}, []);
|
||||
|
||||
const ustpCoords = {
|
||||
latitude: 8.4857,
|
||||
longitude: 124.6565,
|
||||
latitudeDelta: 0.000235,
|
||||
longitudeDelta: 0.000067,
|
||||
};
|
||||
function CustomMap() {
|
||||
if (dist !== null && location !== null) {
|
||||
if (dist <= 1.5) {
|
||||
// Just switch this condition for map debugging
|
||||
return <MapView style={styles.map} initialRegion={ustpCoords} />;
|
||||
} else {
|
||||
return (
|
||||
<View>
|
||||
<Text style={styles.text_white_medium}>
|
||||
You are too far from USTP {"\n"}
|
||||
Get closer to use Stud-E
|
||||
</Text>
|
||||
<MapView
|
||||
style={{
|
||||
height: 256,
|
||||
width: 256,
|
||||
alignSelf: "center",
|
||||
}}
|
||||
showsUserLocation={true}
|
||||
scrollEnabled={false}
|
||||
zoomEnabled={false}
|
||||
rotateEnabled={false}
|
||||
followsUserLocation={true}
|
||||
minZoomLevel={15}
|
||||
initialRegion={{
|
||||
latitude: location.coords.latitude,
|
||||
longitude: location.coords.longitude,
|
||||
latitudeDelta: 0.0922,
|
||||
longitudeDelta: 0.0421,
|
||||
}}
|
||||
/>
|
||||
<Text style={styles.text_white_small}>
|
||||
{dist}km away from USTP {"\n"}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<AnimatedContainer>
|
||||
<Text style={styles.text_white_medium}>{feedback}</Text>
|
||||
<Button onPress={() => requestLocation()} color={colors.blue_3}>
|
||||
<Text style={styles.text_white_small}>Allow Access</Text>
|
||||
</Button>
|
||||
</AnimatedContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
const creds = useSelector((state: RootState) => state.user.user);
|
||||
return (
|
||||
<View style={styles.background}>
|
||||
<AnimatedContainer>
|
||||
<Text style={styles.text_white_large}>Template Homepage</Text>
|
||||
<Text style={styles.text_white_tiny}>{JSON.stringify(creds)}</Text>
|
||||
<CustomMap />
|
||||
</AnimatedContainer>
|
||||
</View>
|
||||
);
|
||||
|
|
|
@ -17,12 +17,17 @@ import { RootDrawerParamList } from "../../interfaces/Interfaces";
|
|||
import { UserInfo, UserLogin } from "../../components/Api/Api";
|
||||
import { ParseLoginError } from "../../components/ParseError/ParseError";
|
||||
import AnimatedContainer from "../../components/AnimatedContainer/AnimatedContainer";
|
||||
import { setUser as setStateUser } from "../../features/redux/slices/AuthSlice/AuthSlice";
|
||||
import { setUser } from "../../features/redux/slices/UserSlice/UserSlice";
|
||||
import {
|
||||
login,
|
||||
setOnboarding,
|
||||
unsetOnboarding,
|
||||
} from "../../features/redux/slices/StatusSlice/StatusSlice";
|
||||
|
||||
export default function Login() {
|
||||
const navigation = useNavigation<RootDrawerParamList>();
|
||||
const dispatch = useDispatch();
|
||||
const [user, setUser] = useState({
|
||||
const [creds, setCreds] = useState({
|
||||
username: "",
|
||||
password: "",
|
||||
error: "",
|
||||
|
@ -49,11 +54,11 @@ export default function Login() {
|
|||
placeholder="Username"
|
||||
placeholderTextColor="white"
|
||||
autoCapitalize="none"
|
||||
value={user.username}
|
||||
value={creds.username}
|
||||
onChange={(
|
||||
e: NativeSyntheticEvent<TextInputChangeEventData>
|
||||
): void => {
|
||||
setUser({ ...user, username: e.nativeEvent.text });
|
||||
setCreds({ ...creds, username: e.nativeEvent.text });
|
||||
}}
|
||||
/>
|
||||
<View style={{ paddingVertical: 4 }} />
|
||||
|
@ -62,42 +67,43 @@ export default function Login() {
|
|||
placeholder="Password"
|
||||
placeholderTextColor="white"
|
||||
secureTextEntry={true}
|
||||
value={user.password}
|
||||
value={creds.password}
|
||||
onChange={(
|
||||
e: NativeSyntheticEvent<TextInputChangeEventData>
|
||||
): void => {
|
||||
setUser({ ...user, password: e.nativeEvent.text });
|
||||
setCreds({ ...creds, password: e.nativeEvent.text });
|
||||
}}
|
||||
/>
|
||||
<View style={{ paddingVertical: 2 }} />
|
||||
<Text style={styles.text_white_small}>{user.error}</Text>
|
||||
<Text style={styles.text_white_small}>{creds.error}</Text>
|
||||
<View style={{ paddingVertical: 4 }} />
|
||||
<Button
|
||||
onPress={async () => {
|
||||
await UserLogin({
|
||||
username: user.username,
|
||||
password: user.password,
|
||||
username: creds.username,
|
||||
password: creds.password,
|
||||
}).then(async (result) => {
|
||||
if (result[0]) {
|
||||
setUser({ ...user, username: "", password: "", error: "" });
|
||||
setUser({ ...creds, username: "", password: "", error: "" });
|
||||
let user_info = await UserInfo();
|
||||
dispatch(setStateUser(user_info));
|
||||
dispatch(login());
|
||||
dispatch(setUser(user_info[1]));
|
||||
// Redirect to onboarding if no year level, course, or semester specified
|
||||
if (
|
||||
!(
|
||||
user_info.year_level ||
|
||||
user_info.course ||
|
||||
user_info.semester
|
||||
)
|
||||
user_info[1].year_level == null ||
|
||||
user_info[1].course == null ||
|
||||
user_info[1].semester == null
|
||||
) {
|
||||
dispatch(setOnboarding());
|
||||
navigation.navigate("Onboarding");
|
||||
} else {
|
||||
dispatch(unsetOnboarding());
|
||||
navigation.navigate("Home");
|
||||
}
|
||||
console.log(JSON.stringify(user_info));
|
||||
} else {
|
||||
setUser({
|
||||
...user,
|
||||
...creds,
|
||||
error: ParseLoginError(JSON.stringify(result[1])),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,46 +2,99 @@ import * as React from "react";
|
|||
import styles from "../../styles";
|
||||
import { View, Text } from "react-native";
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
import { RootDrawerParamList } from "../../interfaces/Interfaces";
|
||||
import {
|
||||
CourseParams,
|
||||
RootDrawerParamList,
|
||||
SemesterParams,
|
||||
YearLevelParams,
|
||||
} from "../../interfaces/Interfaces";
|
||||
import { colors } from "../../styles";
|
||||
import { AnimatePresence, MotiView } from "moti";
|
||||
import { useEffect, useState } from "react";
|
||||
import Button from "../../components/Button/Button";
|
||||
import DropDownPicker from "react-native-dropdown-picker";
|
||||
import isStringEmpty from "../../components/IsStringEmpty/IsStringEmpty";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
GetCourses,
|
||||
GetSemesters,
|
||||
GetYearLevels,
|
||||
OnboardingUpdateStudentInfo,
|
||||
} from "../../components/Api/Api";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { unsetOnboarding } from "../../features/redux/slices/StatusSlice/StatusSlice";
|
||||
import { setUser } from "../../features/redux/slices/UserSlice/UserSlice";
|
||||
export default function Onboarding() {
|
||||
const navigation = useNavigation<RootDrawerParamList>();
|
||||
// const dispatch = useDispatch();
|
||||
const dispatch = useDispatch();
|
||||
// const creds = useSelector((state: RootState) => state.auth.creds);
|
||||
const [student_info, setStudentInfo] = useState({
|
||||
year_level: "",
|
||||
course: "",
|
||||
semester: "",
|
||||
const [error, setError] = useState("");
|
||||
// Semesters
|
||||
const [selected_semester, setSelectedSemester] = useState("");
|
||||
const [semesterOpen, setSemesterOpen] = useState(false);
|
||||
const [semesters, setSemesters] = useState([
|
||||
{ label: "1st Semester", value: "1st Sem" },
|
||||
{ label: "2nd Semester", value: "2nd Sem" },
|
||||
]);
|
||||
const semester_query = useQuery({
|
||||
queryKey: ["semesters"],
|
||||
queryFn: GetSemesters,
|
||||
onSuccess: (data) => {
|
||||
let semesters = data.map((item: SemesterParams) => ({
|
||||
label: item.name,
|
||||
value: item.name,
|
||||
}));
|
||||
setSemesters(semesters);
|
||||
},
|
||||
});
|
||||
function Introduction() {
|
||||
const [shown, setShown] = useState(true);
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
setShown(false);
|
||||
}, 5000);
|
||||
}, []);
|
||||
// Year Level
|
||||
const [selected_yearlevel, setSelectedYearLevel] = useState("");
|
||||
const [yearLevelOpen, setYearLevelOpen] = useState(false);
|
||||
const [year_levels, setYearLevels] = useState([
|
||||
{ label: "1st Year", value: "1st Year" },
|
||||
{ label: "2nd Year", value: "2nd Year" },
|
||||
]);
|
||||
const yearlevel_query = useQuery({
|
||||
queryKey: ["year_levels"],
|
||||
queryFn: GetYearLevels,
|
||||
onSuccess: (data) => {
|
||||
let year_levels = data.map((item: YearLevelParams) => ({
|
||||
label: item.name,
|
||||
value: item.name,
|
||||
}));
|
||||
setYearLevels(year_levels);
|
||||
},
|
||||
});
|
||||
// Course
|
||||
const [selected_course, setSelectedCourse] = useState("");
|
||||
const [courseOpen, setCourseOpen] = useState(false);
|
||||
const [courses, setCourses] = useState([
|
||||
{
|
||||
label: "Bachelor of Science in Information Technology",
|
||||
value: "BSIT",
|
||||
},
|
||||
{ label: "Bachelor of Science in Computer Science", value: "BSCS" },
|
||||
]);
|
||||
const course_query = useQuery({
|
||||
queryKey: ["courses"],
|
||||
queryFn: GetCourses,
|
||||
onSuccess: (data) => {
|
||||
let courses = data.map((item: CourseParams) => ({
|
||||
label: item.name,
|
||||
value: item.name,
|
||||
}));
|
||||
setCourses(courses);
|
||||
},
|
||||
});
|
||||
if (yearlevel_query.error || semester_query.error || course_query.error) {
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{shown && (
|
||||
<MotiView
|
||||
from={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
exitTransition={{ type: "timing", duration: 1200, delay: 600 }}
|
||||
transition={{ type: "timing", duration: 1200, delay: 600 }}
|
||||
>
|
||||
<Text style={styles.text_white_small}>
|
||||
We're glad to have you on board {"\n"}
|
||||
Just a few more things before we get started
|
||||
</Text>
|
||||
</MotiView>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<View style={styles.background}>
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.text_white_medium}>Error loading details</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.background}>
|
||||
<View style={styles.container}>
|
||||
|
@ -63,14 +116,112 @@ export default function Onboarding() {
|
|||
}}
|
||||
/>
|
||||
<View style={{ paddingVertical: 4 }} />
|
||||
<Introduction />
|
||||
<View style={{ paddingVertical: 8 }} />
|
||||
<MotiView
|
||||
from={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ type: "timing", duration: 900, delay: 2000 }}
|
||||
transition={{ type: "timing", duration: 1200, delay: 600 }}
|
||||
>
|
||||
<Text style={styles.text_white_small}>
|
||||
We're glad to have you on board {"\n"}
|
||||
Just a few more things before we get started
|
||||
</Text>
|
||||
</MotiView>
|
||||
<View style={{ paddingVertical: 8 }} />
|
||||
|
||||
<MotiView
|
||||
from={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ type: "timing", duration: 400, delay: 1700 }}
|
||||
>
|
||||
<Text style={styles.text_white_medium}>Academic Info</Text>
|
||||
<DropDownPicker
|
||||
zIndex={3000}
|
||||
open={courseOpen}
|
||||
value={selected_course}
|
||||
items={courses}
|
||||
setOpen={(open) => {
|
||||
setCourseOpen(open);
|
||||
setSemesterOpen(false);
|
||||
setYearLevelOpen(false);
|
||||
}}
|
||||
setValue={setSelectedCourse}
|
||||
placeholder="Choose your course"
|
||||
containerStyle={{
|
||||
...styles.dropdown_template,
|
||||
...{ zIndex: 3000 },
|
||||
}}
|
||||
dropDownContainerStyle={{ backgroundColor: "white" }}
|
||||
/>
|
||||
<DropDownPicker
|
||||
zIndex={2000}
|
||||
open={semesterOpen}
|
||||
value={selected_semester}
|
||||
items={semesters}
|
||||
setOpen={(open) => {
|
||||
setSemesterOpen(open);
|
||||
setCourseOpen(false);
|
||||
setYearLevelOpen(false);
|
||||
}}
|
||||
setValue={setSelectedSemester}
|
||||
placeholder="Current semester"
|
||||
containerStyle={{
|
||||
...styles.dropdown_template,
|
||||
...{ zIndex: 2000 },
|
||||
}}
|
||||
dropDownContainerStyle={{ backgroundColor: "white" }}
|
||||
/>
|
||||
<DropDownPicker
|
||||
zIndex={1000}
|
||||
open={yearLevelOpen}
|
||||
value={selected_yearlevel}
|
||||
items={year_levels}
|
||||
setOpen={(open) => {
|
||||
setYearLevelOpen(open);
|
||||
setSemesterOpen(false);
|
||||
setCourseOpen(false);
|
||||
}}
|
||||
setValue={setSelectedYearLevel}
|
||||
placeholder="Your Year Level"
|
||||
containerStyle={{
|
||||
...styles.dropdown_template,
|
||||
...{ zIndex: 1000 },
|
||||
}}
|
||||
dropDownContainerStyle={{ backgroundColor: "white" }}
|
||||
/>
|
||||
</MotiView>
|
||||
<MotiView
|
||||
from={{ opacity: 0 }}
|
||||
animate={{ opacity: 1, zIndex: -1 }}
|
||||
transition={{ type: "timing", duration: 400, delay: 1700 }}
|
||||
style={styles.button_template}
|
||||
>
|
||||
<Text style={styles.text_white_small}>{error}</Text>
|
||||
<Button
|
||||
disabled={
|
||||
!selected_yearlevel || !selected_course || !selected_semester
|
||||
}
|
||||
onPress={async () => {
|
||||
let result = await OnboardingUpdateStudentInfo({
|
||||
semester: selected_semester,
|
||||
course: selected_course,
|
||||
year_level: selected_yearlevel,
|
||||
});
|
||||
if (result[0]) {
|
||||
dispatch(unsetOnboarding());
|
||||
setSelectedCourse("");
|
||||
setSelectedYearLevel("");
|
||||
setSelectedSemester("");
|
||||
setError("Success!");
|
||||
dispatch(setUser(result[1]));
|
||||
navigation.navigate("Home");
|
||||
} else {
|
||||
setError(result[1]);
|
||||
}
|
||||
}}
|
||||
color={colors.blue_3}
|
||||
>
|
||||
<Text style={styles.text_white_small}>Proceed</Text>
|
||||
</Button>
|
||||
</MotiView>
|
||||
</View>
|
||||
</View>
|
||||
|
|
|
@ -160,7 +160,7 @@ export default function Register() {
|
|||
} else {
|
||||
setUser({
|
||||
...user,
|
||||
feedback: ParseError(JSON.stringify(result[2])),
|
||||
feedback: ParseError(JSON.stringify(result[1])),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -7,8 +7,14 @@ import { colors } from "../../styles";
|
|||
import { useEffect, useState } from "react";
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
import { RootDrawerParamList } from "../../interfaces/Interfaces";
|
||||
import { setUser } from "../../features/redux/slices/AuthSlice/AuthSlice";
|
||||
import {
|
||||
login,
|
||||
unsetOnboarding,
|
||||
} from "../../features/redux/slices/StatusSlice/StatusSlice";
|
||||
import AnimatedContainer from "../../components/AnimatedContainer/AnimatedContainer";
|
||||
import { setUser } from "../../features/redux/slices/UserSlice/UserSlice";
|
||||
import { setOnboarding } from "../../features/redux/slices/StatusSlice/StatusSlice";
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
|
||||
export default function Revalidation() {
|
||||
const dispatch = useDispatch();
|
||||
|
@ -17,14 +23,23 @@ export default function Revalidation() {
|
|||
useEffect(() => {
|
||||
setState("Previous session found");
|
||||
TokenRefresh().then(async (response) => {
|
||||
if (response[0]) {
|
||||
let user_info = await UserInfo();
|
||||
await dispatch(setUser(user_info));
|
||||
if (!(user_info.year_level || user_info.course || user_info.semester)) {
|
||||
let user_info = await UserInfo();
|
||||
if (response && user_info[0]) {
|
||||
dispatch(login());
|
||||
dispatch(setUser(user_info[1]));
|
||||
if (
|
||||
!(
|
||||
user_info[1].year_level ||
|
||||
user_info[1].course ||
|
||||
user_info[1].semester
|
||||
)
|
||||
) {
|
||||
dispatch(setOnboarding());
|
||||
await setTimeout(() => {
|
||||
navigation.navigate("Onboarding");
|
||||
}, 700);
|
||||
} else {
|
||||
dispatch(unsetOnboarding());
|
||||
await setTimeout(() => {
|
||||
navigation.navigate("Home");
|
||||
}, 700);
|
||||
|
@ -32,6 +47,7 @@ export default function Revalidation() {
|
|||
} else {
|
||||
await setState("Session expired");
|
||||
await setTimeout(() => {
|
||||
AsyncStorage.clear();
|
||||
navigation.navigate("Login");
|
||||
}, 700);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import { createErrorHandler } from "expo/build/errors/ExpoErrorManager";
|
||||
import { StyleSheet } from "react-native";
|
||||
import { StyleSheet, Dimensions } from "react-native";
|
||||
|
||||
const width = Dimensions.get("window").width;
|
||||
const height = Dimensions.get("window").height;
|
||||
|
||||
const containerWidth = width - width * 0.08;
|
||||
const containerHeight = height - height * 0.01;
|
||||
|
||||
export const colors = {
|
||||
orange_1: "#FFDEAD",
|
||||
|
@ -15,6 +20,7 @@ export const colors = {
|
|||
login_color: "#0047AB",
|
||||
reg_color: "#0096FF",
|
||||
head: "white"
|
||||
blue_disabled: "#C07624",
|
||||
};
|
||||
|
||||
export const font_sizes = {
|
||||
|
@ -32,17 +38,13 @@ const styles = StyleSheet.create({
|
|||
width: "100%",
|
||||
},
|
||||
container: {
|
||||
marginTop: "5%",
|
||||
width: "92%",
|
||||
borderRadius: 15,
|
||||
backgroundColor: colors.blue_2,
|
||||
alignItems: "center",
|
||||
alignSelf: "center",
|
||||
paddingTop: 32,
|
||||
paddingBottom: 32,
|
||||
justifyContent: "flex-start",
|
||||
justifyContent: "center",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
flex: 1,
|
||||
paddingHorizontal: 4,
|
||||
},
|
||||
flex_row: {
|
||||
display: "flex",
|
||||
|
@ -53,6 +55,7 @@ const styles = StyleSheet.create({
|
|||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
},
|
||||
text_white_tiny: {
|
||||
color: colors.text_default,
|
||||
|
@ -88,19 +91,32 @@ const styles = StyleSheet.create({
|
|||
justifyContent: "center",
|
||||
alignSelf: "center",
|
||||
alignItems: "center",
|
||||
textAlign: "center",
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
marginVertical: 4,
|
||||
marginHorizontal: 8,
|
||||
padding: 8,
|
||||
borderRadius: 16,
|
||||
width: width * 0.4,
|
||||
},
|
||||
text_input: {
|
||||
color: colors.text_default,
|
||||
backgroundColor: colors.blue_1,
|
||||
width: "50%",
|
||||
padding: 10,
|
||||
borderRadius: 8,
|
||||
width: width * 0.5,
|
||||
},
|
||||
dropdown_template: {
|
||||
borderRadius: 16,
|
||||
width: "70%",
|
||||
marginVertical: 6,
|
||||
},
|
||||
map: {
|
||||
flex: 1,
|
||||
height: containerHeight,
|
||||
width: containerWidth,
|
||||
alignSelf: "center",
|
||||
},
|
||||
profile: {
|
||||
height: 80,
|
||||
|
@ -140,7 +156,5 @@ const styles = StyleSheet.create({
|
|||
inactiveText: {
|
||||
color: 'white',
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default styles;
|
||||
|
|
Loading…
Reference in a new issue