Auth Modal / All Cart API's Done and Local storage Logic handle / Add cart Control button
This commit is contained in:
@@ -12,6 +12,7 @@ import { loginUser } from '@/public/src/services/auth/api';
|
||||
import { logoutUser } from '@/public/src/services/auth/api';
|
||||
import { useCategories } from './context/categoryprovider';
|
||||
import { getCartApi } from '@/public/src/services/cart/api';
|
||||
import AuthModal from './Auth';
|
||||
|
||||
const topBarLinks = [
|
||||
{ label: "بخش صنعتی", href: "/" },
|
||||
@@ -109,6 +110,7 @@ const dashboardMenuItems = [
|
||||
|
||||
export function Header() {
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const [isAuthModalOpen, setIsAuthModalOpen] = useState(false);
|
||||
const pathname = usePathname();
|
||||
const { cart, removeFromCart } = useCart();
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
@@ -131,8 +133,8 @@ export function Header() {
|
||||
const [loginMobile, setLoginMobile] = useState("");
|
||||
const [showRegisterSuccessDialog, setShowRegisterSuccessDialog] = useState(false);
|
||||
const [isOptimistic, setIsOptimistic] = useState(false);
|
||||
// ۱. افکت اول: وقتی کانتکست لوکال (cart) با کلیک کاربر آپدیت میشود،
|
||||
// منو را به حالت Optimistic میبریم تا تغییرات را درجا نشان دهد.
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
setIsOptimistic(true);
|
||||
// بعد از ۱.۵ ثانیه (زمانی که قاعدتاً API سرور کارش تمام شده) به حالت عادی برمیگردد
|
||||
@@ -366,13 +368,10 @@ export function Header() {
|
||||
} finally {
|
||||
clearAuthState();
|
||||
setUserMenuOpen(false);
|
||||
router.push("/");
|
||||
window.location.href = "/";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
const parsePrice = (priceStr?: number | null) => {
|
||||
if (!priceStr) return 0;
|
||||
return Number(priceStr.toString().replace(/,/g, ''));
|
||||
@@ -420,41 +419,6 @@ export function Header() {
|
||||
const [serverCartItems, setServerCartItems] = useState<any[]>([]);
|
||||
const [serverSummary, setServerSummary] = useState<any>(null);
|
||||
|
||||
// // درون کامپوننت هدر شما
|
||||
// useEffect(() => {
|
||||
// const fetchServerData = async () => {
|
||||
// const token = localStorage.getItem('accessToken');
|
||||
// if (token) {
|
||||
// setIsLoggedIn(true);
|
||||
// try {
|
||||
// const data = await getCartApi();
|
||||
// if (data) {
|
||||
// setServerCartItems(data.items || []);
|
||||
// setServerSummary(data.summary || null);
|
||||
// }
|
||||
// } catch (error) {
|
||||
// console.error("خطا در همگامسازی سبد خرید سرور:", error);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// // --- این تابع جدید را اضافه کنید ---
|
||||
// const handleCartClear = () => {
|
||||
// setServerCartItems([]); // درجا لیست منو را خالی میکند
|
||||
// setServerSummary(null);
|
||||
// };
|
||||
|
||||
// // گوش دادن به رویدادها
|
||||
// window.addEventListener('cartUpdated', fetchServerData);
|
||||
// window.addEventListener('cartCleared', handleCartClear); // لیسنر جدید
|
||||
|
||||
// fetchServerData();
|
||||
|
||||
// return () => {
|
||||
// window.removeEventListener('cartUpdated', fetchServerData);
|
||||
// window.removeEventListener('cartCleared', handleCartClear); // کلینآپ لیسنر جدید
|
||||
// };
|
||||
// }, []);
|
||||
|
||||
|
||||
|
||||
@@ -478,15 +442,15 @@ export function Header() {
|
||||
setIsLoggedIn(false);
|
||||
}
|
||||
};
|
||||
// --- این تابع جدید را اضافه کنید ---
|
||||
const handleCartClear = () => {
|
||||
setServerCartItems([]); // درجا لیست منو را خالی میکند
|
||||
setServerSummary(null);
|
||||
};
|
||||
// گوش دادن به رویدادها
|
||||
window.addEventListener('cartUpdated', fetchServerCart);
|
||||
window.addEventListener('cartCleared', handleCartClear); // لیسنر جدید
|
||||
|
||||
// --- این تابع جدید را اضافه کنید ---
|
||||
const handleCartClear = () => {
|
||||
setServerCartItems([]); // درجا لیست منو را خالی میکند
|
||||
setServerSummary(null);
|
||||
};
|
||||
// گوش دادن به رویدادها
|
||||
window.addEventListener('cartUpdated', fetchServerCart);
|
||||
window.addEventListener('cartCleared', handleCartClear); // لیسنر جدید
|
||||
|
||||
fetchServerCart();
|
||||
return () => {
|
||||
window.removeEventListener('cartUpdated', fetchServerCart);
|
||||
@@ -495,32 +459,6 @@ export function Header() {
|
||||
// در صورت نیاز به آپدیت شدن دراپداون با هر تغییر، میتوانید این تابع را به یک Event یا Context متصل کنید
|
||||
}, []);
|
||||
|
||||
// --- متغیرهای هوشمند برای جایگزینی در UI ---
|
||||
// const displayCart = isLoggedIn
|
||||
// ? serverCartItems.map(item => ({
|
||||
// id: item.product?.id || item.productId,
|
||||
// title: item.product?.title || "بدون نام",
|
||||
// brand: item.product?.brand || "متفرقه",
|
||||
// price: item.unitPrice || item.product?.price || 0,
|
||||
// quantity: item.quantity || 1,
|
||||
// image: item.product?.mainImageUrl || item.product?.image || "/placeholder.png"
|
||||
// }))
|
||||
// : cart; // cart از useCart() میآید
|
||||
|
||||
// const displayTotalQuantity = isLoggedIn && serverSummary
|
||||
// ? serverSummary.totalQuantity || serverSummary.itemsCount || 0
|
||||
// : cart.reduce((total, item) => total + item.quantity, 0);
|
||||
|
||||
// const displayTotalPrice = isLoggedIn && serverSummary
|
||||
// ? serverSummary.totalPrice || serverSummary.total || 0
|
||||
// : totalPrice;
|
||||
|
||||
|
||||
|
||||
|
||||
// --- متغیرهای هوشمند اصلاح شده ---
|
||||
// اگر لاگین باشیم و در لحظهی کلیک (Optimistic) نباشیم، دیتای سرور را نشان میدهد
|
||||
// در غیر این صورت (برای نمایش آنی) دیتای لوکال را نشان میدهد.
|
||||
const displayCart = (isLoggedIn && !isOptimistic)
|
||||
? serverCartItems.map(item => ({
|
||||
id: item.product?.id || item.productId,
|
||||
@@ -805,7 +743,8 @@ export function Header() {
|
||||
|
||||
{!user ? (
|
||||
<button
|
||||
onClick={() => setIsOpen(true)}
|
||||
// onClick={() => setIsOpen(true)}
|
||||
onClick={() => setIsAuthModalOpen(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">
|
||||
@@ -867,6 +806,17 @@ export function Header() {
|
||||
)}
|
||||
|
||||
|
||||
{/* فراخوانی مودال احراز هویت */}
|
||||
<AuthModal
|
||||
isOpen={isAuthModalOpen}
|
||||
onClose={() => setIsAuthModalOpen(false)}
|
||||
onLoginSuccess={(userData) => setUser(userData)}
|
||||
onRegisterSuccess={(userData) => {
|
||||
setUser(userData);
|
||||
setShowRegisterSuccessDialog(true);
|
||||
}}
|
||||
/>
|
||||
{/*
|
||||
{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">
|
||||
|
||||
@@ -877,7 +827,6 @@ export function Header() {
|
||||
|
||||
<div className="relative w-full max-w-sm bg-white rounded-3xl shadow-2xl p-8">
|
||||
|
||||
{/* دکمه بستن */}
|
||||
<button
|
||||
onClick={() => setIsOpen(false)}
|
||||
className="absolute cursor-pointer top-4 left-5 text-gray-400 hover:text-gray-700 transition"
|
||||
@@ -887,7 +836,6 @@ export function Header() {
|
||||
|
||||
<div className="flex flex-col items-center mt-2 w-full">
|
||||
|
||||
{/* Tabs */}
|
||||
<div className="flex w-full bg-gray-100 rounded-xl p-1 mb-6">
|
||||
<button
|
||||
onClick={() => setActiveTab("login")}
|
||||
@@ -911,7 +859,6 @@ export function Header() {
|
||||
|
||||
</div>
|
||||
|
||||
{/* ---------------- LOGIN ---------------- */}
|
||||
|
||||
{activeTab === "login" && (
|
||||
<div className="w-full space-y-5">
|
||||
@@ -1046,7 +993,6 @@ export function Header() {
|
||||
{false && activeTab === "login" && (
|
||||
<div className="w-full">
|
||||
|
||||
{/* فرم موبایل */}
|
||||
{formType === "mobile" && (
|
||||
<div className="w-full space-y-4">
|
||||
|
||||
@@ -1070,7 +1016,6 @@ export function Header() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* فرم یوزر پس */}
|
||||
{formType === "password" && (
|
||||
<div className="w-full space-y-4">
|
||||
|
||||
@@ -1108,14 +1053,12 @@ export function Header() {
|
||||
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"
|
||||
@@ -1149,7 +1092,6 @@ export function Header() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ---------------- REGISTER ---------------- */}
|
||||
{activeTab === "register" && (
|
||||
<div className="w-full space-y-4">
|
||||
<div className="rounded-2xl border border-gray-200 bg-gray-50 px-4 py-4 text-right">
|
||||
@@ -1298,14 +1240,12 @@ export function Header() {
|
||||
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"
|
||||
@@ -1317,16 +1257,6 @@ export function Header() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
{/* <input
|
||||
name="confirmPassword"
|
||||
value={registerForm.confirmPassword}
|
||||
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]"
|
||||
/> */}
|
||||
|
||||
<button
|
||||
onClick={handleRegister}
|
||||
className="w-full cursor-pointer py-3.5 bg-[#ffb900] hover:bg-[#e5a600] text-[#1A2332] font-semibold rounded-2xl text-sm"
|
||||
@@ -1347,7 +1277,7 @@ export function Header() {
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)}
|
||||
)} */}
|
||||
|
||||
{showRegisterSuccessDialog && (
|
||||
<div className="fixed inset-0 z-[60] flex items-center justify-center bg-[#1A2332]/45 p-4 backdrop-blur-sm" dir="rtl">
|
||||
|
||||
Reference in New Issue
Block a user