From f6202bfb793dcba1f194fde9302d0f0a27462372 Mon Sep 17 00:00:00 2001 From: afazio1 Date: Sun, 24 Mar 2024 17:21:13 -0400 Subject: [PATCH 1/7] add boilerplate screens --- frontend/package-lock.json | 25 ++++++++++++++++++++++++- frontend/package.json | 3 ++- frontend/src/assets/screens/Login.tsx | 7 +++++++ frontend/src/assets/screens/Signup.tsx | 7 +++++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 frontend/src/assets/screens/Login.tsx create mode 100644 frontend/src/assets/screens/Signup.tsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d74e05d..e1241df 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,7 +9,8 @@ "version": "0.0.0", "dependencies": { "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-router": "^6.22.3" }, "devDependencies": { "@types/react": "^18.2.64", @@ -569,6 +570,14 @@ "node": ">= 8" } }, + "node_modules/@remix-run/router": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", + "integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.13.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz", @@ -2373,6 +2382,20 @@ "react": "^18.2.0" } }, + "node_modules/react-router": { + "version": "6.22.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz", + "integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==", + "dependencies": { + "@remix-run/router": "1.15.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index c0de196..7af203c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,7 +11,8 @@ }, "dependencies": { "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-router": "^6.22.3" }, "devDependencies": { "@types/react": "^18.2.64", diff --git a/frontend/src/assets/screens/Login.tsx b/frontend/src/assets/screens/Login.tsx new file mode 100644 index 0000000..8dbca5e --- /dev/null +++ b/frontend/src/assets/screens/Login.tsx @@ -0,0 +1,7 @@ +export default function Login() { + return ( +
+

Login

+
+ ); +} \ No newline at end of file diff --git a/frontend/src/assets/screens/Signup.tsx b/frontend/src/assets/screens/Signup.tsx new file mode 100644 index 0000000..a0eafdf --- /dev/null +++ b/frontend/src/assets/screens/Signup.tsx @@ -0,0 +1,7 @@ +export default function Signup() { + return ( +
+

Signup

+
+ ); +} \ No newline at end of file From fdb7b3a1ce2e65e3eb4ec36f842773205bc43d2c Mon Sep 17 00:00:00 2001 From: afazio1 Date: Sun, 24 Mar 2024 18:02:40 -0400 Subject: [PATCH 2/7] add basic login, signup, navbar --- frontend/package-lock.json | 18 +++++++++++++++++- frontend/package.json | 2 +- frontend/src/App.css | 0 frontend/src/App.tsx | 15 ++++++++++++--- frontend/src/assets/screens/Login.tsx | 7 ------- frontend/src/assets/screens/Signup.tsx | 7 ------- frontend/src/main.tsx | 26 +++++++++++++++++++++++++- frontend/src/screens/Login.tsx | 19 +++++++++++++++++++ frontend/src/screens/Signup.tsx | 19 +++++++++++++++++++ frontend/src/styles/App.css | 9 +++++++++ frontend/src/styles/Login.css | 20 ++++++++++++++++++++ package-lock.json | 6 ++++++ package.json | 1 + 13 files changed, 129 insertions(+), 20 deletions(-) delete mode 100644 frontend/src/App.css delete mode 100644 frontend/src/assets/screens/Login.tsx delete mode 100644 frontend/src/assets/screens/Signup.tsx create mode 100644 frontend/src/screens/Login.tsx create mode 100644 frontend/src/screens/Signup.tsx create mode 100644 frontend/src/styles/App.css create mode 100644 frontend/src/styles/Login.css create mode 100644 package-lock.json create mode 100644 package.json diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e1241df..b76376c 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router": "^6.22.3" + "react-router-dom": "^6.22.3" }, "devDependencies": { "@types/react": "^18.2.64", @@ -2396,6 +2396,22 @@ "react": ">=16.8" } }, + "node_modules/react-router-dom": { + "version": "6.22.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz", + "integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==", + "dependencies": { + "@remix-run/router": "1.15.3", + "react-router": "6.22.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 7af203c..f3ae3f2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,7 +12,7 @@ "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router": "^6.22.3" + "react-router-dom": "^6.22.3" }, "devDependencies": { "@types/react": "^18.2.64", diff --git a/frontend/src/App.css b/frontend/src/App.css deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 9fdfa75..2dbe740 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,12 +1,21 @@ -import './App.css' +import "./styles/App.css"; +import { Link } from 'react-router-dom'; -function App() { +export default function App() { return ( <> +

PeerNotes

) } -export default App +function Navbar() { + return ( + + ); +} \ No newline at end of file diff --git a/frontend/src/assets/screens/Login.tsx b/frontend/src/assets/screens/Login.tsx deleted file mode 100644 index 8dbca5e..0000000 --- a/frontend/src/assets/screens/Login.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function Login() { - return ( -
-

Login

-
- ); -} \ No newline at end of file diff --git a/frontend/src/assets/screens/Signup.tsx b/frontend/src/assets/screens/Signup.tsx deleted file mode 100644 index a0eafdf..0000000 --- a/frontend/src/assets/screens/Signup.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function Signup() { - return ( -
-

Signup

-
- ); -} \ No newline at end of file diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 3d7150d..14705c2 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -2,9 +2,33 @@ import React from 'react' import ReactDOM from 'react-dom/client' import App from './App.tsx' import './index.css' +import { + createBrowserRouter, + RouterProvider, +} from "react-router-dom"; +import Login from './screens/Login.tsx'; +import Signup from './screens/Signup.tsx'; + +const router = createBrowserRouter([ + { + path: "/", + element: , + children: [ + // add more routes here + ] + }, + { + path: "/login", + element: , + }, + { + path: "/signup", + element: , + }, +]); ReactDOM.createRoot(document.getElementById('root')!).render( - + , ) diff --git a/frontend/src/screens/Login.tsx b/frontend/src/screens/Login.tsx new file mode 100644 index 0000000..2d9011f --- /dev/null +++ b/frontend/src/screens/Login.tsx @@ -0,0 +1,19 @@ +import { Link } from "react-router-dom" +import "../styles/Login.css" +export default function Login() { + return ( +
+
+

Login

+
+ + + + +
+ +

or Sign up

+
+
+ ); +} \ No newline at end of file diff --git a/frontend/src/screens/Signup.tsx b/frontend/src/screens/Signup.tsx new file mode 100644 index 0000000..e674985 --- /dev/null +++ b/frontend/src/screens/Signup.tsx @@ -0,0 +1,19 @@ +import { Link } from "react-router-dom"; +import "../styles/Login.css" +export default function Signup() { + return ( +
+
+

Sign Up

+
+ + + + +
+ +

or Login

+
+
+ ); +} \ No newline at end of file diff --git a/frontend/src/styles/App.css b/frontend/src/styles/App.css new file mode 100644 index 0000000..da7d9e9 --- /dev/null +++ b/frontend/src/styles/App.css @@ -0,0 +1,9 @@ +nav { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 2rem; + border: 3px solid #f1f1f1; + border-radius: 5px; + color: white; +} \ No newline at end of file diff --git a/frontend/src/styles/Login.css b/frontend/src/styles/Login.css new file mode 100644 index 0000000..f50e3da --- /dev/null +++ b/frontend/src/styles/Login.css @@ -0,0 +1,20 @@ +form { + display: flex; + flex-direction: column; + justify-content: center; + gap: 0.5rem; +} +main { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; +} +h1 { + text-align: center; +} + +.form-inputs { + display: flex; + flex-direction: column; +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..283f7d0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "peernotes", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/package.json @@ -0,0 +1 @@ +{} From 6556bb643b655d1950311dbfc365f3e701b5f03e Mon Sep 17 00:00:00 2001 From: afazio1 Date: Thu, 11 Apr 2024 00:56:43 -0400 Subject: [PATCH 3/7] fix styling + folders --- frontend/src/App.tsx | 2 +- frontend/src/styles/App.css | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 2406274..c44ef54 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -7,7 +7,7 @@ export default function App() { return ( <> -
+
PeerNotes Logo Date: Thu, 11 Apr 2024 01:07:07 -0400 Subject: [PATCH 4/7] fix styling on login + signup page --- frontend/src/screens/Login.tsx | 8 +++++--- frontend/src/screens/Signup.tsx | 10 ++++++---- frontend/src/styles/Login.css | 26 ++++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/frontend/src/screens/Login.tsx b/frontend/src/screens/Login.tsx index 2d9011f..3fa1142 100644 --- a/frontend/src/screens/Login.tsx +++ b/frontend/src/screens/Login.tsx @@ -3,15 +3,17 @@ import "../styles/Login.css" export default function Login() { return (
-
+

Login

-
+
+
+
- +

or Sign up

diff --git a/frontend/src/screens/Signup.tsx b/frontend/src/screens/Signup.tsx index e674985..1f1fbb2 100644 --- a/frontend/src/screens/Signup.tsx +++ b/frontend/src/screens/Signup.tsx @@ -3,15 +3,17 @@ import "../styles/Login.css" export default function Signup() { return (
-
+

Sign Up

-
+
+
+
-
- +
+

or Login

diff --git a/frontend/src/styles/Login.css b/frontend/src/styles/Login.css index f50e3da..3fbe8c4 100644 --- a/frontend/src/styles/Login.css +++ b/frontend/src/styles/Login.css @@ -14,7 +14,29 @@ h1 { text-align: center; } -.form-inputs { +.form-input { display: flex; flex-direction: column; -} \ No newline at end of file +} + + .login-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background: #B1D4E0; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); /* shadow */; + width: 40vh; + } + + .submit-button { + padding: 8px 16px; + margin-top: 20px; /* Adds space above the button */ + background-color: #2E8BC0; /* Example background color */ + color: white; /* Text color */ + border: none; + border-radius: 4px; + cursor: pointer; + font-family: 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif; + } \ No newline at end of file From 04d8c8504ccee8ffef6920eb99ece37d4035b69b Mon Sep 17 00:00:00 2001 From: afazio1 Date: Thu, 11 Apr 2024 02:34:32 -0400 Subject: [PATCH 5/7] add set cookie --- backend/api/user_login.py | 4 +++- backend/peer_notes/settings.py | 4 ++++ frontend/src/screens/Login.tsx | 21 ++++++++++++++++++++- frontend/src/screens/Signup.tsx | 28 +++++++++++++++++++++++++++- 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/backend/api/user_login.py b/backend/api/user_login.py index 1a8becb..4cd8ff5 100644 --- a/backend/api/user_login.py +++ b/backend/api/user_login.py @@ -18,7 +18,9 @@ class LoginView(APIView): user = authenticate(username=username, password=password) if user: token, _ = Token.objects.get_or_create(user=user) - return Response({"token": token.key}) + response = Response({"token": token.key}, status=status.HTTP_200_OK) + response.set_cookie("token", token.key) + return response else: return Response( {"error": "Invalid credentials"}, diff --git a/backend/peer_notes/settings.py b/backend/peer_notes/settings.py index 474b470..2418f69 100644 --- a/backend/peer_notes/settings.py +++ b/backend/peer_notes/settings.py @@ -134,3 +134,7 @@ STATIC_URL = "static/" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" AUTH_USER_MODEL = "api.PeerUser" CORS_ALLOW_ALL_ORIGINS = True +# CORS_ALLOWED_ORIGINS = [ +# "http://localhost:5173" +# ] +CORS_ALLOW_CREDENTIALS = True \ No newline at end of file diff --git a/frontend/src/screens/Login.tsx b/frontend/src/screens/Login.tsx index 3fa1142..928ef90 100644 --- a/frontend/src/screens/Login.tsx +++ b/frontend/src/screens/Login.tsx @@ -1,9 +1,28 @@ import { Link } from "react-router-dom" import "../styles/Login.css" +import { FormEvent } from "react"; + export default function Login() { + function handleSubmit(e: FormEvent) { + e.preventDefault(); + const formData = new FormData(e.target as HTMLFormElement); + const username = formData.get('username'); + const password = formData.get('password'); + fetch('http://localhost:8000/api/login/', { + method: 'POST', + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ username, password }), + }) + .catch((error) => { + console.error('Error:', error); + }); + } return (
-
+

Login

diff --git a/frontend/src/screens/Signup.tsx b/frontend/src/screens/Signup.tsx index 1f1fbb2..c207581 100644 --- a/frontend/src/screens/Signup.tsx +++ b/frontend/src/screens/Signup.tsx @@ -1,10 +1,36 @@ import { Link } from "react-router-dom"; import "../styles/Login.css" +import { FormEvent } from "react"; export default function Signup() { + function handleSubmit(e: FormEvent) { + e.preventDefault(); + const formData = new FormData(e.target as HTMLFormElement); + const email = formData.get('email'); + const username = formData.get('username'); + const password = formData.get('password'); + fetch('http://localhost:8000/api/signup/', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ email, username, password }), + }) + .then(response => response.json()) + .then(data => { + console.log('Success:', data); + }) + .catch((error) => { + console.error('Error:', error); + }); + } return (
- +

Sign Up

+
+ + +
From c89b282e9a5360f1461c549ae8a381ce6f3be981 Mon Sep 17 00:00:00 2001 From: afazio1 Date: Thu, 11 Apr 2024 02:39:23 -0400 Subject: [PATCH 6/7] remove accidental package-lock.json --- package-lock.json | 6 ------ package.json | 1 - 2 files changed, 7 deletions(-) delete mode 100644 package-lock.json delete mode 100644 package.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 283f7d0..0000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "peernotes", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} diff --git a/package.json b/package.json deleted file mode 100644 index 0967ef4..0000000 --- a/package.json +++ /dev/null @@ -1 +0,0 @@ -{} From 16c8e4377b87936b3910ed3c0f1fd811ad8d482f Mon Sep 17 00:00:00 2001 From: afazio1 Date: Thu, 11 Apr 2024 16:48:58 -0400 Subject: [PATCH 7/7] finish login, logout, session context --- frontend/src/App.tsx | 55 +++++++++++++------ frontend/src/contexts/session.ts | 17 ++++++ frontend/src/hooks/sessionRedirect.ts | 14 +++++ frontend/src/screens/Login.tsx | 78 +++++++++++++++------------ frontend/src/screens/Signup.tsx | 10 ++-- 5 files changed, 121 insertions(+), 53 deletions(-) create mode 100644 frontend/src/contexts/session.ts create mode 100644 frontend/src/hooks/sessionRedirect.ts diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index c44ef54..73dfb70 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,31 +1,56 @@ import "./styles/App.css"; -import { Link } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; import MainSearch from './components/MainSearch'; +import { SessionContext, destroySessionCookie, getSessionCookie } from "./contexts/session"; +import { useState, useEffect, useContext } from "react"; export default function App() { + const [session, setSession] = useState(getSessionCookie()); + const navigate = useNavigate(); + + // Redirect to login if session is undefined + useEffect( + () => { + setSession(getSessionCookie()); + if (session === undefined) { + navigate("/login"); + } + }, + [session, navigate] + ); return ( <> - -
- PeerNotes Logo - -
+ + +
+ PeerNotes Logo + +
+
) } - function Navbar() { + const session = useContext(SessionContext); + + const links = session ? ( + <> + Home + Logout + + ): ( + Login + ) return ( ); } \ No newline at end of file diff --git a/frontend/src/contexts/session.ts b/frontend/src/contexts/session.ts new file mode 100644 index 0000000..ce77016 --- /dev/null +++ b/frontend/src/contexts/session.ts @@ -0,0 +1,17 @@ +import React from "react"; + +type SessionContextType = string | undefined; + +export const getSessionCookie = () => { + const sessionCookie = document.cookie + .split('; ') + .find(row => row.startsWith('token=')) + ?.split('=')[1]; + return sessionCookie; +} +export const destroySessionCookie = () => { + document.cookie = "token=; Max-Age=0;" +} + +export const SessionContext = React.createContext(getSessionCookie()); + diff --git a/frontend/src/hooks/sessionRedirect.ts b/frontend/src/hooks/sessionRedirect.ts new file mode 100644 index 0000000..c90d30a --- /dev/null +++ b/frontend/src/hooks/sessionRedirect.ts @@ -0,0 +1,14 @@ +import { useEffect, useContext } from "react"; +import { useNavigate } from "react-router-dom"; +import { SessionContext } from "../contexts/session"; + +export const useSessionRedirect = () => { + const session = useContext(SessionContext); + const navigate = useNavigate(); + // Redirect to home if session is defined + useEffect(() => { + if (session !== undefined) { + navigate('/'); + } + }, [session, navigate]) +} \ No newline at end of file diff --git a/frontend/src/screens/Login.tsx b/frontend/src/screens/Login.tsx index 928ef90..23a1cd5 100644 --- a/frontend/src/screens/Login.tsx +++ b/frontend/src/screens/Login.tsx @@ -1,40 +1,48 @@ -import { Link } from "react-router-dom" +import { Link, useNavigate } from "react-router-dom" import "../styles/Login.css" import { FormEvent } from "react"; +import { useSessionRedirect } from "../hooks/sessionRedirect"; export default function Login() { - function handleSubmit(e: FormEvent) { - e.preventDefault(); - const formData = new FormData(e.target as HTMLFormElement); - const username = formData.get('username'); - const password = formData.get('password'); - fetch('http://localhost:8000/api/login/', { - method: 'POST', - credentials: 'include', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ username, password }), - }) - .catch((error) => { - console.error('Error:', error); - }); - } - return ( -
- -

Login

-
- - -
-
- - -
- -

or Sign up

- -
- ); + const navigate = useNavigate(); + + useSessionRedirect(); + + function handleSubmit(e: FormEvent) { + e.preventDefault(); + const formData = new FormData(e.target as HTMLFormElement); + const username = formData.get('username'); + const password = formData.get('password'); + fetch('http://localhost:8000/api/login/', { + method: 'POST', + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ username, password }), + }) + .then(() => { + navigate('/'); + }) + .catch((error) => { + console.error('Error:', error); + }); + } + return ( +
+
+

Login

+
+ + +
+
+ + +
+ +

or Sign up

+
+
+ ); } \ No newline at end of file diff --git a/frontend/src/screens/Signup.tsx b/frontend/src/screens/Signup.tsx index c207581..9022619 100644 --- a/frontend/src/screens/Signup.tsx +++ b/frontend/src/screens/Signup.tsx @@ -1,7 +1,11 @@ -import { Link } from "react-router-dom"; +import { Link, useNavigate } from "react-router-dom"; import "../styles/Login.css" import { FormEvent } from "react"; +import { useSessionRedirect } from "../hooks/sessionRedirect"; export default function Signup() { + const navigate = useNavigate(); + useSessionRedirect(); + function handleSubmit(e: FormEvent) { e.preventDefault(); const formData = new FormData(e.target as HTMLFormElement); @@ -16,8 +20,8 @@ export default function Signup() { body: JSON.stringify({ email, username, password }), }) .then(response => response.json()) - .then(data => { - console.log('Success:', data); + .then(() => { + navigate('/login'); }) .catch((error) => { console.error('Error:', error);