Added functional registration

This commit is contained in:
Keannu Bernasol 2023-07-03 21:22:31 +08:00
parent dfc20753b3
commit 26b3db25f0
23 changed files with 679 additions and 57 deletions

View file

@ -1,6 +1,8 @@
import "react-native-gesture-handler";
import { NavigationContainer } from "@react-navigation/native";
import { createDrawerNavigator } from "@react-navigation/drawer";
import { Provider } from "react-redux";
import store from "./src/features/redux/Store/Store";
import CustomDrawerContent from "./src/components/DrawerSettings/CustomDrawerContent";
import DrawerScreenSettings from "./src/components/DrawerSettings/DrawerScreenSettings";
@ -13,6 +15,7 @@ const Drawer = createDrawerNavigator();
export default function App() {
return (
<Provider store={store}>
<NavigationContainer>
<Drawer.Navigator
initialRouteName="Home"
@ -24,5 +27,6 @@ export default function App() {
<Drawer.Screen name="Register" component={Register} />
</Drawer.Navigator>
</NavigationContainer>
</Provider>
);
}

199
package-lock.json generated
View file

@ -8,8 +8,11 @@
"name": "stude_frontend",
"version": "1.0.0",
"dependencies": {
"@react-native-async-storage/async-storage": "1.17.11",
"@react-navigation/drawer": "^6.6.3",
"@react-navigation/native-stack": "^6.9.13",
"@reduxjs/toolkit": "^1.9.5",
"axios": "^1.4.0",
"expo": "~48.0.18",
"expo-status-bar": "~1.4.4",
"react": "18.2.0",
@ -18,7 +21,9 @@
"react-native-reanimated": "~2.14.4",
"react-native-safe-area-context": "4.5.0",
"react-native-screens": "~3.20.0",
"react-native-svg": "13.4.0"
"react-native-svg": "13.4.0",
"react-redux": "^8.1.1",
"redux": "^4.2.1"
},
"devDependencies": {
"@babel/core": "^7.20.0",
@ -3653,6 +3658,17 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@react-native-async-storage/async-storage": {
"version": "1.17.11",
"resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.17.11.tgz",
"integrity": "sha512-bzs45n5HNcDq6mxXnSsOHysZWn1SbbebNxldBXCQs8dSvF8Aor9KCdpm+TpnnGweK3R6diqsT8lFhX77VX0NFw==",
"dependencies": {
"merge-options": "^3.0.4"
},
"peerDependencies": {
"react-native": "^0.0.0-0 || 0.60 - 0.71 || 1000.0.0"
}
},
"node_modules/@react-native-community/cli": {
"version": "10.2.2",
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-10.2.2.tgz",
@ -5044,6 +5060,29 @@
"nanoid": "^3.1.23"
}
},
"node_modules/@reduxjs/toolkit": {
"version": "1.9.5",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.5.tgz",
"integrity": "sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ==",
"dependencies": {
"immer": "^9.0.21",
"redux": "^4.2.1",
"redux-thunk": "^2.4.2",
"reselect": "^4.1.8"
},
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18",
"react-redux": "^7.2.1 || ^8.0.2"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-redux": {
"optional": true
}
}
},
"node_modules/@segment/loosely-validate-event": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz",
@ -5097,6 +5136,15 @@
"resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.41.tgz",
"integrity": "sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA=="
},
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
@ -5126,14 +5174,12 @@
"node_modules/@types/prop-types": {
"version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
"dev": true
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
},
"node_modules/@types/react": {
"version": "18.0.38",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.38.tgz",
"integrity": "sha512-ExsidLLSzYj4cvaQjGnQCk4HFfVT9+EZ9XZsQ8Hsrcn8QNgXtpZ3m9vSIC2MWtx7jHictK6wYhQgGh6ic58oOw==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
@ -5143,14 +5189,18 @@
"node_modules/@types/scheduler": {
"version": "0.16.3",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
"integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==",
"dev": true
"integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ=="
},
"node_modules/@types/stack-utils": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw=="
},
"node_modules/@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"node_modules/@types/yargs": {
"version": "15.0.15",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.15.tgz",
@ -5446,6 +5496,29 @@
"node": ">= 4.5.0"
}
},
"node_modules/axios": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/babel-core": {
"version": "7.0.0-bridge.0",
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
@ -6592,8 +6665,7 @@
"node_modules/csstype": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==",
"dev": true
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
},
"node_modules/dag-map": {
"version": "1.0.2",
@ -7644,6 +7716,25 @@
"node": ">=0.4.0"
}
},
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/fontfaceobserver": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz",
@ -8140,6 +8231,15 @@
"node": ">=4.0"
}
},
"node_modules/immer": {
"version": "9.0.21",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/import-fresh": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
@ -8419,6 +8519,14 @@
"node": ">=8"
}
},
"node_modules/is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"engines": {
"node": ">=8"
}
},
"node_modules/is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@ -9649,6 +9757,17 @@
"resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz",
"integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA=="
},
"node_modules/merge-options": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz",
"integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==",
"dependencies": {
"is-plain-obj": "^2.1.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@ -11659,6 +11778,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
@ -11976,6 +12100,49 @@
"async-limiter": "~1.0.0"
}
},
"node_modules/react-redux": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.1.tgz",
"integrity": "sha512-5W0QaKtEhj+3bC0Nj0NkqkhIv8gLADH/2kYFMTHxCVqQILiWzLv6MaLuV5wJU3BQEdHKzTfcvPN0WMS6SC1oyA==",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"peerDependencies": {
"@types/react": "^16.8 || ^17.0 || ^18.0",
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0",
"react-native": ">=0.59",
"redux": "^4 || ^5.0.0-beta.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
},
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-redux/node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/react-refresh": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz",
@ -12037,6 +12204,22 @@
"node": ">=0.10.0"
}
},
"node_modules/redux": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
"dependencies": {
"@babel/runtime": "^7.9.2"
}
},
"node_modules/redux-thunk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
"peerDependencies": {
"redux": "^4"
}
},
"node_modules/regenerate": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",

