"use client"; import React, { useState } from "react"; import { motion } from "motion/react"; import { User, ShoppingBag, Wallet, MapPin, LogOut, ChevronRight, Package, Calendar, UserCircle, ShoppingCart, Trash2, Edit2, Phone, Hash, CheckCircle2, ArrowUpCircle, ArrowDownCircle, Info, Clock, CheckCircle, Heart, Sparkles, MessageSquare, Send, Stethoscope, FileText } from "lucide-react"; import { OrderRowSkeleton } from "./Skeleton"; import { useUserStore, Address } from "../lib/store/userStore"; import { useCartStore } from "../lib/store/cartStore"; import { toPersian, toEnglishDigits, cn } from "../lib/utils"; import { toast } from "sonner"; import OrderDetailsModal from "./OrderDetailsModal"; import AddressModal from "./AddressModal"; import DeleteConfirmModal from "./DeleteConfirmModal"; import TopUpModal from "./TopUpModal"; import { useRouter } from 'next/navigation'; export default function UserDashboard() { const router = useRouter(); const { profile, isLoggedIn, logout, updateProfile, addAddress, updateAddress, deleteAddress, setDefaultAddress, topUpWallet } = useUserStore(); React.useEffect(() => { if (!isLoggedIn && typeof window !== "undefined") { router.push("/"); toast.error("برای دسترسی به داشبورد لطفاً ابتدا وارد حساب کاربری خود شوید."); } }, [isLoggedIn, router]); const { orders } = useCartStore(); const [activeTab, setActiveTab] = React.useState<"profile" | "orders" | "wallet" | "addresses" | "tickets">("profile"); const [isLoadingOrders, setIsLoadingOrders] = useState(false); // Fetch fresh profile data (which includes orders) whenever orders tab is opened React.useEffect(() => { if (activeTab === "orders") { let isSubscribed = true; Promise.resolve().then(() => { if (isSubscribed) setIsLoadingOrders(true); }); useUserStore.getState().fetchProfile().finally(() => { if (isSubscribed) setIsLoadingOrders(false); }); return () => { isSubscribed = false; }; } }, [activeTab]); const [selectedOrder, setSelectedOrder] = useState(null); // Address State const [isAddressModalOpen, setIsAddressModalOpen] = useState(false); const [editingAddress, setEditingAddress] = useState
(null); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [addressToDelete, setAddressToDelete] = useState
(null); // Wallet State const [isTopUpModalOpen, setIsTopUpModalOpen] = useState(false); // Profile State const [isEditing, setIsEditing] = useState(false); const [isSavingProfile, setIsSavingProfile] = useState(false); const [profileForm, setProfileForm] = useState(() => ({ firstName: profile.firstName || "", lastName: profile.lastName || "", email: profile.email || "", mobile: profile.mobile || "" })); // Sync profile data on change React.useEffect(() => { let isSubscribed = true; Promise.resolve().then(() => { if (isSubscribed) { setProfileForm({ firstName: profile.firstName || "", lastName: profile.lastName || "", email: profile.email || "", mobile: profile.mobile || "" }); } }); return () => { isSubscribed = false; }; }, [profile]); if (!isLoggedIn) { return null; } const handleSaveProfile = async (e: React.FormEvent) => { e.preventDefault(); setIsSavingProfile(true); try { const cleanPhone = toEnglishDigits(profileForm.mobile); await updateProfile({ firstName: profileForm.firstName, lastName: profileForm.lastName, email: profileForm.email, mobile: cleanPhone }); setIsEditing(false); toast.success("اطلاعات کاربری با موفقیت ویرایش شد"); } catch { toast.error("خطا در ویرایش اطلاعات"); } finally { setIsSavingProfile(false); } }; const handleLogout = () => { logout(); router.push('/'); }; const handleSaveAddress = async (addr: Address) => { try { if (editingAddress) { await updateAddress(addr.id, addr); } else { await addAddress(addr); } } catch { toast.error("خطا در ثبت آدرس"); } setEditingAddress(null); }; const handleDeleteClick = (addr: Address) => { setAddressToDelete(addr); setIsDeleteModalOpen(true); }; const handleConfirmDelete = async () => { if (addressToDelete) { try { await deleteAddress(addressToDelete.id); toast.success("آدرس با موفقیت حذف شد"); } catch { toast.error("خطا در حذف آدرس"); } setAddressToDelete(null); } }; const handleEditClick = (addr: Address) => { setEditingAddress(addr); setIsAddressModalOpen(true); }; const handleAddClick = () => { setEditingAddress(null); setIsAddressModalOpen(true); }; const tabs = [ { id: "profile", label: "اطلاعات فردی", icon: }, { id: "orders", label: "سفارشات من", icon: }, { id: "wallet", label: "کیف پول", icon: }, { id: "addresses", label: "آدرس‌ها", icon: }, { id: "tickets", label: "پشتیبانی و مشاوره", icon: }, ]; return (
{/* Breadcrumb */}
router.push('/')}>خانه پنل کاربری
{/* Top User Info & Navigation Tabs */}

{profile.firstName} {profile.lastName}

{profile.email}

