mirror of
https://github.com/ershisan99/todolist_next.git
synced 2025-12-17 05:09:30 +00:00
fix login flow
This commit is contained in:
@@ -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 />
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user