'use client'; import React, { useEffect, useMemo, useState } from 'react'; import { User, Crown, Home, ShoppingBag, Wallet, MapPin, Headphones, IdCard, LogOut, TrendingUp, Plus, Hash, Clock, AlertCircle, Eye, Reply, CreditCard, Box, Shield, ShieldAlert, Mail, CheckCircle, ShieldX, CircleCheck, Search, Send, X, LoaderCircle } from 'lucide-react'; import { useRouter } from "next/navigation"; import { logoutUser } from "@/public/src/services/auth/api"; import { closeUserTicket, createUserTicket, getAdminTicketById, getAdminTickets, getUserTicketById, getUserTickets, sendAdminTicketMessage, sendUserTicketMessage, TicketDetail, TicketListItem, TicketPriority, TicketStatus, updateAdminTicket, } from "@/public/src/services/tickets/api"; import NotLogin from '@/components/Notlogin'; const sampleOrders = [ { id: "PR-10452", status: "در حال پردازش", statusColor: "amber", total: "500,000", regDate: "15 دی 1404", deliveryDate: "20 دی 1404", delivered: false }, { id: "PR-10451", status: "تحویل شده", statusColor: "green", total: "120,000", regDate: "10 دی 1404", deliveryDate: "12 دی 1404", delivered: true }, ]; const sampleAddresses = [ { id: "addr1", text: "شیراز، بلوار معالی آباد، خیابان پزشکان، ساختمان پارس، واحد 4", receiver: "علی محمدی", phone: "09123456789", isDefault: true }, { id: "addr2", text: "تهران، خیابان سعدی جنوبی، کوچه ناظم‌الاطباء، پلاک 20", receiver: "دفتر تهران", phone: "021-33900000", isDefault: false }, ]; const statusLabels: Record = { waiting_for_admin: "در انتظار پاسخ پشتیبانی", waiting_for_user: "در انتظار پاسخ کاربر", closed: "بسته شده", }; const priorityLabels: Record = { low: "کم", normal: "عادی", high: "زیاد", urgent: "فوری", }; type TicketCounts = { total: number; waiting_for_admin: number; waiting_for_user: number; closed: number; }; export default function DashboardPage() { const [activeTab, setActiveTab] = useState('dash'); const router = useRouter(); const [success, setSuccess] = useState<"" | "login" | "register">(""); const [authorized, setAuthorized] = useState(null); const [token, setToken] = useState(""); const [userInfo, setUserInfo] = useState({ fullName: "کاربر پارس شاپ", username: "user", phone: "شماره ثبت نشده", role: "user" as "user" | "admin", }); const [ticketCounts, setTicketCounts] = useState({ total: 0, waiting_for_admin: 0, waiting_for_user: 0, closed: 0, }); const [userTickets, setUserTickets] = useState([]); const [userTicketsLoading, setUserTicketsLoading] = useState(false); const [userTicketsError, setUserTicketsError] = useState(""); const [selectedUserTicketId, setSelectedUserTicketId] = useState(""); const [selectedUserTicket, setSelectedUserTicket] = useState(null); const [ticketDetailLoading, setTicketDetailLoading] = useState(false); const [ticketReply, setTicketReply] = useState(""); const [ticketReplyLoading, setTicketReplyLoading] = useState(false); const [ticketStatusFilter, setTicketStatusFilter] = useState<"" | TicketStatus>(""); const [ticketPage, setTicketPage] = useState(1); const [ticketTotalPages, setTicketTotalPages] = useState(1); const [isCreateTicketOpen, setIsCreateTicketOpen] = useState(false); const [createTicketLoading, setCreateTicketLoading] = useState(false); const [createTicketError, setCreateTicketError] = useState(""); const [createTicketForm, setCreateTicketForm] = useState({ subject: "", priority: "normal" as TicketPriority, message: "", }); const [adminTickets, setAdminTickets] = useState([]); const [adminTicketsLoading, setAdminTicketsLoading] = useState(false); const [adminTicketsError, setAdminTicketsError] = useState(""); const [adminStatusFilter, setAdminStatusFilter] = useState<"" | TicketStatus>(""); const [adminPriorityFilter, setAdminPriorityFilter] = useState<"" | TicketPriority>(""); const [adminSearch, setAdminSearch] = useState(""); const [adminPage, setAdminPage] = useState(1); const [adminTotalPages, setAdminTotalPages] = useState(1); const [selectedAdminTicketId, setSelectedAdminTicketId] = useState(""); const [selectedAdminTicket, setSelectedAdminTicket] = useState(null); const [adminReply, setAdminReply] = useState(""); const [adminReplyLoading, setAdminReplyLoading] = useState(false); const [adminUpdateLoading, setAdminUpdateLoading] = useState(false); const [adminTicketForm, setAdminTicketForm] = useState({ status: "waiting_for_user" as TicketStatus, priority: "normal" as TicketPriority, assignedAdminId: "", }); const ticketStatValue = useMemo(() => `${ticketCounts.total.toLocaleString('fa-IR')} مورد`, [ticketCounts.total]); useEffect(() => { const token = localStorage.getItem("accessToken"); const role = localStorage.getItem("role"); const params = new URLSearchParams(window.location.search); const currentTab = params.get("tab"); const currentSuccess = params.get("success"); if (currentTab && ['dash', 'orders', 'wallet', 'address', 'tickets', 'profile'].includes(currentTab)) { setActiveTab(currentTab); } if (currentSuccess === "login" || currentSuccess === "register") { setSuccess(currentSuccess); } if (token && (role === "user" || role === "admin")) { setToken(token); setUserInfo({ fullName: localStorage.getItem("fullName") || localStorage.getItem("username") || "کاربر پارس شاپ", username: localStorage.getItem("username") || "user", phone: localStorage.getItem("phone") || "شماره ثبت نشده", role: role, }); setAuthorized(true); } else { setAuthorized(false); } }, []); useEffect(() => { if (!token) { return; } loadTicketCounts(); }, [token, userInfo.role]); useEffect(() => { if (!token || activeTab !== 'tickets') { return; } if (userInfo.role === "admin") { loadAdminTickets(); return; } loadUserTickets(); }, [token, activeTab, userInfo.role, ticketStatusFilter, ticketPage, adminStatusFilter, adminPriorityFilter, adminSearch, adminPage]); useEffect(() => { if (!token) { return; } if (userInfo.role === "admin") { if (selectedAdminTicketId) { loadAdminTicketDetail(selectedAdminTicketId); } return; } if (selectedUserTicketId) { loadUserTicketDetail(selectedUserTicketId); } }, [token, userInfo.role, selectedUserTicketId, selectedAdminTicketId]); const handleLogout = async () => { const token = localStorage.getItem("accessToken"); try { if (token) { await logoutUser(token); } } catch (error) { console.error("Logout failed:", error); } finally { localStorage.removeItem("accessToken"); localStorage.removeItem("refreshToken"); localStorage.removeItem("username"); localStorage.removeItem("fullName"); localStorage.removeItem("phone"); localStorage.removeItem("role"); setAuthorized(false); router.push("/"); } }; const loadTicketCounts = async () => { try { if (userInfo.role === "admin") { const [allRes, adminWaitRes, userWaitRes, closedRes] = await Promise.all([ getAdminTickets(token, { page: 1, limit: 1 }), getAdminTickets(token, { status: "waiting_for_admin", page: 1, limit: 1 }), getAdminTickets(token, { status: "waiting_for_user", page: 1, limit: 1 }), getAdminTickets(token, { status: "closed", page: 1, limit: 1 }), ]); setTicketCounts({ total: allRes.pagination.total, waiting_for_admin: adminWaitRes.pagination.total, waiting_for_user: userWaitRes.pagination.total, closed: closedRes.pagination.total, }); return; } const [allRes, adminWaitRes, userWaitRes, closedRes] = await Promise.all([ getUserTickets(token, { page: 1, limit: 1 }), getUserTickets(token, { status: "waiting_for_admin", page: 1, limit: 1 }), getUserTickets(token, { status: "waiting_for_user", page: 1, limit: 1 }), getUserTickets(token, { status: "closed", page: 1, limit: 1 }), ]); setTicketCounts({ total: allRes.pagination.total, waiting_for_admin: adminWaitRes.pagination.total, waiting_for_user: userWaitRes.pagination.total, closed: closedRes.pagination.total, }); } catch (error) { console.error("Ticket count load failed:", error); } }; const loadUserTickets = async () => { setUserTicketsLoading(true); setUserTicketsError(""); try { const response = await getUserTickets(token, { status: ticketStatusFilter || undefined, page: ticketPage, limit: 10, }); setUserTickets(response.items); setTicketTotalPages(response.pagination.totalPages || 1); if (!selectedUserTicketId && response.items[0]) { setSelectedUserTicketId(response.items[0].id); } if (!response.items.length) { setSelectedUserTicketId(""); setSelectedUserTicket(null); } } catch (error: any) { setUserTicketsError(error?.message || "دریافت تیکت‌ها انجام نشد."); } finally { setUserTicketsLoading(false); } }; const loadUserTicketDetail = async (ticketId: string) => { setTicketDetailLoading(true); try { const detail = await getUserTicketById(token, ticketId); setSelectedUserTicket(detail); } catch (error) { console.error("User ticket detail failed:", error); } finally { setTicketDetailLoading(false); } }; const loadAdminTickets = async () => { setAdminTicketsLoading(true); setAdminTicketsError(""); try { const response = await getAdminTickets(token, { status: adminStatusFilter || undefined, priority: adminPriorityFilter || undefined, search: adminSearch || undefined, page: adminPage, limit: 10, }); setAdminTickets(response.items); setAdminTotalPages(response.pagination.totalPages || 1); if (!selectedAdminTicketId && response.items[0]) { setSelectedAdminTicketId(response.items[0].id); } if (!response.items.length) { setSelectedAdminTicketId(""); setSelectedAdminTicket(null); } } catch (error: any) { setAdminTicketsError(error?.message || "دریافت تیکت‌های ادمین انجام نشد."); } finally { setAdminTicketsLoading(false); } }; const loadAdminTicketDetail = async (ticketId: string) => { setTicketDetailLoading(true); try { const detail = await getAdminTicketById(token, ticketId); setSelectedAdminTicket(detail); setAdminTicketForm({ status: detail.status, priority: detail.priority, assignedAdminId: detail.assignedAdmin?.id || "", }); } catch (error) { console.error("Admin ticket detail failed:", error); } finally { setTicketDetailLoading(false); } }; const handleCreateTicket = async () => { if (!createTicketForm.subject.trim() || !createTicketForm.message.trim()) { setCreateTicketError("موضوع و متن پیام را کامل کنید."); return; } setCreateTicketLoading(true); setCreateTicketError(""); try { const detail = await createUserTicket(token, { subject: createTicketForm.subject.trim(), priority: createTicketForm.priority, message: createTicketForm.message.trim(), }); setIsCreateTicketOpen(false); setCreateTicketForm({ subject: "", priority: "normal", message: "" }); setSelectedUserTicketId(detail.id); setSelectedUserTicket(detail); setTicketPage(1); await Promise.all([loadUserTickets(), loadTicketCounts()]); } catch (error: any) { setCreateTicketError(error?.message || "ثبت تیکت انجام نشد."); } finally { setCreateTicketLoading(false); } }; const handleSendUserReply = async () => { if (!selectedUserTicket || !ticketReply.trim()) return; setTicketReplyLoading(true); try { const detail = await sendUserTicketMessage(token, selectedUserTicket.id, ticketReply.trim()); setSelectedUserTicket(detail); setTicketReply(""); await Promise.all([loadUserTickets(), loadTicketCounts()]); } catch (error) { console.error("User reply failed:", error); } finally { setTicketReplyLoading(false); } }; const handleCloseTicket = async () => { if (!selectedUserTicket) return; try { const detail = await closeUserTicket(token, selectedUserTicket.id); setSelectedUserTicket(detail); await Promise.all([loadUserTickets(), loadTicketCounts()]); } catch (error) { console.error("Close ticket failed:", error); } }; const handleAdminReply = async () => { if (!selectedAdminTicket || !adminReply.trim()) return; setAdminReplyLoading(true); try { const detail = await sendAdminTicketMessage(token, selectedAdminTicket.id, adminReply.trim()); setSelectedAdminTicket(detail); setAdminReply(""); await Promise.all([loadAdminTickets(), loadTicketCounts()]); } catch (error) { console.error("Admin reply failed:", error); } finally { setAdminReplyLoading(false); } }; const handleAdminUpdate = async () => { if (!selectedAdminTicket) return; setAdminUpdateLoading(true); try { const detail = await updateAdminTicket(token, selectedAdminTicket.id, { status: adminTicketForm.status, priority: adminTicketForm.priority, assignedAdminId: adminTicketForm.assignedAdminId.trim() || undefined, }); setSelectedAdminTicket(detail); await Promise.all([loadAdminTickets(), loadTicketCounts()]); } catch (error) { console.error("Admin update failed:", error); } finally { setAdminUpdateLoading(false); } }; const menuItems = [ { id: 'dash', label: 'پیشخوان', icon: Home }, { id: 'orders', label: 'سفارش‌های من', icon: ShoppingBag }, { id: 'wallet', label: 'کیف پول', icon: Wallet }, { id: 'address', label: 'آدرس‌ها', icon: MapPin }, { id: 'tickets', label: 'تیکت پشتیبانی', icon: Headphones }, { id: 'profile', label: 'مشخصات حساب', icon: IdCard }, ]; if (authorized === null) { return (

در حال بررسی دسترسی...

); } if (!authorized) { return (
); } return (
{success === "login" &&
ورود با موفقیت انجام شد
} {success === "register" &&
ثبت نام با موفقیت انجام شد
}
{activeTab === 'dash' && (

خوش آمدید

} color="bg-blue-50 text-blue-600" label="موجودی کیف پول" value="1,500,000 تومان" /> } color="bg-green-50 text-green-600" label="سفارشات جاری" value="2 مورد" /> } color="bg-orange-50 text-orange-600" label="تیکت‌ها" value={ticketStatValue} /> } color="bg-purple-50 text-purple-600" label="امتیاز وفاداری" value="2,340 امتیاز" />
)} {activeTab === 'tickets' && ( userInfo.role === "admin" ? ( { setAdminStatusFilter(value); setAdminPage(1); }} onPriorityFilterChange={(value) => { setAdminPriorityFilter(value); setAdminPage(1); }} onSearchChange={(value) => { setAdminSearch(value); setAdminPage(1); }} selectedTicketId={selectedAdminTicketId} onSelectTicket={setSelectedAdminTicketId} selectedTicket={selectedAdminTicket} detailLoading={ticketDetailLoading} reply={adminReply} onReplyChange={setAdminReply} onReplySubmit={handleAdminReply} replyLoading={adminReplyLoading} ticketForm={adminTicketForm} onTicketFormChange={setAdminTicketForm} onTicketUpdate={handleAdminUpdate} updateLoading={adminUpdateLoading} page={adminPage} totalPages={adminTotalPages} onPrevPage={() => setAdminPage((prev) => Math.max(1, prev - 1))} onNextPage={() => setAdminPage((prev) => Math.min(adminTotalPages, prev + 1))} /> ) : ( { setTicketStatusFilter(value); setTicketPage(1); }} selectedTicketId={selectedUserTicketId} onSelectTicket={setSelectedUserTicketId} selectedTicket={selectedUserTicket} detailLoading={ticketDetailLoading} reply={ticketReply} onReplyChange={setTicketReply} onReplySubmit={handleSendUserReply} replyLoading={ticketReplyLoading} onCloseTicket={handleCloseTicket} onOpenCreateTicket={() => setIsCreateTicketOpen(true)} page={ticketPage} totalPages={ticketTotalPages} onPrevPage={() => setTicketPage((prev) => Math.max(1, prev - 1))} onNextPage={() => setTicketPage((prev) => Math.min(ticketTotalPages, prev + 1))} /> ) )} {activeTab === 'address' && (
{sampleAddresses.map((address) => (
{address.text}
گیرنده: {address.receiver}
تماس: {address.phone}
))}
)} {activeTab === 'orders' && (
{sampleOrders.map((order) => (

{order.id}

ثبت سفارش: {order.regDate}

{order.status}
تاریخ ثبت: {order.regDate}
{order.delivered ? : }{order.delivered ? 'تحویل شده:' : 'تحویل تا:'} {order.deliveryDate}
مبلغ کل: {order.total} تومان
))}
)} {activeTab === 'wallet' && (
موجودی فعلی حساب شما:
1,500,000 تومان
)} {activeTab === 'profile' && (

اطلاعات شخصی

تغییر رمز عبور

آخرین تغییر: 2 ماه پیش

احراز هویت دو مرحله‌ای

وضعیت: غیرفعال

اطلاع‌رسانی ایمیلی

دریافت ایمیل برای هشدارهای امنیتی

)}
{isCreateTicketOpen && ( setIsCreateTicketOpen(false)} onSubmit={handleCreateTicket} loading={createTicketLoading} error={createTicketError} /> )}
); } function DashboardStat({ icon, color, label, value }: { icon: React.ReactNode; color: string; label: string; value: string }) { return (
{icon}

{label}

{value}
); } function TicketSummaryCard({ value, label, color }: { value: string; label: string; color: string }) { return (
{value}
{label}
); } function UserTicketsView(props: { tickets: TicketListItem[]; loading: boolean; error: string; counts: TicketCounts; statusFilter: "" | TicketStatus; onStatusFilterChange: (value: "" | TicketStatus) => void; selectedTicketId: string; onSelectTicket: (id: string) => void; selectedTicket: TicketDetail | null; detailLoading: boolean; reply: string; onReplyChange: (value: string) => void; onReplySubmit: () => void; replyLoading: boolean; onCloseTicket: () => void; onOpenCreateTicket: () => void; page: number; totalPages: number; onPrevPage: () => void; onNextPage: () => void; }) { return (

تیکت‌های پشتیبانی

props.onStatusFilterChange("")}>همه تیکت‌ها props.onStatusFilterChange("waiting_for_admin")}>در انتظار پشتیبانی props.onStatusFilterChange("waiting_for_user")}>در انتظار شما props.onStatusFilterChange("closed")}>بسته شده
{props.loading ? : props.error ? : props.tickets.length === 0 ? : ( <> {props.tickets.map((ticket) => ( ))} )}
{props.detailLoading ? : !props.selectedTicket ? : ( )}
); } function AdminTicketsView(props: { tickets: TicketListItem[]; loading: boolean; error: string; counts: TicketCounts; statusFilter: "" | TicketStatus; priorityFilter: "" | TicketPriority; search: string; onStatusFilterChange: (value: "" | TicketStatus) => void; onPriorityFilterChange: (value: "" | TicketPriority) => void; onSearchChange: (value: string) => void; selectedTicketId: string; onSelectTicket: (id: string) => void; selectedTicket: TicketDetail | null; detailLoading: boolean; reply: string; onReplyChange: (value: string) => void; onReplySubmit: () => void; replyLoading: boolean; ticketForm: { status: TicketStatus; priority: TicketPriority; assignedAdminId: string }; onTicketFormChange: React.Dispatch>; onTicketUpdate: () => void; updateLoading: boolean; page: number; totalPages: number; onPrevPage: () => void; onNextPage: () => void; }) { return (

مدیریت تیکت‌ها

props.onSearchChange(e.target.value)} placeholder="جستجو در موضوع یا شماره تیکت" className="w-full pr-10 px-4 py-3 border border-gray-200 rounded-xl text-sm outline-none focus:border-[#ffb900]" />
{props.loading ? : props.error ? : props.tickets.length === 0 ? : ( <> {props.tickets.map((ticket) => ( ))} )}
{props.detailLoading ? : !props.selectedTicket ? : ( <>
{props.selectedTicket.ticketNumber}

{props.selectedTicket.subject}

props.onTicketFormChange((prev) => ({ ...prev, assignedAdminId: e.target.value }))} placeholder="assignedAdminId" className="px-4 py-3 border border-gray-200 rounded-xl text-sm outline-none focus:border-[#ffb900]" />
)}
); } function ProfileField({ label, value }: { label: string; value: string }) { return (
{value}
); } function TicketConversationCard({ ticket, reply, onReplyChange, onReplySubmit, replyLoading, onCloseTicket, adminMode = false }: { ticket: TicketDetail; reply: string; onReplyChange: (value: string) => void; onReplySubmit: () => void; replyLoading: boolean; onCloseTicket?: () => void; adminMode?: boolean; }) { const closed = ticket.status === "closed"; return (
{ticket.ticketNumber}

{ticket.subject}

{!adminMode && onCloseTicket && (
)}
{ticket.messages.map((message) => (
{message.sender.fullName} • {message.senderType === 'user' ? 'کاربر' : 'پشتیبانی'}
{message.message}
{formatDateTime(message.createdAt)}
))}