diff --git a/backend/routes/auth.js b/backend/routes/auth.js
index 5b71b58..6843335 100644
--- a/backend/routes/auth.js
+++ b/backend/routes/auth.js
@@ -31,6 +31,7 @@ router.post("/signup", async (req, res, next) => {
if (user) errors.username = "Username already exists";
if (Object.keys(errors).length > 0) {
+ console.log(errors);
return res.status(422).json({
message: "User signup failed due to validation errors.",
errors,
diff --git a/frontend/.gitignore b/frontend/.gitignore
index a547bf3..3b0b403 100644
--- a/frontend/.gitignore
+++ b/frontend/.gitignore
@@ -22,3 +22,5 @@ dist-ssr
*.njsproj
*.sln
*.sw?
+
+.env
\ No newline at end of file
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index a2971ae..460419e 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -3,7 +3,7 @@ import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import { Button } from '@mantine/core'
-import { createBrowserRouter, RouterProvider } from 'react-router-dom'
+import { createBrowserRouter, redirect, RouterProvider } from 'react-router-dom'
import Home from './pages/Home'
import MainLayout from './layout/MainLayout'
import Settings from './pages/Settings/Settings'
@@ -14,12 +14,16 @@ import Themes from './pages/Settings/Themes'
import PlayLayout from './pages/Play/Layout'
import PlayFriend from './pages/Play/PlayFriend'
import Play from './pages/Play/Play'
+import AuthenticationPage, { loginAction, signupAction } from './pages/Authentication/Authentication'
+import { getAuthToken } from '../utils/auth'
+import { logoutAction } from './components/Logout'
const router = createBrowserRouter([{
path: '/',
element: ,
+ loader: () => getAuthToken() || redirect('/login'),
children: [
{ index: true, element: },
{ path: 'home', element: },
@@ -39,8 +43,14 @@ const router = createBrowserRouter([{
{ path: 'password', element: },
{ path: 'friends', element: },
]
- }
+ },
]
+}, {
+ path: '/login', element: , action: loginAction, loader: () => { if (getAuthToken()) return redirect('/home'); else return null; }
+}, {
+ path: '/signup', element: , action: signupAction, loader: () => { if (getAuthToken()) return redirect('/signup'); else return null; }
+}, {
+ path: '/logout', loader: () => { getAuthToken() || redirect('/home') }, action: logoutAction
}]);
function App() {
diff --git a/frontend/src/components/Logout.jsx b/frontend/src/components/Logout.jsx
new file mode 100644
index 0000000..f92b7b4
--- /dev/null
+++ b/frontend/src/components/Logout.jsx
@@ -0,0 +1,30 @@
+import React from 'react'
+import { Button, Flex, Modal, Text, Title } from '@mantine/core'
+import { Form, redirect } from 'react-router-dom'
+import { useDisclosure } from '@mantine/hooks'
+
+const Logout = () => {
+ const [isOpen, { open, close }] = useDisclosure(false);
+
+ return (
+ <>
+ Logout} centered>
+ Are you sure you want to logout?
+
+
+
+
+
+
+ >
+ )
+}
+
+export const logoutAction = ({ request }) => {
+ localStorage.removeItem('token');
+ return redirect('/login');
+}
+
+export default Logout
\ No newline at end of file
diff --git a/frontend/src/layout/MainLayout.jsx b/frontend/src/layout/MainLayout.jsx
index 9c62ce9..d274644 100644
--- a/frontend/src/layout/MainLayout.jsx
+++ b/frontend/src/layout/MainLayout.jsx
@@ -2,6 +2,7 @@ import { AppShell, Button, Container, Navbar, Paper, Text, useMantineTheme } fro
import React, { useState } from 'react'
import NavbarLinks from '../components/NavbarLinks';
import { Outlet } from 'react-router-dom'
+import Logout from '../components/Logout';
const MainLayout = () => {
const theme = useMantineTheme();
@@ -27,7 +28,7 @@ const MainLayout = () => {
-
+
}
diff --git a/frontend/src/pages/Authentication/Authentication.jsx b/frontend/src/pages/Authentication/Authentication.jsx
new file mode 100644
index 0000000..721837a
--- /dev/null
+++ b/frontend/src/pages/Authentication/Authentication.jsx
@@ -0,0 +1,116 @@
+import React, { useState } from 'react';
+import { Button, Card, Container, Text, TextInput } from '@mantine/core';
+import { Form, redirect, useNavigate } from 'react-router-dom';
+import { isLoggedIn } from '../../../utils/auth';
+
+const AuthenticationPage = (props) => {
+ const navigate = useNavigate();
+ const { isLogin } = props;
+
+ return (
+
+
+
+ {isLogin ? 'Login' : 'Sign Up'}
+
+
+ {isLogin ? : }
+
+ {/* Toggle between login and signup */}
+
+ {isLogin ? 'Don\'t have an account?' : 'Already have an account?'}
+
+
+
+
+
+ );
+};
+
+const LoginForm = () => {
+ return (
+
+ );
+};
+
+const SignupForm = () => {
+ return (
+
+ );
+};
+
+export const loginAction = async ({ request }) => {
+ const data = await request.formData();
+ let url = `${import.meta.env.VITE_BACKEND_HOST}/api/auth/login`;
+
+ const authData = {
+ username: data.get('username'),
+ password: data.get('password')
+ }
+
+ const response = await fetch(url, {
+ method: 'POST',
+ body: JSON.stringify(authData),
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+
+ if (response.status >= 400) return response;
+ else {
+ const responseBody = await response.json();
+ localStorage.setItem('token', responseBody.token);
+ return redirect('/home');
+ }
+}
+
+export const signupAction = async ({ request }) => {
+ const data = await request.formData();
+ let url = `${import.meta.env.VITE_BACKEND_HOST}/api/auth/signup`;
+
+ const authData = {
+ username: data.get('username'),
+ email: data.get('email'),
+ password: data.get('password')
+ }
+
+ const response = await fetch(url, {
+ method: 'POST',
+ body: JSON.stringify(authData),
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+
+ if (response.status >= 400) return response;
+ else {
+ const responseBody = await response.json();
+ localStorage.setItem('token', responseBody.token);
+ return redirect('/home');
+ }
+}
+
+export default AuthenticationPage;
diff --git a/frontend/utils/auth.js b/frontend/utils/auth.js
new file mode 100644
index 0000000..b046139
--- /dev/null
+++ b/frontend/utils/auth.js
@@ -0,0 +1,16 @@
+import { redirect } from "react-router-dom";
+
+export function checkAuthStatus() {
+ const token = localStorage.getItem("token");
+ if (token) return token;
+ else return redirect("/login");
+}
+
+export function isLoggedIn() {
+ if(localStorage.getItem('token')) return true;
+ else return false;
+}
+
+export function getAuthToken() {
+ return localStorage.getItem("token");
+}