add logout

This commit is contained in:
2026-05-28 10:20:11 +03:30
parent fcc6a3733d
commit d0772c4c68
5 changed files with 74 additions and 41 deletions

View File

@@ -2,53 +2,46 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server"; import type { NextRequest } from "next/server";
// کلید کوکی که توکن در آن ذخیره می‌شود const AUTH_COOKIE_KEY = "userToken";
const AUTH_COOKIE_KEY = "userToken"; // <<< این را با نام واقعی کوکی خودتان جایگزین کنید
// مسیرهای عمومی
const publicPaths = ["/"]; // فرض کردیم "/" صفحه لاگین است
export function middleware(request: NextRequest) { export function middleware(request: NextRequest) {
const token = request.cookies.get(AUTH_COOKIE_KEY)?.value; const token = request.cookies.get(AUTH_COOKIE_KEY)?.value;
const { pathname } = request.nextUrl; const { pathname } = request.nextUrl;
// مسیرهای عمومی که نیاز به احراز هویت ندارند (مثلا برای لاگین و ثبت نام) const isPublicPath = publicPaths.includes(pathname);
const publicPaths = ["/"];
// اگر کاربر توکن دارد // اگر کاربر لاگین کرده باشد
if (token) { if (token) {
// اگر در مسیر لاگین است، به داشبورد هدایت کن // اگر رفت صفحه لاگین، بفرستش داخل پنل
if (pathname === "/") { if (pathname === "/") {
const url = request.nextUrl.clone(); const url = request.nextUrl.clone();
url.pathname = "/tickets/create"; url.pathname = "/tickets/create";
return NextResponse.redirect(url); return NextResponse.redirect(url);
} }
// در غیر این صورت، اجازه دسترسی به مسیر فعلی را بده
return NextResponse.next(); // بقیه مسیرها مجاز
} else {
// اگر کاربر توکن ندارد
// اگر در مسیرهای عمومی است، اجازه دسترسی بده
if (publicPaths.includes(pathname)) {
return NextResponse.next(); return NextResponse.next();
} }
// اگر در مسیرهای خصوصی است (مثل داشبورد)، به صفحه لاگین هدایت کن
if (pathname.startsWith("/tickets/create")) { // اگر کاربر توکن نداشته باشد
if (!token) {
// فقط مسیرهای عمومی مجازند
if (isPublicPath) {
return NextResponse.next();
}
// هر مسیر دیگری => ریدایرکت به لاگین
const url = request.nextUrl.clone(); const url = request.nextUrl.clone();
url.pathname = "/"; url.pathname = "/";
return NextResponse.redirect(url); return NextResponse.redirect(url);
} }
// برای سایر مسیرهای خصوصی ناشناس
return NextResponse.next(); // یا هدایت به صفحه لاگین return NextResponse.next();
}
} }
// تنظیمات middleware: کدام مسیرها را پوشش دهد
export const config = { export const config = {
matcher: [ matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
/*
* Match all request paths except for the ones starting with:
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
*/
"/((?!api|_next/static|_next/image|favicon.ico).*)",
],
}; };

View File

@@ -4,3 +4,7 @@ export async function loginUser(data: any) {
return await callAPI.post("/auth/login", data).then((res) => res.data); return await callAPI.post("/auth/login", data).then((res) => res.data);
} }
export async function logoutUser() {
return await callAPI.post("/auth/logout").then((res) => res.data);
}

View File

@@ -0,0 +1,4 @@
import { useMutation } from "@tanstack/react-query";
import { logoutUser } from "../api/auth.api";
export const useLogout = () => useMutation({ mutationFn: logoutUser });

35
ui/LogoutButton.tsx Normal file
View File

@@ -0,0 +1,35 @@
"use client";
import { handleAxiosError } from "@/core/utils";
import { useLogout } from "@/services/hooks/auth.hook";
import { Logout } from "@mui/icons-material";
import { Button } from "@mui/material";
import { useRouter } from "next/navigation";
import { toast } from "react-toastify";
export default function LogoutButton() {
const { mutateAsync, isPending } = useLogout();
const router = useRouter();
const handleLogout = async () => {
try {
const { message } = await mutateAsync();
toast.success(message);
router.push("/");
} catch (error) {
toast.error(handleAxiosError(error));
}
};
return (
<>
<Button
className="flex items-center text-[#2a5298] w-full justify-start gap-x-4 hover:cursor-pointer transition-all duration-300
"
onClick={handleLogout}
>
<span>
<Logout />
</span>
<span> خروج از حساب</span>
</Button>
</>
);
}

View File

@@ -1,7 +1,12 @@
import { Apartment, Dashboard, Logout, Notes, Person, PictureInPicture, ShowChart } from "@mui/icons-material"; import {
Logout,
Notes,
PictureInPicture,
ShowChart,
} from "@mui/icons-material";
import { Button } from "@mui/material"; import { Button } from "@mui/material";
import Link from "next/link"; import Link from "next/link";
import React from "react"; import LogoutButton from "../LogoutButton";
export default function Sidebar() { export default function Sidebar() {
return ( return (
@@ -67,15 +72,7 @@ export default function Sidebar() {
</span> </span>
<span> گزارش گيري</span> <span> گزارش گيري</span>
</Link> </Link>
<Button <LogoutButton />
className="flex items-center text-[#2a5298] w-full justify-start gap-x-4 hover:cursor-pointer transition-all duration-300
"
>
<span>
<Logout />
</span>
<span> خروج از حساب</span>
</Button>
</div> </div>
</> </>
); );