{/* Tab Navigation */}
{tabs.map(tab => ( ))}
{/* Main Content Area */}
{activeTab === "profile" && (

اطلاعات فردی

setProfileForm({ ...profileForm, firstName: e.target.value })} className={cn( "w-full border p-4 rounded-2xl font-bold outline-none transition-all", isEditing ? "bg-white border-canina-blue/30 focus:ring-2 focus:ring-canina-blue/20" : "bg-medical-gray-50 border-medical-gray-100" )} />
setProfileForm({ ...profileForm, lastName: e.target.value })} className={cn( "w-full border p-4 rounded-2xl font-bold outline-none transition-all", isEditing ? "bg-white border-canina-blue/30 focus:ring-2 focus:ring-canina-blue/20" : "bg-medical-gray-50 border-medical-gray-100" )} />
setProfileForm({ ...profileForm, email: e.target.value })} className={cn( "w-full border p-4 rounded-2xl font-bold outline-none transition-all text-left", isEditing ? "bg-white border-canina-blue/30 focus:ring-2 focus:ring-canina-blue/20" : "bg-medical-gray-50 border-medical-gray-100" )} dir="ltr" />
setProfileForm({ ...profileForm, mobile: e.target.value.replace(/[^0-9]/g, '') })} className={cn( "w-full border p-4 rounded-2xl font-bold outline-none transition-all text-left", isEditing ? "bg-white border-canina-blue/30 focus:ring-2 focus:ring-canina-blue/20" : "bg-medical-gray-50 border-medical-gray-100 opacity-75 cursor-not-allowed" )} dir="ltr" />
{isEditing ? ( <> ) : ( )}
)} {activeTab === "orders" && (

تاریخچه سفارشات

تعداد کل: {toPersian((orders || []).length.toString())} مورد
{(orders || []).length === 0 ? (

هنوز سفارشی ثبت نکرده‌اید.

) : (
{isLoadingOrders ? ( [1, 2, 3].map(i => ) ) : ( (orders || []).map(order => ( setSelectedOrder(order)} className="p-6 border border-medical-gray-100 rounded-[2.5rem] hover:border-canina-blue transition-all group cursor-pointer bg-white overflow-hidden relative" >
سفارش {toPersian(order.trackingNumber || order.id?.substring(0, 8))}
{toPersian(new Date(order.date || (order as unknown as Record).createdAt || 0).toLocaleDateString("fa-IR"))} - ساعت {toPersian(new Date(order.date || (order as unknown as Record).createdAt || 0).toLocaleTimeString("fa-IR", { hour: '2-digit', minute: '2-digit' }))}
{toPersian(order.total.toLocaleString())} تومان
{order.isRefill && ( تمدید خودکار ۵٪- )} {order.status === 'delivered' ? 'تحویل شده' : order.status === 'shipped' ? 'ارسال شده' : 'در حال پردازش'}
)) )}
)}
)} {activeTab === "addresses" && (

آدرس‌های من

{(profile?.addresses || []).length === 0 ? (

هنوز آدرسی ثبت نکرده‌اید.

) : ( (profile?.addresses || []).map((addr) => (

{addr.title}

{addr.isDefault && ( پیش‌فرض )}

تحویل گیرنده: {addr.receptorName}

{toPersian(addr.province)}، {toPersian(addr.city)}، {toPersian(addr.detail)}

{toPersian(addr.phone)}
{toPersian(addr.zipCode)}
{!addr.isDefault && ( )} {addr.isDefault && (
آدرس اصلی ارسال
)}
)) )}
)} {activeTab === "wallet" && (

مدیریت کیف پول

حساب تایید شده
{/* Main Balance Card */}
موجودی زنده و قابل استفاده
{toPersian(profile.walletBalance.toLocaleString())}
تومان
{/* Transaction History */}

تاریخچه تراکنش‌ها

{(profile?.transactions || []).length === 0 ? (

تراکنشی یافت نشد.

) : ( (profile?.transactions || []).map((trx) => (
{trx.type === 'top_up' ? : }
{trx.type === 'top_up' ? "افزایش موجودی (شارژ)" : "پرداخت سفارش"}
کد: {trx.id} {toPersian(new Date(trx.date).toLocaleDateString("fa-IR"))}
{trx.type === 'top_up' ? "+" : ""}{toPersian(trx.amount.toLocaleString())} تومان
تایید شده
)) )}
)} {activeTab === "tickets" && (

پشتیبانی و مشاوره آنلاین دامپزشک

مشاوره دوز مکمل کانینوکال برای سگ ژرمن

شناسه تیکت: TK-۸۴۹۲ • پاسخ داده شده توسط دکتر صادقی

پاسخ داده شد

استعلام اصالت نسخه پزشکی و سفارش فوری

شناسه تیکت: TK-۸۴۱۰ • در حال بررسی توسط کارشناس دارویی

در حال بررسی
)}
{/* Sidebar Widgets (Wallet & Charity) */}
موجودی کیف پول
{toPersian((profile.walletBalance ?? 0).toLocaleString())}
تومان

ردپای مهربانی

مجموع کمک‌های اهدایی

{toPersian((Math.max(profile.charityDonationTotal || 0, orders.reduce((sum, o) => sum + Number(o.charityDonation || 0), 0))).toLocaleString())} تومان

همکاری شما باعث تامین هزینه {toPersian(Math.floor((profile.charityDonationTotal || 0) / 15000).toString())} وعده غذا برای حیوانات بی‌پناه شده است.

setSelectedOrder(null)} order={selectedOrder} /> setIsAddressModalOpen(false)} onSave={handleSaveAddress} editingAddress={editingAddress} /> setIsDeleteModalOpen(false)} onConfirm={handleConfirmDelete} title="حذف آدرس" message={`آیا از حذف آدرس "${addressToDelete?.title}" اطمینان دارید؟ این عمل غیرقابل بازگشت است.`} /> setIsTopUpModalOpen(false)} onConfirm={topUpWallet} />
); }