handle dashboard access by role

This commit is contained in:
haniyeroozmand
2026-03-30 12:59:12 +03:30
parent d9902b7d99
commit be8212deed
4 changed files with 312 additions and 111 deletions

View File

@@ -5,8 +5,14 @@ import {
User, Crown, Home, ShoppingBag, Wallet, MapPin,
Headphones, Heart, IdCard, LogOut, TrendingUp,
Plus, Hash, Clock, AlertCircle, Eye, Reply,
CreditCard, Gift, Edit, Trash2, CircleCheck, Info, Box, Camera, Check, Shield, ShieldAlert, Mail
CreditCard, Gift, Edit, Trash2, CircleCheck, Info, Box, Camera, Check, Shield, ShieldAlert, Mail, CheckCircle, ShieldX
} from 'lucide-react';
import { useSearchParams } from "next/navigation";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
// === رابط‌ها و کامپوننت‌های کمکی ===
interface PriceDisplayProps {
@@ -89,7 +95,22 @@ const sampleAddresses = [
];
export default function Dashboard() {
const [activeTab, setActiveTab] = useState('dash');
const searchParams = useSearchParams();
const success = searchParams.get("success");
const [authorized, setAuthorized] = useState<boolean | null>(null);
React.useEffect(() => {
const token = localStorage.getItem("accessToken");
const role = localStorage.getItem("role");
if (token && (role === "user" || role === "admin")) {
setAuthorized(true);
} else {
setAuthorized(false);
}
}, []);
const menuItems = [
{ id: 'dash', label: 'پیشخوان', icon: Home },
@@ -100,9 +121,73 @@ export default function Dashboard() {
{ id: 'profile', label: 'مشخصات حساب', icon: IdCard },
];
// ✅ حالت در حال بررسی
if (authorized === null) {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50" dir="rtl">
<p className="text-gray-600">در حال بررسی دسترسی...</p>
</div>
);
}
// ❌ دسترسی ندارد
if (!authorized) {
const router = useRouter();
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 px-4" dir="rtl">
<div className="bg-white shadow-xl rounded-2xl p-10 max-w-md w-full text-center border border-gray-100">
<div className="flex justify-center mb-6">
<div className="bg-red-100 p-4 rounded-full">
<ShieldX className="w-10 h-10 text-red-600" />
</div>
</div>
<h1 className="text-2xl font-bold text-gray-800 mb-2">
دسترسی غیرمجاز
</h1>
<p className="text-gray-500 text-sm leading-relaxed mb-6">
شما اجازه دسترسی به این صفحه را ندارید.
برای مشاهده داشبورد باید ابتدا وارد حساب کاربری خود شوید.
</p>
<div className="flex gap-3 justify-center">
<button
onClick={() => router.push("/")}
className="flex cursor-pointer items-center gap-2 bg-gray-900 text-white px-4 py-2 rounded-lg text-sm hover:bg-black transition"
>
<Home className="w-4 h-4" />
بازگشت به صفحه اصلی
</button>
</div>
</div>
</div>
);
}
return (
<div className="min-h-screen bg-gray-50 py-8" dir="rtl">
<div className="container mx-auto px-4 max-w-6xl">
{success === "login" && (
<div className="mb-4 flex items-center gap-2 p-3 bg-[#d2f6dca3] text-green-700 rounded-xl text-sm">
<CheckCircle className="w-4 h-4 text-green-600" />
<span>ورود با موفقیت انجام شد</span>
</div>
)}
{success === "register" && (
<div className="mb-4 flex items-center gap-2 p-3 bg-[#d2f6dca3] text-green-700 rounded-xl text-sm">
<CheckCircle className="w-4 h-4 text-green-600" />
<span>ثبت نام با موفقیت انجام شد</span>
</div>
)}
<div className="flex flex-col lg:flex-row gap-8">
<aside className="w-full lg:w-[280px] bg-white rounded-2xl shadow-sm flex-shrink-0 h-fit">
@@ -129,7 +214,7 @@ export default function Dashboard() {
<li key={item.id}>
<button
onClick={() => setActiveTab(item.id)}
className={`w-full flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold transition-all duration-200 ${activeTab === item.id
className={`w-full cursor-pointer flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold transition-all duration-200 ${activeTab === item.id
? 'bg-[#1a2332] text-white shadow-md'
: 'text-gray-600 hover:bg-gray-50 hover:text-[#ffb900]'
}`}
@@ -153,38 +238,38 @@ export default function Dashboard() {
{activeTab === 'dash' && (
<div className="animate-in fade-in slide-in-from-bottom-4 duration-500">
<h2 className="text-2xl font-bold text-gray-800 mb-6">خوش آمدید، علی عزیز</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<div className="bg-white p-5 rounded-2xl border border-gray-100 shadow-sm flex items-center gap-4 hover:shadow-md transition-shadow">
<div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4 mb-6">
<div className="bg-white p-5 rounded-2xl border border-gray-100 flex-col shadow-sm flex items-center gap-4 hover:shadow-md transition-shadow">
<div className="w-12 h-12 rounded-xl bg-blue-50 text-blue-600 flex items-center justify-center flex-shrink-0"><Wallet size={24} /></div>
<div>
<h4 className="text-xs text-gray-500 mb-1">موجودی کیف پول</h4>
<strong className="text-lg text-gray-800"><PriceDisplay amount={1500000} /></strong>
<strong className="text-[1em] text-gray-800"><PriceDisplay amount={1500000} /></strong>
</div>
</div>
<div className="bg-white p-5 rounded-2xl border border-gray-100 shadow-sm flex items-center gap-4 hover:shadow-md transition-shadow">
<div className="bg-white flex-col p-5 rounded-2xl border border-gray-100 shadow-sm flex items-center gap-4 hover:shadow-md transition-shadow">
<div className="w-12 h-12 rounded-xl bg-green-50 text-green-600 flex items-center justify-center flex-shrink-0"><ShoppingBag size={24} /></div>
<div>
<div className='flex flex-col items-center'>
<h4 className="text-xs text-gray-500 mb-1">سفارشات جاری</h4>
<strong className="text-lg text-gray-800">۲ <span className="text-xs font-normal text-gray-500">مورد</span></strong>
</div>
</div>
<div className="bg-white p-5 rounded-2xl border border-gray-100 shadow-sm flex items-center gap-4 hover:shadow-md transition-shadow">
<div className="bg-white flex-col p-5 rounded-2xl border border-gray-100 shadow-sm flex items-center gap-4 hover:shadow-md transition-shadow">
<div className="w-12 h-12 rounded-xl bg-orange-50 text-orange-600 flex items-center justify-center flex-shrink-0"><Headphones size={24} /></div>
<div>
<div className='flex flex-col items-center'>
<h4 className="text-xs text-gray-500 mb-1">تیکتهای باز</h4>
<strong className="text-lg text-gray-800">۱ <span className="text-xs font-normal text-gray-500">مورد</span></strong>
</div>
</div>
<div className="bg-white p-5 rounded-2xl border border-gray-100 shadow-sm flex items-center gap-4 hover:shadow-md transition-shadow">
<div className="bg-white flex-col p-5 rounded-2xl border border-gray-100 shadow-sm flex items-center gap-4 hover:shadow-md transition-shadow">
<div className="w-12 h-12 rounded-xl bg-purple-50 text-purple-600 flex items-center justify-center flex-shrink-0"><TrendingUp size={24} /></div>
<div>
<div className='flex flex-col items-center'>
<h4 className="text-xs text-gray-500 mb-1">امتیاز وفاداری</h4>
<strong className="text-lg text-gray-800">۲,۳۴۰ <span className="text-xs font-normal text-gray-500">امتیاز</span></strong>
</div>
</div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div className="grid lg:grid-cols-2 gap-6">
<div className="bg-white rounded-2xl border border-gray-100 shadow-sm p-6">
<div className="flex justify-between items-center pb-4 border-b border-gray-100 mb-4">
<h3 className="font-bold text-gray-800">آخرین سفارشات</h3>
@@ -647,3 +732,5 @@ export default function Dashboard() {
</div>
);
}