fix login flow

This commit is contained in:
2024-08-15 17:36:24 +02:00
parent 0d32ec6d97
commit 171539eacf
5 changed files with 94 additions and 99 deletions

View File

@@ -9,17 +9,17 @@ import { useMeQuery } from "@/services"
export const AuthRedirect: FC<{ children: ReactNode }> = ({ children }) => { export const AuthRedirect: FC<{ children: ReactNode }> = ({ children }) => {
const router = useRouter() const router = useRouter()
const { data: user, isLoading } = useMeQuery() const { data: user, isPending } = useMeQuery()
const isAuthPage = const isAuthPage =
router.pathname === "/login" || router.pathname === "/sign-up" router.pathname === "/login" || router.pathname === "/sign-up"
useEffect(() => { useEffect(() => {
if (!isLoading && !user && !isAuthPage) { if (!isPending && !user && !isAuthPage) {
router.push("/login") router.push("/login")
} }
}, [user, isLoading, isAuthPage, router]) }, [user, isPending, isAuthPage, router])
if (isLoading || (!user && !isAuthPage)) { if (isPending || (!user && !isAuthPage)) {
return ( return (
<div className={"h-screen"}> <div className={"h-screen"}>
<Loader /> <Loader />

View File

@@ -7,40 +7,59 @@ import { AuthRedirect, Button } from "@/components"
import { ModeToggle } from "@/components/mode-toggle" import { ModeToggle } from "@/components/mode-toggle"
import { ThemeProvider } from "@/components/theme-provider" import { ThemeProvider } from "@/components/theme-provider"
import { useLogoutMutation } from "@/services" import { useLogoutMutation } from "@/services"
import Link from "next/link"
import { useRouter } from "next/router"
const queryClient = new QueryClient() const queryClient = new QueryClient()
const MyApp: AppType = ({ Component, pageProps }) => { const MyApp: AppType = ({ Component, pageProps }) => {
return ( return (
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<AuthRedirect> <ThemeProvider
<ThemeProvider attribute="class"
attribute="class" defaultTheme="system"
defaultTheme="system" enableSystem
enableSystem disableTransitionOnChange
disableTransitionOnChange >
> <Header />
<Header /> <AuthRedirect>
<Component {...pageProps} /> <Component {...pageProps} />
</ThemeProvider> </AuthRedirect>
</AuthRedirect> </ThemeProvider>
</QueryClientProvider> </QueryClientProvider>
) )
} }
function Header() { function Header() {
const router = useRouter()
const { mutate: logout } = useLogoutMutation() const { mutate: logout } = useLogoutMutation()
const handleLogout = () => {
logout() const isLoginPage = router.pathname === "/login"
} const isSignUpPage = router.pathname === "/sign-up"
const isOtherPage = !isLoginPage && !isSignUpPage
return ( return (
<header className={"flex items-center justify-between p-4"}> <header className={"flex items-center justify-between p-4"}>
<h1 className={"text-3xl"}>Tasks</h1> <Link href={"/"} className={"text-3xl"}>
Tasks
</Link>
<div className={"flex gap-4"}> <div className={"flex gap-4"}>
<ModeToggle /> <ModeToggle />
<Button onClick={handleLogout} variant={"outline"}> {isOtherPage && (
Logout <Button onClick={logout} variant={"outline"}>
</Button> Logout
</Button>
)}
{isLoginPage && (
<Button variant={"outline"} asChild>
<Link href={"/sign-up"}>Sign up</Link>
</Button>
)}
{isSignUpPage && (
<Button variant={"outline"} asChild>
<Link href={"/login"}>Sign In</Link>
</Button>
)}
</div> </div>
</header> </header>
) )

View File

@@ -1,68 +1,40 @@
import type { ChangeEvent } from "react" import type { FormEvent } from "react"
import React, { useState } from "react" import React from "react"
import type { NextPage } from "next" import type { NextPage } from "next"
import { Button, Input } from "@/components" import { Button, Input } from "@/components"
import { Label } from "@/components/ui/label" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { useLoginMutation } from "@/services" import { useLoginMutation } from "@/services"
const Login: NextPage = () => { const Login: NextPage = () => {
const { mutate: login } = useLoginMutation() const { mutate: login } = useLoginMutation()
const [email, setEmail] = useState("") const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
const [password, setPassword] = useState("") e.preventDefault()
const [remember, setRemember] = useState(true) const formData = new FormData(e.currentTarget)
const handlePasswordChange = (e: ChangeEvent<HTMLInputElement>) => { // biome-ignore lint/suspicious/noExplicitAny: <explanation>
setPassword(e.target.value) const values = Object.fromEntries(formData) as any
} login(values)
const handleEmailChange = (e: ChangeEvent<HTMLInputElement>) => {
setEmail(e.target.value)
}
const handleRememberChange = (e: ChangeEvent<HTMLInputElement>) => {
setRemember(e.target.checked)
}
const handleSubmit = () => {
login({
email,
password,
rememberMe: remember,
})
} }
return ( return (
<div className={"flex h-full items-center justify-center"}> <div className={"flex h-full items-center justify-center"}>
<div className={"flex w-52 flex-col gap-3"}> <Card className={"w-96"}>
<Input <CardHeader>
value={email} <CardTitle>Sign In</CardTitle>
onChange={handleEmailChange} </CardHeader>
type="email" <CardContent>
label={"Email"} <form className={"flex flex-col gap-3"} onSubmit={handleSubmit}>
/> <Input type="email" name={"email"} label={"Email"} />
<Input type="password" name={"password"} label={"Password"} />
<Input <Button className={"w-full"} type={"submit"}>
type="password" Sign in
label={"Password"} </Button>
value={password} </form>
onChange={handlePasswordChange} </CardContent>
/> </Card>
<Label className={"flex items-center gap-2"}>
<input
type={"checkbox"}
checked={remember}
onChange={handleRememberChange}
/>
Remember me
</Label>
<Button className={"w-full"} onClick={handleSubmit}>
Login
</Button>
</div>
</div> </div>
) )
} }

View File

@@ -4,6 +4,7 @@ import React from "react"
import type { NextPage } from "next" import type { NextPage } from "next"
import { Button, Input } from "@/components" import { Button, Input } from "@/components"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { useSignUpMutation } from "@/services" import { useSignUpMutation } from "@/services"
const Login: NextPage = () => { const Login: NextPage = () => {
@@ -19,30 +20,33 @@ const Login: NextPage = () => {
} }
return ( return (
<div className={"flex h-screen items-center justify-center"}> <div className={"flex h-full items-center justify-center"}>
<form <Card className={"w-96"}>
className={"flex w-96 flex-col gap-3 rounded-md border p-6"} <CardHeader>
onSubmit={handleSubmit} <CardTitle>Sign up</CardTitle>
> </CardHeader>
<h1 className={"font-bold text-2xl"}>Sign up</h1> <CardContent>
<label className={"flex flex-col gap-1"}> <form className={"flex flex-col gap-3"} onSubmit={handleSubmit}>
Username (optional) <label className={"flex flex-col gap-1"}>
<Input name={"username"} type="text" /> Username (optional)
</label> <Input name={"username"} type="text" />
<label className={"flex flex-col gap-1"}> </label>
Email <label className={"flex flex-col gap-1"}>
<Input name={"email"} type="email" /> Email
</label> <Input name={"email"} type="email" />
</label>
<label className={"flex flex-col gap-1"}> <label className={"flex flex-col gap-1"}>
Password Password
<Input type="password" name={"password"} /> <Input type="password" name={"password"} />
</label> </label>
<Button className={"w-full"} type={"submit"}> <Button className={"w-full"} type={"submit"}>
Login Sign Up
</Button> </Button>
</form> </form>
</CardContent>
</Card>
</div> </div>
) )
} }

View File

@@ -29,14 +29,14 @@ export const useLoginMutation = () => {
export const useLogoutMutation = () => { export const useLogoutMutation = () => {
const queryClient = useQueryClient() const queryClient = useQueryClient()
const router = useRouter() const router = useRouter()
return {
return useMutation({ mutate: async () => {
mutationFn: AuthApi.logout, localStorage.removeItem("accessToken")
onSuccess: async () => { localStorage.removeItem("refreshToken")
await queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.ME] }) await queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.ME] })
await router.push(ROUTES.LOGIN) await router.push(ROUTES.LOGIN)
}, },
}) }
} }
export const useSignUpMutation = () => { export const useSignUpMutation = () => {