handle dashboard access by role
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
112
app/page.tsx
112
app/page.tsx
@@ -17,50 +17,6 @@ import Link from "next/link";
|
||||
import { useCategories } from "@/components/context/categoryprovider";
|
||||
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: Headphones,
|
||||
title: "مشاوره فنی رایگان",
|
||||
desc: "انتخاب بهترین قطعه با توجه به نیاز شما",
|
||||
},
|
||||
{
|
||||
icon: FileText,
|
||||
title: "فاکتور رسمی",
|
||||
desc: "صدور فاکتور برای شرکتها",
|
||||
},
|
||||
{
|
||||
icon: Truck,
|
||||
title: "ارسال فوری",
|
||||
desc: "ارسال در سریعترین زمان ممکن",
|
||||
},
|
||||
{
|
||||
icon: ShieldCheck,
|
||||
title: "ضمانت اصالت کالا",
|
||||
desc: "تضمین اورجینال بودن محصولات",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
const tabs = ["پرفروشترینها", "تخفیفدار", "جدیدترینها"];
|
||||
|
||||
|
||||
const faqs = [
|
||||
{
|
||||
question: "آیا تمامی قطعات دارای ضمانت اصالت هستند؟",
|
||||
answer:
|
||||
"بله، تمامی محصولات ارائه شده دارای ضمانت اصالت کالا بوده و از برندهای معتبر جهانی تأمین میشوند.",
|
||||
},
|
||||
{
|
||||
question: "امکان صدور فاکتور رسمی برای شرکتها وجود دارد؟",
|
||||
answer:
|
||||
"بله، برای تمامی سفارشات امکان صدور فاکتور رسمی وجود دارد.",
|
||||
},
|
||||
{
|
||||
question: "سفارشها چه زمانی ارسال میشوند؟",
|
||||
answer:
|
||||
"سفارشها در سریعترین زمان ممکن پردازش شده و از طریق روشهای ارسال معتبر ارسال میشوند.",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
export default function Home() {
|
||||
@@ -68,26 +24,52 @@ export default function Home() {
|
||||
const brands = ["NTN", "KOYO", "NACHI", "TIMKEN", "FAG", "SKF"];
|
||||
const latestArticles = articles.slice(-4);
|
||||
const { rootCategories } = useCategories();
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: Headphones,
|
||||
title: "مشاوره فنی رایگان",
|
||||
desc: "انتخاب بهترین قطعه با توجه به نیاز شما",
|
||||
},
|
||||
{
|
||||
icon: FileText,
|
||||
title: "فاکتور رسمی",
|
||||
desc: "صدور فاکتور برای شرکتها",
|
||||
},
|
||||
{
|
||||
icon: Truck,
|
||||
title: "ارسال فوری",
|
||||
desc: "ارسال در سریعترین زمان ممکن",
|
||||
},
|
||||
{
|
||||
icon: ShieldCheck,
|
||||
title: "ضمانت اصالت کالا",
|
||||
desc: "تضمین اورجینال بودن محصولات",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
const tabs = ["پرفروشترینها", "تخفیفدار", "جدیدترینها"];
|
||||
|
||||
|
||||
const faqs = [
|
||||
{
|
||||
question: "آیا تمامی قطعات دارای ضمانت اصالت هستند؟",
|
||||
answer:
|
||||
"بله، تمامی محصولات ارائه شده دارای ضمانت اصالت کالا بوده و از برندهای معتبر جهانی تأمین میشوند.",
|
||||
},
|
||||
{
|
||||
question: "امکان صدور فاکتور رسمی برای شرکتها وجود دارد؟",
|
||||
answer:
|
||||
"بله، برای تمامی سفارشات امکان صدور فاکتور رسمی وجود دارد.",
|
||||
},
|
||||
{
|
||||
question: "سفارشها چه زمانی ارسال میشوند؟",
|
||||
answer:
|
||||
"سفارشها در سریعترین زمان ممکن پردازش شده و از طریق روشهای ارسال معتبر ارسال میشوند.",
|
||||
},
|
||||
];
|
||||
|
||||
// const uniqueCategories = Array.from(new Set(products.map((p) => p.category)));
|
||||
// const getCategoryIcon = (categoryName: string) => {
|
||||
// switch (categoryName) {
|
||||
// case "شیار عمیق":
|
||||
// return CircleDashed;
|
||||
// case "مخروطی":
|
||||
// return Disc;
|
||||
// case "شبکه ای":
|
||||
// return Hexagon;
|
||||
// case "سوزنی":
|
||||
// return Settings;
|
||||
// case "یاتاقان":
|
||||
// return Wrench;
|
||||
// case "گریس و روانکار":
|
||||
// return Droplets;
|
||||
// default:
|
||||
// return Settings; // آیکون پیشفرض
|
||||
// }
|
||||
// };
|
||||
|
||||
const categoryIcons = [
|
||||
CircleDashed,
|
||||
@@ -241,7 +223,7 @@ export default function Home() {
|
||||
{/* cards */}
|
||||
<div className="grid justify-center grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-6">
|
||||
|
||||
|
||||
|
||||
|
||||
{rootCategories.map((cat, index) => {
|
||||
const Icon = categoryIcons[index % categoryIcons.length];
|
||||
@@ -254,7 +236,7 @@ export default function Home() {
|
||||
>
|
||||
<Icon size={34} strokeWidth={1} className="text-gray-400 mb-3 group-hover:text-blue-500 transition-colors" />
|
||||
<span className="text-sm font-medium text-gray-700 group-hover:text-blue-600">{cat.name}</span>
|
||||
|
||||
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -40,6 +40,13 @@ export function Header() {
|
||||
const [registerError, setRegisterError] = useState("");
|
||||
const [loginError, setLoginError] = useState("");
|
||||
const { rootCategories } = useCategories();
|
||||
const [user, setUser] = useState<{ username: string } | null>(null);
|
||||
const [userMenuOpen, setUserMenuOpen] = useState(false);
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [showLoginPassword, setShowLoginPassword] = useState(false);
|
||||
|
||||
|
||||
|
||||
const [loginForm, setLoginForm] = useState({
|
||||
username: "",
|
||||
password: "",
|
||||
@@ -59,6 +66,17 @@ export function Header() {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem("accessToken");
|
||||
const username = localStorage.getItem("username");
|
||||
|
||||
if (token && username) {
|
||||
setUser({ username });
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
const handleRegister = async () => {
|
||||
|
||||
setRegisterError("");
|
||||
@@ -84,12 +102,19 @@ export function Header() {
|
||||
};
|
||||
|
||||
const res = await registerUser(payload);
|
||||
const role = res.data?.user?.role;
|
||||
|
||||
localStorage.setItem("accessToken", res.data.accessToken);
|
||||
localStorage.setItem("refreshToken", res.data.refreshToken);
|
||||
localStorage.setItem("username", username);
|
||||
localStorage.setItem("role", role.toLowerCase());
|
||||
console.log(res);
|
||||
|
||||
|
||||
setUser({ username });
|
||||
setIsOpen(false);
|
||||
router.push("/dashboard");
|
||||
router.push("/dashboard?success=register");
|
||||
|
||||
|
||||
} catch (error: any) {
|
||||
|
||||
@@ -126,11 +151,16 @@ export function Header() {
|
||||
|
||||
try {
|
||||
const res = await loginUser({ username, password });
|
||||
|
||||
const role = res.data?.user?.role;
|
||||
localStorage.setItem("role", role.toLowerCase());
|
||||
localStorage.setItem("accessToken", res.data.accessToken);
|
||||
localStorage.setItem("refreshToken", res.data.refreshToken);
|
||||
localStorage.setItem("username", username);
|
||||
console.log(res);
|
||||
setUser({ username });
|
||||
setIsOpen(false);
|
||||
router.push("/dashboard");
|
||||
router.push("/dashboard?success=login");
|
||||
|
||||
|
||||
} catch (error: any) {
|
||||
const msg = error?.message?.toLowerCase() || "";
|
||||
@@ -162,6 +192,16 @@ export function Header() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleLogout = () => {
|
||||
localStorage.removeItem("accessToken");
|
||||
localStorage.removeItem("refreshToken");
|
||||
localStorage.removeItem("username");
|
||||
localStorage.removeItem("role");
|
||||
|
||||
setUser(null);
|
||||
router.push("/");
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -467,15 +507,52 @@ export function Header() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => setIsOpen(true)}
|
||||
className="flex cursor-pointer items-center gap-2 px-3 py-2.5 bg-white border border-gray-300/60 rounded-xl text-xs text-gray-700 hover:bg-gray-50 transition"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" className="w-4 h-4 text-gray-500">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.5 20.25a7.5 7.5 0 0115 0" />
|
||||
</svg>
|
||||
<span>ورود / عضویت</span>
|
||||
</button>
|
||||
{!user ? (
|
||||
<button
|
||||
onClick={() => setIsOpen(true)}
|
||||
className="flex cursor-pointer items-center gap-2 px-3 py-2.5 bg-white border border-gray-300/60 rounded-xl text-xs text-gray-700 hover:bg-gray-50 transition"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" className="w-4 h-4 text-gray-500">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.5 20.25a7.5 7.5 0 0115 0" />
|
||||
</svg>
|
||||
|
||||
<span>ورود / عضویت</span>
|
||||
</button>
|
||||
) : (
|
||||
<div className="relative" onClick={() => setUserMenuOpen(!userMenuOpen)}
|
||||
>
|
||||
<button
|
||||
className="flex cursor-pointer items-center gap-2 px-3 py-2.5 bg-white border border-gray-300/60 rounded-xl text-xs text-gray-700 hover:bg-gray-50 transition"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-gray-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.8} d="M5.121 17.804A9 9 0 1118.879 17.804M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
|
||||
<span>{user.username}</span>
|
||||
</button>
|
||||
|
||||
{userMenuOpen && (
|
||||
<div className="absolute left-0 mt-2 w-40 bg-white border border-gray-200 rounded-xl shadow-lg p-2 text-xs">
|
||||
|
||||
<button
|
||||
onClick={() => router.push("/dashboard")}
|
||||
className="w-full cursor-pointer text-right px-3 py-2 rounded-lg hover:bg-gray-100"
|
||||
>
|
||||
داشبورد
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
className="w-full cursor-pointer text-right px-3 py-2 rounded-lg text-red-500 hover:bg-red-50"
|
||||
>
|
||||
خروج
|
||||
</button>
|
||||
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{isOpen && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-[#1A2332]/40 backdrop-blur-sm transition-opacity" dir="rtl">
|
||||
@@ -542,7 +619,7 @@ export function Header() {
|
||||
|
||||
<button
|
||||
onClick={() => setFormType("password")}
|
||||
className="w-full text-xs text-gray-500 hover:text-[#1A2332]"
|
||||
className="w-full cursor-pointer text-xs text-gray-500 hover:text-[#1A2332]"
|
||||
>
|
||||
ورود با نام کاربری و رمز عبور
|
||||
</button>
|
||||
@@ -567,18 +644,45 @@ export function Header() {
|
||||
className="w-full px-4 py-3.5 bg-gray-50 border border-gray-200 rounded-2xl text-sm text-right focus:outline-none focus:border-[#ffb900]"
|
||||
/>
|
||||
|
||||
<input
|
||||
type="password"
|
||||
value={loginForm.password}
|
||||
onChange={(e) =>
|
||||
setLoginForm((prev) => ({
|
||||
...prev,
|
||||
password: e.target.value,
|
||||
}))
|
||||
}
|
||||
placeholder="رمز عبور"
|
||||
className="w-full px-4 py-3.5 bg-gray-50 border border-gray-200 rounded-2xl text-sm text-right focus:outline-none focus:border-[#ffb900]"
|
||||
/>
|
||||
|
||||
<div className="relative w-full">
|
||||
<input
|
||||
type={showLoginPassword ? "text" : "password"} // تغییر نوع بر اساس state
|
||||
value={loginForm.password}
|
||||
onChange={(e) =>
|
||||
setLoginForm((prev) => ({
|
||||
...prev,
|
||||
password: e.target.value,
|
||||
}))
|
||||
}
|
||||
placeholder="رمز عبور"
|
||||
className="w-full px-4 pl-4 py-3.5 bg-gray-50 border border-gray-200 rounded-2xl text-sm text-right focus:outline-none focus:border-[#ffb900]"
|
||||
/>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowLoginPassword(!showLoginPassword)}
|
||||
className="absolute cursor-pointer left-4 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-700 p-1" // پدینگ اضافه شد تا کلیک راحتتر باشد
|
||||
>
|
||||
{showLoginPassword ? (
|
||||
// آیکون چشم خط خورده (eye-off)
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="w-5 h-5" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor" strokeWidth="1.8">
|
||||
<path strokeLinecap="round" strokeLinejoin="round"
|
||||
d="M3 3l18 18M10.477 10.477A3 3 0 0113.5 13.5m-7.09-2.664A9.956 9.956 0 003 12s2.91-6 9-6a9.953 9.953 0 016.328 2.318M15.54 15.54A9.953 9.953 0 0112 18c-6.09 0-9-6-9-6a9.956 9.956 0 012.41-3.868" />
|
||||
</svg>
|
||||
) : (
|
||||
// آیکون چشم باز (eye)
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="w-5 h-5" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor" strokeWidth="1.8">
|
||||
<path strokeLinecap="round" strokeLinejoin="round"
|
||||
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.477 0 8.268 2.943 9.542 7-1.274 4.057-5.065 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round"
|
||||
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button onClick={handleLogin} className="w-full cursor-pointer py-3.5 bg-[#ffb900] hover:bg-[#e5a600] text-[#1A2332] font-semibold rounded-2xl text-sm">
|
||||
ورود
|
||||
@@ -591,7 +695,7 @@ export function Header() {
|
||||
|
||||
<button
|
||||
onClick={() => setFormType("mobile")}
|
||||
className="w-full text-xs text-gray-500 hover:text-[#1A2332]"
|
||||
className="w-full cursor-pointer text-xs text-gray-500 hover:text-[#1A2332]"
|
||||
>
|
||||
ورود با شماره موبایل
|
||||
</button>
|
||||
@@ -631,13 +735,41 @@ export function Header() {
|
||||
placeholder="نام کاربری"
|
||||
className='w-full px-4 py-3.5 bg-gray-50 border border-gray-200 rounded-2xl text-sm text-right focus:outline-none focus:border-[#ffb900]'
|
||||
/>
|
||||
<input
|
||||
name="password"
|
||||
value={registerForm.password}
|
||||
onChange={handleChange} type="password"
|
||||
placeholder="رمز عبور"
|
||||
className="w-full px-4 py-3.5 bg-gray-50 border border-gray-200 rounded-2xl text-sm text-right focus:outline-none focus:border-[#ffb900]"
|
||||
/>
|
||||
<div className="relative w-full">
|
||||
<input
|
||||
name="password"
|
||||
value={registerForm.password}
|
||||
onChange={handleChange}
|
||||
type={showPassword ? "text" : "password"}
|
||||
placeholder="رمز عبور"
|
||||
className="w-full px-4 py-3.5 bg-gray-50 border border-gray-200 rounded-2xl text-sm text-right focus:outline-none focus:border-[#ffb900]"
|
||||
/>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
className="absolute cursor-pointer left-4 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-700"
|
||||
>
|
||||
{showPassword ? (
|
||||
// eye-off icon
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="w-5 h-5" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor" strokeWidth="1.8">
|
||||
<path strokeLinecap="round" strokeLinejoin="round"
|
||||
d="M3 3l18 18M10.477 10.477A3 3 0 0113.5 13.5m-7.09-2.664A9.956 9.956 0 003 12s2.91-6 9-6a9.953 9.953 0 016.328 2.318M15.54 15.54A9.953 9.953 0 0112 18c-6.09 0-9-6-9-6a9.956 9.956 0 012.41-3.868" />
|
||||
</svg>
|
||||
) : (
|
||||
// eye icon
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="w-5 h-5" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor" strokeWidth="1.8">
|
||||
<path strokeLinecap="round" strokeLinejoin="round"
|
||||
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.477 0 8.268 2.943 9.542 7-1.274 4.057-5.065 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round"
|
||||
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
{/* <input
|
||||
name="confirmPassword"
|
||||
|
||||
@@ -7,4 +7,4 @@ export interface ApiResponse<T> {
|
||||
timestamp: string;
|
||||
data: T; // دیتای اصلی که در هر API فرق میکند اینجا قرار میگیرد
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user