Basic logout flow

This commit is contained in:
Manuel Bustillo 2024-12-01 17:29:57 +01:00
parent 989820e41b
commit 7697148b7d
4 changed files with 66 additions and 12 deletions

View File

@ -1,6 +1,7 @@
/* Copyright (C) 2024 Manuel Bustillo*/ /* Copyright (C) 2024 Manuel Bustillo*/
import { getCsrfToken } from '@/app/lib/utils'; import { getCsrfToken } from '@/app/lib/utils';
import { User } from '@/app/lib/definitions';
export function login({ email, password, onLogin }: { email: string, password: string, onLogin: () => void }) { export function login({ email, password, onLogin }: { email: string, password: string, onLogin: () => void }) {
console.log(email, password); console.log(email, password);
@ -15,3 +16,23 @@ export function login({ email, password, onLogin }: { email: string, password: s
.then(onLogin) .then(onLogin)
.catch((error) => console.error(error)); .catch((error) => console.error(error));
} }
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;
});
}

View File

@ -54,3 +54,8 @@ export type guestsTable = {
amount: number; amount: number;
status: 'pending' | 'paid'; status: 'pending' | 'paid';
}; };
export type User = {
id: string;
email: string;
}

View File

@ -4,16 +4,23 @@
import { FloatLabel } from 'primereact/floatlabel'; import { FloatLabel } from 'primereact/floatlabel';
import { InputText } from 'primereact/inputtext'; import { InputText } from 'primereact/inputtext';
import { login } from '../../api/authentication'; import { getCurrentUser, login } from '../../api/authentication';
import { useState } from 'react'; import { useState, useEffect } from 'react';
import { classNames } from './button'; import { classNames } from './button';
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { User } from '../../lib/definitions';
export default function LoginForm() { export default function LoginForm() {
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
const router = useRouter() const router = useRouter();
const [currentUser, setCurrentUser] = useState<User | null>(null);
useEffect(() => {
localStorage.setItem('currentUser', JSON.stringify(currentUser));
}, [currentUser]);
return ( return (
<div className="card flex justify-evenly py-5"> <div className="card flex justify-evenly py-5">
@ -28,7 +35,14 @@ export default function LoginForm() {
<button <button
className={classNames('primary')} className={classNames('primary')}
disabled={email.length == 0 || password.length == 0} disabled={email.length == 0 || password.length == 0}
onClick={() => login({ email: email, password: password, onLogin: () => router.push('/dashboard') })}> onClick={() => login({
email: email,
password: password,
onLogin: () => {
getCurrentUser({ onLoad: (user) => setCurrentUser(user) });
router.push('/dashboard')
}
})}>
Sign in Sign in
</button> </button>
</div> </div>

View File

@ -1,30 +1,44 @@
/* Copyright (C) 2024 Manuel Bustillo*/ /* Copyright (C) 2024 Manuel Bustillo*/
'use client';
import Link from 'next/link'; import Link from 'next/link';
import NavLinks from '@/app/ui/dashboard/nav-links'; import NavLinks from '@/app/ui/dashboard/nav-links';
import { PowerIcon } from '@heroicons/react/24/outline'; import { PowerIcon } from '@heroicons/react/24/outline';
import { gloriaHallelujah } from '@/app/ui/fonts'; import { gloriaHallelujah } from '@/app/ui/fonts';
import { logout } from '@/app/api/authentication';
import { useRouter } from 'next/navigation';
export default function SideNav() { export default function SideNav() {
const router = useRouter();
return ( return (
<div className="flex h-full flex-col px-3 py-4 md:px-2"> <div className="flex h-full flex-col px-3 py-4 md:px-2">
<Link <Link
className="mb-2 flex h-20 items-center justify-start rounded-md bg-blue-600 p-4 md:h-20" className="mb-2 flex h-20 items-center justify-start rounded-md bg-blue-600 p-4 md:h-20"
href="/dashboard/guests" href="/dashboard/guests"
> >
<div className={`${gloriaHallelujah.className} "w-32 text-white md:w-40 antialiased` }> <div className={`${gloriaHallelujah.className} "w-32 text-white md:w-40 antialiased`}>
<h1>Wedding Planner</h1> <h1>Wedding Planner</h1>
</div> </div>
</Link> </Link>
<div className="flex grow flex-row justify-between space-x-2 md:flex-col md:space-x-0 md:space-y-2"> <div className="flex grow flex-row justify-between space-x-2 md:flex-col md:space-x-0 md:space-y-2">
<NavLinks /> <NavLinks />
<div className="hidden h-auto w-full grow rounded-md bg-gray-50 md:block"></div> <div className="hidden h-auto w-full grow rounded-md bg-gray-50 md:block"></div>
<form> <button
<button className="flex h-[48px] w-full grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"> className="flex h-[48px] w-full grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
<PowerIcon className="w-6" /> onClick={() => {
<div className="hidden md:block">Sign Out</div> logout({
</button> onLogout: () => {
</form> localStorage.clear();
router.push('/');
}
});
}}
>
<PowerIcon className="w-6" />
<div className="hidden md:block">Sign Out</div>
</button>
</div> </div>
</div> </div>
); );