From 9b3443addfd8d537a6a771e2c451f387e0871ba2 Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 1 Dec 2024 16:31:56 +0100 Subject: [PATCH 1/7] Define a basic login form with redirection to the Dashboard --- app/api/authentication.tsx | 15 ++++++++++++++ app/page.tsx | 17 +++++++++++++++- app/ui/components/login-form.tsx | 34 ++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 app/api/authentication.tsx create mode 100644 app/ui/components/login-form.tsx diff --git a/app/api/authentication.tsx b/app/api/authentication.tsx new file mode 100644 index 0000000..4393b98 --- /dev/null +++ b/app/api/authentication.tsx @@ -0,0 +1,15 @@ +import { getCsrfToken } from '@/app/lib/utils'; + +export function login({ email, password, onLogin }: { email: string, password: string, onLogin: () => void }) { + console.log(email, password); + return fetch("/api/default/users/sign_in", { + method: 'POST', + body: JSON.stringify({ user: { email, password } }), + headers: { + 'Content-Type': 'application/json', + 'X-CSRF-TOKEN': getCsrfToken(), + } + }) + .then(onLogin) + .catch((error) => console.error(error)); +} \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index 95ca011..1d01aee 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -2,11 +2,26 @@ import Link from 'next/link'; import styles from '@/app/ui/home.module.css'; +import LoginForm from '@/app/ui/components/login-form'; + + export default function Page() { return (
- +
+
+ + Already have an account? Sign in + + +
+ +
+ Don't have an account? Register now! +
+
+
); } diff --git a/app/ui/components/login-form.tsx b/app/ui/components/login-form.tsx new file mode 100644 index 0000000..4ae32da --- /dev/null +++ b/app/ui/components/login-form.tsx @@ -0,0 +1,34 @@ +'use client'; + +import { FloatLabel } from 'primereact/floatlabel'; +import { InputText } from 'primereact/inputtext'; +import { login } from '../../api/authentication'; +import { useState } from 'react'; +import { classNames } from './button'; +import { useRouter } from 'next/navigation' + +export default function LoginForm() { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + + const router = useRouter() + + return ( +
+ + setEmail(e.target.value)} /> + + + + setPassword(e.target.value)} /> + + + +
+ ) +} \ No newline at end of file From 989820e41bb129ef5feddc4ecc6b28db761b9f2e Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 1 Dec 2024 15:33:24 +0000 Subject: [PATCH 2/7] Add copyright notice --- app/api/authentication.tsx | 2 ++ app/ui/components/login-form.tsx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app/api/authentication.tsx b/app/api/authentication.tsx index 4393b98..e6637af 100644 --- a/app/api/authentication.tsx +++ b/app/api/authentication.tsx @@ -1,3 +1,5 @@ +/* Copyright (C) 2024 Manuel Bustillo*/ + import { getCsrfToken } from '@/app/lib/utils'; export function login({ email, password, onLogin }: { email: string, password: string, onLogin: () => void }) { diff --git a/app/ui/components/login-form.tsx b/app/ui/components/login-form.tsx index 4ae32da..492d1d2 100644 --- a/app/ui/components/login-form.tsx +++ b/app/ui/components/login-form.tsx @@ -1,3 +1,5 @@ +/* Copyright (C) 2024 Manuel Bustillo*/ + 'use client'; import { FloatLabel } from 'primereact/floatlabel'; From 7697148b7dd33b0b6706de2ef80add0df08cb3e7 Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 1 Dec 2024 17:29:57 +0100 Subject: [PATCH 3/7] Basic logout flow --- app/api/authentication.tsx | 23 ++++++++++++++++++++++- app/lib/definitions.ts | 5 +++++ app/ui/components/login-form.tsx | 22 ++++++++++++++++++---- app/ui/dashboard/sidenav.tsx | 28 +++++++++++++++++++++------- 4 files changed, 66 insertions(+), 12 deletions(-) diff --git a/app/api/authentication.tsx b/app/api/authentication.tsx index e6637af..3275700 100644 --- a/app/api/authentication.tsx +++ b/app/api/authentication.tsx @@ -1,6 +1,7 @@ /* Copyright (C) 2024 Manuel Bustillo*/ import { getCsrfToken } from '@/app/lib/utils'; +import { User } from '@/app/lib/definitions'; export function login({ email, password, onLogin }: { email: string, password: string, onLogin: () => void }) { console.log(email, password); @@ -14,4 +15,24 @@ export function login({ email, password, onLogin }: { email: string, password: s }) .then(onLogin) .catch((error) => console.error(error)); -} \ No newline at end of file +} + +export function logout({ onLogout }: { onLogout: () => void }) { + fetch("/api/default/users/sign_out", { + method: 'DELETE', + headers: { + 'X-CSRF-TOKEN': getCsrfToken(), + } + }).then(onLogout) + .catch((error) => console.error(error)); +} + +export function getCurrentUser({ onLoad }: { onLoad: (user: User) => void }) { + fetch("/api/default/users/current") + .then((response) => response.json()) + .then((data) => { + onLoad(data); + }, (error) => { + return null; + }); +} \ No newline at end of file diff --git a/app/lib/definitions.ts b/app/lib/definitions.ts index 5c008c9..5511a46 100644 --- a/app/lib/definitions.ts +++ b/app/lib/definitions.ts @@ -54,3 +54,8 @@ export type guestsTable = { amount: number; status: 'pending' | 'paid'; }; + +export type User = { + id: string; + email: string; +} \ No newline at end of file diff --git a/app/ui/components/login-form.tsx b/app/ui/components/login-form.tsx index 492d1d2..13c6349 100644 --- a/app/ui/components/login-form.tsx +++ b/app/ui/components/login-form.tsx @@ -4,16 +4,23 @@ import { FloatLabel } from 'primereact/floatlabel'; import { InputText } from 'primereact/inputtext'; -import { login } from '../../api/authentication'; -import { useState } from 'react'; +import { getCurrentUser, login } from '../../api/authentication'; +import { useState, useEffect } from 'react'; import { classNames } from './button'; import { useRouter } from 'next/navigation' +import { User } from '../../lib/definitions'; export default function LoginForm() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); - const router = useRouter() + const router = useRouter(); + + const [currentUser, setCurrentUser] = useState(null); + + useEffect(() => { + localStorage.setItem('currentUser', JSON.stringify(currentUser)); + }, [currentUser]); return (
@@ -28,7 +35,14 @@ export default function LoginForm() {
diff --git a/app/ui/dashboard/sidenav.tsx b/app/ui/dashboard/sidenav.tsx index a13a2e6..39a2346 100644 --- a/app/ui/dashboard/sidenav.tsx +++ b/app/ui/dashboard/sidenav.tsx @@ -1,30 +1,44 @@ /* Copyright (C) 2024 Manuel Bustillo*/ +'use client'; + import Link from 'next/link'; import NavLinks from '@/app/ui/dashboard/nav-links'; import { PowerIcon } from '@heroicons/react/24/outline'; import { gloriaHallelujah } from '@/app/ui/fonts'; +import { logout } from '@/app/api/authentication'; +import { useRouter } from 'next/navigation'; export default function SideNav() { + const router = useRouter(); + return (
-
+

Wedding Planner

-
- -
+
); From 868f950559999574755cce8e2c9aff993ef7edc9 Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 1 Dec 2024 17:33:26 +0100 Subject: [PATCH 4/7] Display email of current user --- app/ui/dashboard/sidenav.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/ui/dashboard/sidenav.tsx b/app/ui/dashboard/sidenav.tsx index 39a2346..437cbe6 100644 --- a/app/ui/dashboard/sidenav.tsx +++ b/app/ui/dashboard/sidenav.tsx @@ -25,6 +25,7 @@ export default function SideNav() {
+ Logged in as {JSON.parse(localStorage.getItem('currentUser') || '{}').email}