forked from fr/deguapp
		
	Added: fully working signin/signup system with routing
This commit is contained in:
		| @@ -11,7 +11,7 @@ services: | |||||||
|     image: mongo-express |     image: mongo-express | ||||||
|     restart: always |     restart: always | ||||||
|     ports: |     ports: | ||||||
|       - 8081:8081 |       - 8091:8081 | ||||||
|     environment: |     environment: | ||||||
|       ME_CONFIG_MONGODB_ADMINUSERNAME: root |       ME_CONFIG_MONGODB_ADMINUSERNAME: root | ||||||
|       ME_CONFIG_MONGODB_ADMINPASSWORD: root |       ME_CONFIG_MONGODB_ADMINPASSWORD: root | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ | |||||||
| 		"bcrypt": "^5.1.1", | 		"bcrypt": "^5.1.1", | ||||||
| 		"colors": "1.4.0", | 		"colors": "1.4.0", | ||||||
| 		"cookie-parser": "^1.4.6", | 		"cookie-parser": "^1.4.6", | ||||||
|  | 		"cors": "^2.8.5", | ||||||
| 		"dotenv": "^16.4.5", | 		"dotenv": "^16.4.5", | ||||||
| 		"express": "^4.19.2", | 		"express": "^4.19.2", | ||||||
| 		"fs-extra": "^10.0.0", | 		"fs-extra": "^10.0.0", | ||||||
| @@ -41,6 +42,7 @@ | |||||||
| 		"@types/bcrypt": "^5.0.2", | 		"@types/bcrypt": "^5.0.2", | ||||||
| 		"@types/chai": "^4.2.22", | 		"@types/chai": "^4.2.22", | ||||||
| 		"@types/cookie-parser": "^1.4.7", | 		"@types/cookie-parser": "^1.4.7", | ||||||
|  | 		"@types/cors": "^2.8.17", | ||||||
| 		"@types/express": "^4.17.21", | 		"@types/express": "^4.17.21", | ||||||
| 		"@types/fs-extra": "^9.0.13", | 		"@types/fs-extra": "^9.0.13", | ||||||
| 		"@types/inquirer": "^8.1.3", | 		"@types/inquirer": "^8.1.3", | ||||||
|   | |||||||
| @@ -1,29 +1,29 @@ | |||||||
| import express from "express"; | import express from "express"; | ||||||
| import morgan from "morgan"; | import morgan from "morgan"; | ||||||
| import path from 'path' | import path from 'path' | ||||||
| //import cors from 'cors' | import cors from 'cors' | ||||||
| import cookieParser from 'cookie-parser' | import cookieParser from 'cookie-parser' | ||||||
| import { router as routes } from "./routes"; | import { router as routes } from "./routes"; | ||||||
| //import { router as middlewares } from './middlewares' | //import { router as middlewares } from './middlewares' | ||||||
| //import env from './config/environment' | import env from './config/environment' | ||||||
|  |  | ||||||
| //export let corsWhitelist: Array<string> | export let corsWhitelist: Array<string> | ||||||
| //if (env.CORS_WHITELIST != 'undefined') { | if (env.CORS_WHITELIST != 'undefined') { | ||||||
| //	corsWhitelist = [...['http://localhost:8080', 'http://localhost:6040'], ...env.CORS_WHITELIST.split(';')] | 	corsWhitelist = [...['http://localhost:8080', 'http://localhost:6040'], ...env.CORS_WHITELIST.split(';')] | ||||||
| //} else { | } else { | ||||||
| //	corsWhitelist = ['http://localhost:8080', 'http://localhost:6040'] | 	corsWhitelist = ['http://localhost:8080', 'http://localhost:6040'] | ||||||
| //} | } | ||||||
| //const corsOptions = { | const corsOptions = { | ||||||
| //	origin: function (origin: any, callback: any) { | 	origin: function (origin: any, callback: any) { | ||||||
| //		if (!origin || corsWhitelist.indexOf(origin) !== -1) { | 		if (!origin || corsWhitelist.indexOf(origin) !== -1) { | ||||||
| //			callback(null, true) | 			callback(null, true) | ||||||
| //		} else { | 		} else { | ||||||
| //			callback(new Error('Not allowed by CORS')) | 			callback(new Error('Not allowed by CORS')) | ||||||
| //		} | 		} | ||||||
| //	}, | 	}, | ||||||
| //	optionsSuccessStatus: 200, | 	optionsSuccessStatus: 200, | ||||||
| //	credentials: true | 	credentials: true | ||||||
| //} | } | ||||||
|  |  | ||||||
| export const app = express(); | export const app = express(); | ||||||
|  |  | ||||||
| @@ -31,7 +31,7 @@ export const app = express(); | |||||||
| //app.use(middlewares) | //app.use(middlewares) | ||||||
| //app.set('view engine', 'ejs') | //app.set('view engine', 'ejs') | ||||||
| //app.set('views', path.join(__dirname, 'views')) | //app.set('views', path.join(__dirname, 'views')) | ||||||
| //app.use(cors(corsOptions)) | app.use(cors(corsOptions)) | ||||||
| app.use(morgan("dev")); | app.use(morgan("dev")); | ||||||
| app.use(express.urlencoded({ extended: true })); | app.use(express.urlencoded({ extended: true })); | ||||||
| app.use(express.json()); | app.use(express.json()); | ||||||
|   | |||||||
| @@ -52,7 +52,7 @@ export async function signin_post(req: Request, res: Response) { | |||||||
| 			res.cookie('jwt', token, { httpOnly: true, maxAge: maxAge * 1000 }); | 			res.cookie('jwt', token, { httpOnly: true, maxAge: maxAge * 1000 }); | ||||||
| 			res.cookie('auth', true, { httpOnly: false, maxAge: maxAge * 1000 }); | 			res.cookie('auth', true, { httpOnly: false, maxAge: maxAge * 1000 }); | ||||||
|  |  | ||||||
| 			res.json(Log.info(200, 'user is logged in')); | 			res.json(Log.info(200, 'user is logged in', {jwt: token})); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ router.get('/', docsController.docs_get); | |||||||
|  |  | ||||||
| router.post("/auth/signup",validate(AuthVal.signup) , authController.signup_post); | router.post("/auth/signup",validate(AuthVal.signup) , authController.signup_post); | ||||||
| router.post("/auth/signin",validate(AuthVal.signin) , authController.signin_post); | router.post("/auth/signin",validate(AuthVal.signin) , authController.signin_post); | ||||||
|  | router.options("/auth/signin",validate(AuthVal.signin) , authController.signin_post); | ||||||
| router.post("/auth/logout", requireAuth, authController.logout_post); | router.post("/auth/logout", requireAuth, authController.logout_post); | ||||||
| router.get("/auth/status", requireAuth, authController.status_get); | router.get("/auth/status", requireAuth, authController.status_get); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,5 +2,5 @@ import * as shell from 'shelljs'; | |||||||
|  |  | ||||||
| // Copy all the view templates | // Copy all the view templates | ||||||
| //shell.cp('-R', 'src/views', 'dist/') | //shell.cp('-R', 'src/views', 'dist/') | ||||||
| //shell.cp('-R', 'src/public', 'dist/'); | shell.cp('-R', 'src/public', 'dist/'); | ||||||
| shell.cp('-u', 'src/.env', 'dist/'); | shell.cp('-u', 'src/.env', 'dist/'); | ||||||
| @@ -2,6 +2,7 @@ | |||||||
|   "expo": { |   "expo": { | ||||||
|     "name": "deguapp", |     "name": "deguapp", | ||||||
|     "slug": "deguapp", |     "slug": "deguapp", | ||||||
|  |     "scheme": "deguapp", | ||||||
|     "version": "1.0.0", |     "version": "1.0.0", | ||||||
|     "orientation": "portrait", |     "orientation": "portrait", | ||||||
|     "icon": "./assets/icon.png", |     "icon": "./assets/icon.png", | ||||||
| @@ -25,6 +26,9 @@ | |||||||
|     }, |     }, | ||||||
|     "web": { |     "web": { | ||||||
|       "favicon": "./assets/favicon.png" |       "favicon": "./assets/favicon.png" | ||||||
|     } |     }, | ||||||
|  |     "plugins": [ | ||||||
|  |       "expo-router" | ||||||
|  |     ] | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								frontend/app/(app)/_layout.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								frontend/app/(app)/_layout.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | import { Redirect, Stack } from "expo-router"; | ||||||
|  |  | ||||||
|  | import { useAuth } from "../context/AuthContext"; | ||||||
|  | import { View, Text } from "react-native"; | ||||||
|  |  | ||||||
|  | export default function AppLayout() { | ||||||
|  |   const { authState } = useAuth(); | ||||||
|  |  | ||||||
|  |   if (authState.authenticated === null) { | ||||||
|  |     // micro loading co neni skoro videt ale get the fuck out se uz neloguje | ||||||
|  |     return ( | ||||||
|  |       <View> | ||||||
|  |         <Text>Loading...</Text> | ||||||
|  |       </View> | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |   if (!authState.authenticated) { | ||||||
|  |     console.log("get the fuck out"); | ||||||
|  |     return <Redirect href="/login" />; | ||||||
|  |   } | ||||||
|  |   return <Stack />; | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								frontend/app/(app)/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								frontend/app/(app)/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | import { Text, View } from "react-native"; | ||||||
|  |  | ||||||
|  | import { useAuth } from "../context/AuthContext"; | ||||||
|  |  | ||||||
|  | export default function Index() { | ||||||
|  |   const { onLogout } = useAuth(); | ||||||
|  |   const user = "debil" | ||||||
|  |   return ( | ||||||
|  |     <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}> | ||||||
|  |       <Text>Welcome {user}</Text> | ||||||
|  |       <Text | ||||||
|  |         onPress={() => { | ||||||
|  |           // The `app/(app)/_layout.tsx` will redirect to the sign-in screen. | ||||||
|  |           onLogout(); | ||||||
|  |         }} | ||||||
|  |       > | ||||||
|  |         Sign Out | ||||||
|  |       </Text> | ||||||
|  |     </View> | ||||||
|  |   ); | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								frontend/app/_layout.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								frontend/app/_layout.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | import { Slot } from "expo-router"; | ||||||
|  | import { AuthProvider } from "./context/AuthContext"; | ||||||
|  |  | ||||||
|  | export default function Root() { | ||||||
|  |   return ( | ||||||
|  |     <AuthProvider> | ||||||
|  |       <Slot /> | ||||||
|  |     </AuthProvider> | ||||||
|  |   ); | ||||||
|  | } | ||||||
							
								
								
									
										103
									
								
								frontend/app/context/AuthContext.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								frontend/app/context/AuthContext.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | |||||||
|  | import { createContext, useContext, useEffect, useState } from "react"; | ||||||
|  | import axios from "axios"; | ||||||
|  | import storageUtil from "./storage"; | ||||||
|  |  | ||||||
|  | const TOKEN_KEY = "my-jwt"; | ||||||
|  | export const API_URL = "http://10.69.1.137:6060/api/v1"; | ||||||
|  | const AuthContext = createContext(null); | ||||||
|  |  | ||||||
|  | export function useAuth() { | ||||||
|  |   const authContext = useContext(AuthContext); | ||||||
|  |   if (authContext === undefined) { | ||||||
|  |     throw new Error("Context is outside of provider"); | ||||||
|  |   } | ||||||
|  |   return authContext; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export function AuthProvider({ children }) { | ||||||
|  |   const [authState, setAuthState] = useState({ | ||||||
|  |     token: null, | ||||||
|  |     authenticated: null, | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   useEffect(() => { | ||||||
|  |     // tohle se zavola jen poprve pri startu appky | ||||||
|  |     async function loadToken() { | ||||||
|  |       const token = await storageUtil.getItem(TOKEN_KEY); | ||||||
|  |       console.log(`stored: ${token}`); | ||||||
|  |  | ||||||
|  |       if (token) { | ||||||
|  |         axios.defaults.headers.common["Authorization"] = `Bearer ${token}`; | ||||||
|  |  | ||||||
|  |         setAuthState({ | ||||||
|  |           token: token, | ||||||
|  |           authenticated: true, | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       setAuthState({ | ||||||
|  |         authenticated: false, | ||||||
|  |         token: null, | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     loadToken(); | ||||||
|  |   }, []); | ||||||
|  |  | ||||||
|  |   async function register(username, email, password) { | ||||||
|  |     try { | ||||||
|  |       const res = await axios.post(`${API_URL}/auth/signup`, { | ||||||
|  |         username, | ||||||
|  |         email, | ||||||
|  |         password, | ||||||
|  |       }); | ||||||
|  |       return res | ||||||
|  |     } catch (err) { | ||||||
|  |       return { error: true, msg: err.response.data}; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   async function login(email, password) { | ||||||
|  |     try { | ||||||
|  |       const res = await axios.post(`${API_URL}/auth/signin`, { | ||||||
|  |         email, | ||||||
|  |         password, | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |       setAuthState({ | ||||||
|  |         token: res.data.data.jwt, | ||||||
|  |         authenticated: true, | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |       //axios.defaults.headers.common[ | ||||||
|  |       //  "Authorization" | ||||||
|  |       //] = `Bearer ${res.data.data.jwt}`; | ||||||
|  |  | ||||||
|  |       await storageUtil.setItem(TOKEN_KEY, res.data.data.jwt); | ||||||
|  |  | ||||||
|  |       return res | ||||||
|  |     } catch (err) { | ||||||
|  |       return { error: true, msg: err.res }; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   async function logout() { | ||||||
|  |     await storageUtil.delItem(TOKEN_KEY); | ||||||
|  |  | ||||||
|  |     axios.defaults.headers.common["Authorization"] = ""; | ||||||
|  |  | ||||||
|  |     setAuthState({ | ||||||
|  |       token: null, | ||||||
|  |       authenticated: false, | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const value = { | ||||||
|  |     onSignin: register, | ||||||
|  |     onLogin: login, | ||||||
|  |     onLogout: logout, | ||||||
|  |     authState, | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>; | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								frontend/app/context/storage.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								frontend/app/context/storage.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | import * as SecureStore from "expo-secure-store"; | ||||||
|  | import { Platform } from "react-native"; | ||||||
|  | import AsyncStorage from "@react-native-async-storage/async-storage"; | ||||||
|  |  | ||||||
|  | const storageUtil = { | ||||||
|  |   setItem: async (k, v) => { | ||||||
|  |     if (Platform.OS === "web") { | ||||||
|  |       // web | ||||||
|  |       await AsyncStorage.setItem(k, v); | ||||||
|  |     } else { | ||||||
|  |       // mobile | ||||||
|  |       await SecureStore.setItemAsync(k, v.toString()); // v must be string, | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   getItem: async (k) => { | ||||||
|  |     if (Platform.OS === "web") { | ||||||
|  |       // web | ||||||
|  |       return await AsyncStorage.getItem(k); | ||||||
|  |     } else { | ||||||
|  |       // mobile | ||||||
|  |       return await SecureStore.getItemAsync(k); | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   delItem: async (k) => { | ||||||
|  |     if (Platform.OS === "web") { | ||||||
|  |       // web | ||||||
|  |       await AsyncStorage.removeItem(k); | ||||||
|  |     } else { | ||||||
|  |       // mobile | ||||||
|  |       await SecureStore.deleteItemAsync(k); | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | }; | ||||||
|  | export default storageUtil; | ||||||
							
								
								
									
										6
									
								
								frontend/app/hooks/useIsAutheticated.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								frontend/app/hooks/useIsAutheticated.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | import { useAuth } from "../context/AuthContext"; | ||||||
|  |  | ||||||
|  | export function useIsAutheticated() { | ||||||
|  |   const { authState } = useAuth(); | ||||||
|  |   return authState.authenticated | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								frontend/app/index.js.old
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								frontend/app/index.js.old
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | import { Redirect, Link } from "expo-router"; | ||||||
|  | import { Text, View } from "react-native"; | ||||||
|  | import { AuthProvider } from "./context/AuthContext"; | ||||||
|  |  | ||||||
|  | function HomePage() { | ||||||
|  |   return <Redirect href="/login" />; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export default HomePage; | ||||||
| @@ -1,15 +1,26 @@ | |||||||
| import { | import { StyleSheet, TextInput, View, Text, Image } from "react-native"; | ||||||
|   StyleSheet, | import { useEffect, useState } from "react"; | ||||||
|   TouchableOpacity, | import { router } from "expo-router"; | ||||||
|   TextInput, |  | ||||||
|   View, |  | ||||||
|   Text, |  | ||||||
|   Image, |  | ||||||
| } from "react-native"; |  | ||||||
| import Button from "../components/Button"; | import Button from "../components/Button"; | ||||||
| import { colors } from "../components/style"; | import { colors } from "../components/style"; | ||||||
| 
 | 
 | ||||||
| export function LoginForm() { | import { useAuth } from "./context/AuthContext"; | ||||||
|  | 
 | ||||||
|  | function LoginPage() { | ||||||
|  |   const [pass, setPass] = useState(""); | ||||||
|  |   const [email, setEmail] = useState(""); | ||||||
|  |   const { onLogin, authState } = useAuth(); | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (authState.authenticated) { | ||||||
|  |       router.replace("/"); | ||||||
|  |     } | ||||||
|  |   }, [authState.authenticated]); | ||||||
|  | 
 | ||||||
|  |   function login() { | ||||||
|  |     onLogin(email, pass); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   return ( |   return ( | ||||||
|     <View style={styles.container}> |     <View style={styles.container}> | ||||||
|       <View style={styles.header}> |       <View style={styles.header}> | ||||||
| @@ -19,7 +30,6 @@ export function LoginForm() { | |||||||
|         /> |         /> | ||||||
|         <Text style={styles.h1}>Please Log In</Text> |         <Text style={styles.h1}>Please Log In</Text> | ||||||
|       </View> |       </View> | ||||||
| 
 |  | ||||||
|       <View style={styles.form}> |       <View style={styles.form}> | ||||||
|         <TextInput |         <TextInput | ||||||
|           style={styles.input} |           style={styles.input} | ||||||
| @@ -30,6 +40,8 @@ export function LoginForm() { | |||||||
|           keyboardType="email-address" |           keyboardType="email-address" | ||||||
|           placeholderTextColor={"#aaaaaa"} |           placeholderTextColor={"#aaaaaa"} | ||||||
|           returnKeyType="next" |           returnKeyType="next" | ||||||
|  |           value={email} | ||||||
|  |           onChangeText={(text) => setEmail(text)} | ||||||
|         /> |         /> | ||||||
|         <TextInput |         <TextInput | ||||||
|           style={styles.input} |           style={styles.input} | ||||||
| @@ -37,19 +49,21 @@ export function LoginForm() { | |||||||
|           placeholder="Enter your password" |           placeholder="Enter your password" | ||||||
|           placeholderTextColor={"#aaaaaa"} |           placeholderTextColor={"#aaaaaa"} | ||||||
|           returnKeyType="done" |           returnKeyType="done" | ||||||
|  |           value={pass} | ||||||
|  |           onChangeText={(text) => setPass(text)} | ||||||
|         /> |         /> | ||||||
|         <View style={styles.btnContainer}> |         <View style={styles.btnContainer}> | ||||||
|           <Button |           <Button | ||||||
|             style={styles.button} |             style={styles.button} | ||||||
|             title="Sign Up" |             title="Sign Up" | ||||||
|             color={colors.charcoal} |             color={colors.charcoal} | ||||||
|             onPress={() => alert("Signed In")} |             onPress={() => router.replace("/signup")} | ||||||
|           /> |           /> | ||||||
|           <Button |           <Button | ||||||
|             style={styles.button} |             style={styles.button} | ||||||
|             title="Log In" |             title="Log In" | ||||||
|             color={colors.gold} |             color={colors.gold} | ||||||
|             onPress={() => alert("Logged In")} |             onPress={login} | ||||||
|           /> |           /> | ||||||
|         </View> |         </View> | ||||||
|       </View> |       </View> | ||||||
| @@ -92,9 +106,12 @@ const styles = StyleSheet.create({ | |||||||
|     borderWidth: 1, |     borderWidth: 1, | ||||||
|     borderRadius: 5, |     borderRadius: 5, | ||||||
|     padding: 10, |     padding: 10, | ||||||
|  |     color: "#fff", | ||||||
|   }, |   }, | ||||||
|   btnContainer: { |   btnContainer: { | ||||||
|     flexDirection: "row", |     flexDirection: "row", | ||||||
|     gap: 5, |     gap: 5, | ||||||
|   }, |   }, | ||||||
| }); | }); | ||||||
|  | 
 | ||||||
|  | export default LoginPage; | ||||||
							
								
								
									
										148
									
								
								frontend/app/signup.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								frontend/app/signup.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | |||||||
|  | import { StyleSheet, TextInput, View, Text, Image } from "react-native"; | ||||||
|  | import { useState } from "react"; | ||||||
|  | import Button from "../components/Button"; | ||||||
|  | import { colors } from "../components/style"; | ||||||
|  | import { Link, router } from "expo-router"; | ||||||
|  |  | ||||||
|  | import { useAuth } from "./context/AuthContext"; | ||||||
|  |  | ||||||
|  | function SignupPage() { | ||||||
|  |   const [pass1, setPass1] = useState(""); | ||||||
|  |   const [pass2, setPass2] = useState(""); | ||||||
|  |   const [email, setEmail] = useState(""); | ||||||
|  |   const [username, setUsername] = useState(""); | ||||||
|  |   const { onSignin } = useAuth(); | ||||||
|  |  | ||||||
|  |   async function signin() { | ||||||
|  |     if (pass1 == pass2) { | ||||||
|  |       const res = await onSignin(username, email, pass1); | ||||||
|  |       if (res.error) { | ||||||
|  |         if(res.msg.message == "validation error") { | ||||||
|  |           alert(res.msg.data.message); | ||||||
|  |         } else { | ||||||
|  |           alert(res.msg.message) | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       if (!res.error) { | ||||||
|  |         alert("You have been successfully registered. Please Log In"); | ||||||
|  |         router.replace("/login"); | ||||||
|  |       } | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     alert("Passwords are not same!"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return ( | ||||||
|  |     <View style={styles.container}> | ||||||
|  |       <View style={styles.header}> | ||||||
|  |         <Image | ||||||
|  |           source={require("../assets/deguapp_logo.png")} | ||||||
|  |           style={styles.logo} | ||||||
|  |         /> | ||||||
|  |         <Text style={styles.h1}>Please Sign Up</Text> | ||||||
|  |       </View> | ||||||
|  |  | ||||||
|  |       <View style={styles.form}> | ||||||
|  |         <TextInput | ||||||
|  |           style={styles.input} | ||||||
|  |           placeholder="Enter your username" | ||||||
|  |           placeholderTextColor={"#aaaaaa"} | ||||||
|  |           returnKeyType="done" | ||||||
|  |           value={username} | ||||||
|  |           onChangeText={(username) => setUsername(username)} | ||||||
|  |         /> | ||||||
|  |         <TextInput | ||||||
|  |           style={styles.input} | ||||||
|  |           placeholder="Enter your email" | ||||||
|  |           autoCapitalize="none" | ||||||
|  |           autoCompleteType="email" | ||||||
|  |           textContentType="emailAddress" | ||||||
|  |           keyboardType="email-address" | ||||||
|  |           placeholderTextColor={"#aaaaaa"} | ||||||
|  |           returnKeyType="next" | ||||||
|  |           value={email} | ||||||
|  |           onChangeText={(email) => setEmail(email)} | ||||||
|  |         /> | ||||||
|  |         <TextInput | ||||||
|  |           style={styles.input} | ||||||
|  |           secureTextEntry={true} | ||||||
|  |           placeholder="Enter your password" | ||||||
|  |           placeholderTextColor={"#aaaaaa"} | ||||||
|  |           returnKeyType="done" | ||||||
|  |           value={pass1} | ||||||
|  |           onChangeText={(pass1) => setPass1(pass1)} | ||||||
|  |         /> | ||||||
|  |         <TextInput | ||||||
|  |           style={styles.input} | ||||||
|  |           secureTextEntry={true} | ||||||
|  |           placeholder="Enter your password" | ||||||
|  |           placeholderTextColor={"#aaaaaa"} | ||||||
|  |           returnKeyType="done" | ||||||
|  |           value={pass2} | ||||||
|  |           onChangeText={(pass2) => setPass2(pass2)} | ||||||
|  |         /> | ||||||
|  |         <Button | ||||||
|  |           style={styles.button} | ||||||
|  |           title="Sign Up" | ||||||
|  |           color={colors.gold} | ||||||
|  |           onPress={signin} | ||||||
|  |         /> | ||||||
|  |         <Link href="/login" style={styles.a}> | ||||||
|  |           Already have an account? Log In! | ||||||
|  |         </Link> | ||||||
|  |       </View> | ||||||
|  |     </View> | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const styles = StyleSheet.create({ | ||||||
|  |   container: { | ||||||
|  |     width: "100%", | ||||||
|  |     height: "100%", | ||||||
|  |     backgroundColor: colors.dark, | ||||||
|  |   }, | ||||||
|  |   form: { | ||||||
|  |     flex: 1, | ||||||
|  |     alignItems: "center", | ||||||
|  |     paddingTop: "10%", | ||||||
|  |     width: "100%", | ||||||
|  |     gap: 15, | ||||||
|  |   }, | ||||||
|  |   h1: { | ||||||
|  |     color: "#FFF", | ||||||
|  |     fontSize: 30, | ||||||
|  |     textAlign: "center", | ||||||
|  |     paddingTop: "20%", | ||||||
|  |   }, | ||||||
|  |   a: { | ||||||
|  |     color: "#FFF", | ||||||
|  |     fontSize: 12, | ||||||
|  |     fontStyle: "italic", | ||||||
|  |     textDecorationLine: "underline", | ||||||
|  |   }, | ||||||
|  |   logo: { | ||||||
|  |     width: "80%", | ||||||
|  |     resizeMode: "contain", | ||||||
|  |   }, | ||||||
|  |   header: { | ||||||
|  |     width: "100%", | ||||||
|  |     alignItems: "center", | ||||||
|  |     paddingTop: "20%", | ||||||
|  |   }, | ||||||
|  |   input: { | ||||||
|  |     height: "auto", | ||||||
|  |     width: "60%", | ||||||
|  |     borderColor: "gray", | ||||||
|  |     borderWidth: 1, | ||||||
|  |     borderRadius: 5, | ||||||
|  |     padding: 10, | ||||||
|  |     color: "#fff", | ||||||
|  |   }, | ||||||
|  |   btnContainer: { | ||||||
|  |     flexDirection: "row", | ||||||
|  |     gap: 5, | ||||||
|  |   }, | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | export default SignupPage; | ||||||
							
								
								
									
										
											BIN
										
									
								
								frontend/assets/deguapp_logo_v2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								frontend/assets/deguapp_logo_v2.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 79 KiB | 
							
								
								
									
										772
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										772
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,7 +1,7 @@ | |||||||
| { | { | ||||||
|   "name": "deguapp", |   "name": "deguapp", | ||||||
|   "version": "1.0.0", |   "version": "1.0.0", | ||||||
|   "main": "node_modules/expo/AppEntry.js", |   "main": "expo-router/entry", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "start": "expo start", |     "start": "expo start", | ||||||
|     "android": "expo start --android", |     "android": "expo start --android", | ||||||
| @@ -9,13 +9,22 @@ | |||||||
|     "web": "expo start --web" |     "web": "expo start --web" | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|  |     "@expo/metro-runtime": "~3.1.3", | ||||||
|  |     "@react-native-async-storage/async-storage": "^1.23.1", | ||||||
|  |     "@types/react": "~18.2.45", | ||||||
|  |     "axios": "^1.6.8", | ||||||
|     "expo": "~50.0.17", |     "expo": "~50.0.17", | ||||||
|  |     "expo-constants": "~15.4.6", | ||||||
|  |     "expo-linking": "~6.2.2", | ||||||
|  |     "expo-router": "~3.4.10", | ||||||
|  |     "expo-secure-store": "^12.8.1", | ||||||
|     "expo-status-bar": "~1.11.1", |     "expo-status-bar": "~1.11.1", | ||||||
|     "react": "18.2.0", |     "react": "18.2.0", | ||||||
|     "react-native": "0.73.6", |  | ||||||
|     "react-native-web": "~0.19.6", |  | ||||||
|     "react-dom": "18.2.0", |     "react-dom": "18.2.0", | ||||||
|     "@expo/metro-runtime": "~3.1.3" |     "react-native": "0.73.6", | ||||||
|  |     "react-native-safe-area-context": "4.8.2", | ||||||
|  |     "react-native-screens": "~3.29.0", | ||||||
|  |     "react-native-web": "~0.19.6" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@babel/core": "^7.20.0" |     "@babel/core": "^7.20.0" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user