View file

@ -11,6 +11,8 @@
"dependencies": {
"@react-navigation/drawer": "^6.6.3",
"@react-navigation/native-stack": "^6.9.13",
"@reduxjs/toolkit": "^1.9.5",
"axios": "^1.4.0",
"expo": "~48.0.18",
"expo-status-bar": "~1.4.4",
"react": "18.2.0",
@ -19,7 +21,10 @@
"react-native-reanimated": "~2.14.4",
"react-native-safe-area-context": "4.5.0",
"react-native-screens": "~3.20.0",
"react-native-svg": "13.4.0"
"react-native-svg": "13.4.0",
"react-redux": "^8.1.1",
"redux": "^4.2.1",
"@react-native-async-storage/async-storage": "1.17.11"
},
"devDependencies": {
"@babel/core": "^7.20.0",

View file

@ -0,0 +1,73 @@
import axios from "axios";
import AsyncStorage from "@react-native-async-storage/async-storage";
import {
ActivationParams,
LoginParams,
RegistrationParams,
} from "../../interfaces/Interfaces";
let debug = true;
export let backendURL = "";
if (debug) {
backendURL = "http://10.0.10.8:8000";
} else {
backendURL = "https://keannu125.pythonanywhere.com";
}
const instance = axios.create({
baseURL: backendURL,
timeout: 1000,
});
// App APIs
// User APIs
export function UserRegister(register: RegistrationParams) {
console.log(JSON.stringify(register));
return instance
.post("/api/v1/accounts/users/", register)
.then(async (response) => {
return [response.status];
})
.catch((error) => {
return [error.response.status, error.response.data];
});
}
export function UserLogin(user: LoginParams) {
return instance
.post("/api/v1/accounts/token/login/", user)
.then(async (response) => {
AsyncStorage.setItem("token", JSON.stringify(response.data.auth_token));
return true;
})
.catch((error) => {
console.log("Login Failed: " + error);
return false;
});
}
export async function UserInfo() {
const token = JSON.parse((await AsyncStorage.getItem("token")) || "{}");
return instance
.get("/api/v1/accounts/users/me/", {
headers: {
Authorization: "Token " + token,
},
})
.then((response) => {
return response.data;
});
}
export function UserActivate(activation: ActivationParams) {
return instance
.post("/api/v1/accounts/users/activation/", activation)
.then(async (response) => {
return true;
})
.catch((error) => {
return false;
});
}

View file

@ -0,0 +1,23 @@
import * as React from "react";
import { Text, Pressable, GestureResponderEvent } from "react-native";
import styles from "../../styles";
export interface props {
children: React.ReactNode;
onPress: (event: GestureResponderEvent) => void;
color: string;
}
export default function Button(props: props) {
return (
<Pressable
onPress={props.onPress}
style={{
...styles.button_template,
...{ backgroundColor: props.color, width: "50%" },
}}
>
{props.children}
</Pressable>
);
}

View file

@ -14,7 +14,11 @@ export default function DrawerButton(props: props) {
onPress={props.onPress}
style={{
...styles.button_template,
...{ backgroundColor: props.color, width: "95%" },
...{
backgroundColor: props.color,
width: "95%",
justifyContent: "flex-start",
},
}}
>
{props.children}

View file

@ -22,7 +22,7 @@ export default function CustomDrawerContent(props: {}) {
...{ justifyContent: "center" },
}}
>
<AppIcon size={32} color={colors.icon_color} />
<AppIcon size={32} />
<Text style={styles.text_white_medium}>Stud-E</Text>
</View>
<DrawerButton
@ -31,7 +31,7 @@ export default function CustomDrawerContent(props: {}) {
navigation.navigate("Home");
}}
>
<HomeIcon size={32} color={colors.icon_color} />
<HomeIcon size={32} />
<Text style={styles.text_white_medium}>Home</Text>
</DrawerButton>
<DrawerButton
@ -40,7 +40,7 @@ export default function CustomDrawerContent(props: {}) {
navigation.navigate("Login");
}}
>
<LoginIcon size={32} color={colors.icon_color} />
<LoginIcon size={32} />
<Text style={styles.text_white_medium}>Login</Text>
</DrawerButton>
<DrawerButton
@ -49,7 +49,7 @@ export default function CustomDrawerContent(props: {}) {
navigation.navigate("Register");
}}
>
<SignupIcon size={32} color={colors.icon_color} />
<SignupIcon size={32} />
<Text style={styles.text_white_medium}>Register</Text>
</DrawerButton>
</DrawerContentScrollView>

View file

@ -24,7 +24,7 @@ const DrawerScreenSettings: DrawerNavigationOptions = {
<View
style={{ flexDirection: "row", marginRight: 16, alignItems: "center" }}
>
<AppIcon size={32} color={colors.icon_color} />
<AppIcon size={32} />
</View>
),
};

View file

@ -0,0 +1,8 @@
export default function IsNumber(number: string) {
const re = /^[0-9\b]+$/;
if (re.test(number)) {
return true;
} else {
return false;
}
}

View file

@ -0,0 +1,9 @@
export default function ParseError(text: string) {
return text
.replaceAll(/[{}()"]/g, " ")
.replaceAll(/,/g, "\n")
.replaceAll(":", "")
.replaceAll("[", "")
.replaceAll("]", "")
.replaceAll(".", "");
}

View file

@ -0,0 +1,14 @@
import { configureStore } from "@reduxjs/toolkit";
import AuthReducer from "../slices/AuthSlice/AuthSlice";
const store = configureStore({
reducer: {
auth: AuthReducer,
},
});
export default store;
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

View file

@ -0,0 +1,42 @@
import { createSlice } from "@reduxjs/toolkit";
export const AuthSlice = createSlice({
name: "Auth",
initialState: {
creds: {
email: "",
uid: "",
username: "",
full_name: "",
token: "",
},
},
reducers: {
setToken: (state, action) => {
state.creds.token = action.payload.token;
},
setUser: (state, action) => {
state.creds = {
email: action.payload.email,
uid: action.payload.uid,
username: action.payload.username,
full_name: action.payload.full_name,
token: action.payload.token,
};
},
clear: (state) => {
state.creds = {
email: "",
uid: "",
username: "",
full_name: "",
token: "",
};
},
},
});
// Action creators are generated for each case reducer function
export const { setToken, setUser, clear } = AuthSlice.actions;
export default AuthSlice.reducer;

View file

@ -2,6 +2,7 @@ import * as React from "react";
import { IconProps } from "../../interfaces/Interfaces";
import { Svg, Path } from "react-native-svg";
import { colors } from "../../styles";
export default function AddIcon(props: IconProps) {
return (
@ -11,7 +12,7 @@ export default function AddIcon(props: IconProps) {
height={props.size}
viewBox="0 0 24 24"
strokeWidth="2"
stroke={props.color}
stroke={colors.icon_color}
fill="none"
strokeLinecap="round"
strokeLinejoin="round"

View file

@ -2,12 +2,13 @@ import * as React from "react";
import { IconProps } from "../../interfaces/Interfaces";
import { Svg, Path } from "react-native-svg";
import { colors } from "../../styles";
export default function AppIcon(props: IconProps) {
return (
<>
<Svg
fill={props.color}
fill={colors.icon_color}
height={props.size + "px"}
width={props.size + "px"}
viewBox="0 0 375.775 375.775"

View file

@ -2,6 +2,7 @@ import * as React from "react";
import { IconProps } from "../../interfaces/Interfaces";
import { Svg, Path } from "react-native-svg";
import { colors } from "../../styles";
export default function HomeIcon(props: IconProps) {
return (
@ -11,7 +12,7 @@ export default function HomeIcon(props: IconProps) {
height={props.size}
viewBox="0 0 24 24"
strokeWidth="2"
stroke={props.color}
stroke={colors.icon_color}
fill="none"
strokeLinecap="round"
strokeLinejoin="round"

View file

@ -2,6 +2,7 @@ import * as React from "react";
import { IconProps } from "../../interfaces/Interfaces";
import { Svg, Path } from "react-native-svg";
import { colors } from "../../styles";
export default function LoginIcon(props: IconProps) {
return (
@ -11,7 +12,7 @@ export default function LoginIcon(props: IconProps) {
height={props.size}
viewBox="0 0 24 24"
strokeWidth="2"
stroke={props.color}
stroke={colors.icon_color}
fill="none"
strokeLinecap="round"
strokeLinejoin="round"

View file

@ -2,6 +2,7 @@ import * as React from "react";
import { IconProps } from "../../interfaces/Interfaces";
import { Svg, Path } from "react-native-svg";
import { colors } from "../../styles";
export default function LogoutIcon(props: IconProps) {
return (
@ -11,7 +12,7 @@ export default function LogoutIcon(props: IconProps) {
height={props.size}
viewBox="0 0 24 24"
strokeWidth="2"
stroke={props.color}
stroke={colors.icon_color}
fill="none"
strokeLinecap="round"
strokeLinejoin="round"

View file

@ -2,6 +2,7 @@ import * as React from "react";
import { IconProps } from "../../interfaces/Interfaces";
import { Svg, Path } from "react-native-svg";
import { colors } from "../../styles";
export default function SignupIcon(props: IconProps) {
return (
@ -11,7 +12,7 @@ export default function SignupIcon(props: IconProps) {
height={props.size}
viewBox="0 0 24 24"
strokeWidth="2"
stroke={props.color}
stroke={colors.icon_color}
fill="none"
strokeLinecap="round"
strokeLinejoin="round"

View file

@ -2,6 +2,7 @@ import * as React from "react";
import { IconProps } from "../../interfaces/Interfaces";
import { Svg, Path } from "react-native-svg";
import { colors } from "../../styles";
export default function UserIcon(props: IconProps) {
return (
@ -11,7 +12,7 @@ export default function UserIcon(props: IconProps) {
height={props.size}
viewBox="0 0 24 24"
strokeWidth="2"
stroke={props.color}
stroke={colors.icon_color}
fill="none"
strokeLinecap="round"
strokeLinejoin="round"

View file

@ -1,5 +1,9 @@
export interface IconProps {
size: number;
}
export interface ResponsiveIconProps {
size: number;
color: string;
}
@ -28,6 +32,9 @@ export interface RegistrationParams {
email: string;
username: string;
password: string;
first_name: string;
last_name: string;
student_id_number: string;
}
export interface LoginParams {

View file

@ -1,20 +1,87 @@
import * as React from "react";
import styles from "../../styles";
import { font_sizes } from "../../styles";
import { View, Text } from "react-native";
import {
View,
Text,
TextInput,
NativeSyntheticEvent,
TextInputChangeEventData,
} from "react-native";
import { useSelector, useDispatch } from "react-redux";
import { RootState } from "../../features/redux/Store/Store";
import {
setUser,
clear,
} from "../../features/redux/slices/AuthSlice/AuthSlice";
import { colors } from "../../styles";
import { useState } from "react";
import LoginIcon from "../../icons/LoginIcon/LoginIcon";
import Button from "../../components/Button/Button";
import { useNavigation } from "@react-navigation/native";
import { RootDrawerParamList } from "../../interfaces/Interfaces";
export default function Login() {
const navigation = useNavigation<RootDrawerParamList>();
// const dispatch = useDispatch();
// const creds = useSelector((state: RootState) => state.auth.creds);
const [user, setUser] = useState({
email: "",
password: "",
error: "",
});
return (
<View style={styles.background}>
<Text
<View style={styles.container}>
<View
style={{
fontSize: font_sizes.large,
color: "white",
textAlign: "center",
paddingVertical: 4,
marginBottom: 16,
borderRadius: 4,
width: "90%",
backgroundColor: colors.blue_1,
}}
/>
<View style={styles.flex_row}>
<LoginIcon size={32} />
<Text style={styles.text_white_large}>Student Login</Text>
</View>
<View style={{ paddingVertical: 8 }} />
<TextInput
style={styles.text_input}
placeholder="Email"
placeholderTextColor="white"
value={user.email}
onChange={(
e: NativeSyntheticEvent<TextInputChangeEventData>
): void => {
setUser({ ...user, email: e.nativeEvent.text });
}}
/>
<View style={{ paddingVertical: 4 }} />
<TextInput
style={styles.text_input}
placeholder="Password"
placeholderTextColor="white"
secureTextEntry={true}
value={user.password}
onChange={(
e: NativeSyntheticEvent<TextInputChangeEventData>
): void => {
setUser({ ...user, password: e.nativeEvent.text });
}}
/>
<View style={{ paddingVertical: 4 }} />
<Button onPress={() => console.log("heh")} color={colors.blue_3}>
<Text style={styles.text_white_small}>Login</Text>
</Button>
<Button
onPress={() => navigation.navigate("Register")}
color={colors.blue_3}
>
Template Login Page
</Text>
<Text style={styles.text_white_small}>Register</Text>
</Button>
</View>
</View>
);
}

View file

@ -1,20 +1,173 @@
import * as React from "react";
import styles from "../../styles";
import { font_sizes } from "../../styles";
import { View, Text } from "react-native";
import {
View,
Text,
TextInput,
NativeSyntheticEvent,
TextInputChangeEventData,
} from "react-native";
import { useSelector, useDispatch } from "react-redux";
import { colors } from "../../styles";
import { useState } from "react";
import Button from "../../components/Button/Button";
import { useNavigation } from "@react-navigation/native";
import { RootDrawerParamList } from "../../interfaces/Interfaces";
import SignupIcon from "../../icons/SignupIcon/SignupIcon";
import { UserRegister } from "../../components/Api/Api";
import IsNumber from "../../components/IsNumber/IsNumber";
import ParseError from "../../components/ParseError/ParseError";
export default function Register() {
const navigation = useNavigation<RootDrawerParamList>();
// const dispatch = useDispatch();
// const creds = useSelector((state: RootState) => state.auth.creds);
const [user, setUser] = useState({
first_name: "",
last_name: "",
student_id_number: "",
username: "",
email: "",
password: "",
feedback: "",
});
return (
<View style={styles.background}>
<Text
<View style={styles.container}>
<View
style={{
fontSize: font_sizes.large,
color: "white",
textAlign: "center",
paddingVertical: 4,
marginBottom: 16,
borderRadius: 4,
width: "90%",
backgroundColor: colors.blue_1,
}}
/>
<View style={styles.flex_row}>
<SignupIcon size={32} />
<Text style={styles.text_white_large}>Student Signup</Text>
<View style={{ paddingVertical: 8 }} />
</View>
<TextInput
style={styles.text_input}
placeholder="First Name"
placeholderTextColor="white"
value={user.first_name}
onChange={(
e: NativeSyntheticEvent<TextInputChangeEventData>
): void => {
setUser({ ...user, first_name: e.nativeEvent.text });
}}
/>
<View style={{ paddingVertical: 4 }} />
<TextInput
style={styles.text_input}
placeholder="Last Name"
placeholderTextColor="white"
value={user.last_name}
onChange={(
e: NativeSyntheticEvent<TextInputChangeEventData>
): void => {
setUser({ ...user, last_name: e.nativeEvent.text });
}}
/>
<View style={{ paddingVertical: 4 }} />
<TextInput
style={styles.text_input}
placeholder="USTP ID Number"
placeholderTextColor="white"
value={user.student_id_number}
onChange={(
e: NativeSyntheticEvent<TextInputChangeEventData>
): void => {
if (IsNumber(e.nativeEvent.text)) {
setUser({ ...user, student_id_number: e.nativeEvent.text });
} else if (!e.nativeEvent.text) {
setUser({ ...user, student_id_number: "" });
}
}}
/>
<View style={{ paddingVertical: 4 }} />
<View style={{ paddingVertical: 4 }} />
<TextInput
style={styles.text_input}
placeholder="Username"
placeholderTextColor="white"
autoCapitalize={"none"}
value={user.username}
onChange={(
e: NativeSyntheticEvent<TextInputChangeEventData>
): void => {
setUser({ ...user, username: e.nativeEvent.text });
}}
/>
<View style={{ paddingVertical: 4 }} />
<TextInput
style={styles.text_input}
placeholder="Email"
placeholderTextColor="white"
autoCapitalize={"none"}
value={user.email}
onChange={(
e: NativeSyntheticEvent<TextInputChangeEventData>
): void => {
setUser({ ...user, email: e.nativeEvent.text });
}}
/>
<View style={{ paddingVertical: 4 }} />
<TextInput
style={styles.text_input}
placeholder="Password"
placeholderTextColor="white"
secureTextEntry={true}
value={user.password}
onChange={(
e: NativeSyntheticEvent<TextInputChangeEventData>
): void => {
setUser({ ...user, password: e.nativeEvent.text });
}}
/>
<View style={{ paddingVertical: 4 }} />
<Text style={styles.text_white_small}>{user.feedback}</Text>
<View style={{ paddingVertical: 4 }} />
<Button
onPress={async () => {
await UserRegister({
username: user.username,
email: user.email,
password: user.password,
student_id_number: user.student_id_number,
first_name: user.first_name,
last_name: user.last_name,
}).then((result) => {
console.log(result);
try {
setUser({
...user,
feedback: ParseError(JSON.stringify(result[1])),
});
} catch {
setUser({
...user,
first_name: "",
last_name: "",
student_id_number: "",
username: "",
email: "",
password: "",
feedback:
"Success! An email has been sent to activate your account",
});
}
});
{
}
}}
color={colors.blue_3}
>
Template Register Page
</Text>
<Text style={styles.text_white_small}>Register</Text>
</Button>
</View>
</View>
);
}

View file

@ -8,6 +8,8 @@ export const colors = {
blue_2: "#77ACC3",
blue_3: "#1B5D79",
text_default: "white",
text_error: "#e32d1e",
text_success: "green",
icon_color: "white",
};
@ -25,6 +27,19 @@ const styles = StyleSheet.create({
height: "100%",
width: "100%",
},
container: {
marginTop: "5%",
width: "92%",
borderRadius: 15,
backgroundColor: colors.blue_2,
alignItems: "center",
alignSelf: "center",
paddingTop: 32,
paddingBottom: 32,
justifyContent: "flex-start",
display: "flex",
flexDirection: "column",
},
flex_row: {
display: "flex",
flexDirection: "row",
@ -66,15 +81,23 @@ const styles = StyleSheet.create({
textAlign: "center",
},
button_template: {
justifyContent: "flex-start",
justifyContent: "center",
alignSelf: "center",
alignItems: "center",
display: "flex",
flexDirection: "row",
margin: 8,
marginVertical: 4,
marginHorizontal: 8,
padding: 8,
borderRadius: 16,
},
text_input: {
color: colors.text_default,
backgroundColor: colors.blue_1,
width: "50%",
padding: 10,
borderRadius: 8,
},
});
export default styles;