import React, { useState, useEffect, useMemo } from 'react' import { useParams, useNavigate, Link, Navigate } from 'react-router-dom' import { Ic, IconName } from '@/icons' import { Card, CardContent } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Badge } from '@/components/ui/badge' import { Shimmer } from '@/components/shared/shimmer_frontend' import { toFa } from '@/lib/utils' import { SimcardServiceView } from './components/SimcardServiceView' import { ZayerGuideServiceView } from './components/ZayerGuideServiceView' import { DuasServiceView } from './components/DuasServiceView' import { CategoriesServiceView } from './components/CategoriesServiceView' import { CitiesServiceView } from './components/CitiesServiceView' import { FaqServiceView } from './components/FaqServiceView' import { StoreServiceView } from './components/StoreServiceView' // تعریف ساختار داده‌های سرویس‌ها export interface ServiceMeta { key: string title: string titleEn: string icon: IconName color: string bgColor: string borderColor: string description: string endpoint: string statsLabel: string defaultCount: number badge: string } export const SERVICES_LIST: ServiceMeta[] = [ { key: 'simcard', title: 'سیم‌کارت', titleEn: 'Simcard', icon: 'simcard', color: 'text-primary', bgColor: 'bg-primary/10', borderColor: 'border-primary/20', description: 'مدیریت بسته‌های اینترنت، سیم‌کارت‌های بین‌المللی و سفارش‌های زائرین (ایران، عراق، عربستان سعودی)', endpoint: '/store/simcards/', statsLabel: 'بسته‌های فعال', defaultCount: 9, badge: 'ارتباطات و دیتا', }, { key: 'zayer-guide', title: 'راهنمای زائر', titleEn: 'Zayer Guide', icon: 'guide', color: 'text-primary', bgColor: 'bg-primary/10', borderColor: 'border-primary/20', description: 'بانک جامع اماکن متبرکه، راهنمای اماکن تاریخی، بیمارستان‌ها، مواکب و موقعیت مکانی شهرها', endpoint: '/cityguide/', statsLabel: 'مکان ثبت‌شده', defaultCount: 42, badge: 'اماکن و نقشه‌ها', }, { key: 'exchange', title: 'صرافی آنلاین و تشریفات', titleEn: 'Currency Exchange', icon: 'exchange', color: 'text-primary', bgColor: 'bg-primary/10', borderColor: 'border-primary/20', description: 'نرخ لحظه‌ای ارزهای زیارتی (دینار، ریال، دلار، لیر)، تبدیل آنلاین و سفارش تحویل وجه نقد در مقصد', endpoint: '/tasrif/orders/', statsLabel: 'سفارش تبدیل ارز', defaultCount: 19, badge: 'مالی و ارزی', }, { key: 'cities', title: 'شهرهای زیارتی', titleEn: 'Holy Cities', icon: 'map', color: 'text-primary', bgColor: 'bg-primary/10', borderColor: 'border-primary/20', description: 'فهرست استاتیک و رسمی شهرهای زیارتی اپلیکیشن عقیله به همراه شناسه‌های ثابت دیتابیس و دسته‌بندی‌های اعمال', endpoint: '/trip-etiquette/cities/', statsLabel: 'شهر زیارتی مرجع', defaultCount: 10, badge: 'استاتیک و مرجع', }, { key: 'duas', title: 'ادعیه و زیارات', titleEn: 'Duas & Ziyarat', icon: 'book', color: 'text-primary', bgColor: 'bg-primary/10', borderColor: 'border-primary/20', description: 'فهرست مستقیم ادعیه، تخصیص چندگانه به حرم‌ها، مدیریت متن عربی با اعراب و ترجمه‌های 5 زبانه', endpoint: '/trip-etiquette/duas/', statsLabel: 'دعا و زیارت ثبت‌شده', defaultCount: 4, badge: 'فرهنگی و معنوی', }, { key: 'categories', title: 'دسته‌بندی‌های ادعیه', titleEn: 'Dua Categories', icon: 'folder', color: 'text-primary', bgColor: 'bg-primary/10', borderColor: 'border-primary/20', description: 'تعریف و مدیریت پوشه‌ها و دسته‌بندی‌های ادعیه (مانند اعمال، آداب، زیارات) به تفکیک شهرها و تخصیص مستقیم ادعیه', endpoint: '/trip-etiquette/categories/', statsLabel: 'دسته‌بندی فعال', defaultCount: 6, badge: 'شهرها و پوشه‌ها', }, { key: 'store', title: 'فروشگاه معصومه', titleEn: 'Massoumah Store', icon: 'store', color: 'text-primary', bgColor: 'bg-primary/10', borderColor: 'border-primary/20', description: 'سوغات متبرک، ملزومات سفر اربعین و عتبات، کتب ادعیه، چفیه، سجاده و محصولات فرهنگی', endpoint: '/store/products/', statsLabel: 'محصول در انبار', defaultCount: 35, badge: 'فروشگاه و سوغات', }, { key: 'cost-estimate', title: 'تخمین هزینه سفر', titleEn: 'Cost Estimate', icon: 'calculator', color: 'text-primary', bgColor: 'bg-primary/10', borderColor: 'border-primary/20', description: 'سامانه هوشمند برآورد هزینه‌های اقامت، پرواز، ترانسفر و خوراک برای سفرهای انفرادی و گروهی', endpoint: '/cost-estimates/', statsLabel: 'آیتم محاسباتی', defaultCount: 14, badge: 'محاسبات و برآورد', }, { key: 'faq', title: 'سوالات متداول', titleEn: 'FAQ', icon: 'helpCircle', color: 'text-primary', bgColor: 'bg-primary/10', borderColor: 'border-primary/20', description: 'مدیریت جامع دسته‌بندی‌های موضوعی، پرسش و پاسخ‌ها، پشتیبانی کامل 5 زبانه و فعال/غیرفعال‌سازی نمایش در اپلیکیشن', endpoint: '/home/faq/categories/', statsLabel: 'دسته‌بندی فعال', defaultCount: 6, badge: 'پشتیبانی و راهنما', }, { key: 'consultant', title: 'پشتیبانی', titleEn: 'Support', icon: 'headset', color: 'text-primary', bgColor: 'bg-primary/10', borderColor: 'border-primary/20', description: 'شبکه کارشناسان تخصصی پزشکی سفر، احکام، امور حقوقی، گمشدگان و پشتیبانی 24 ساعته زائرین', endpoint: '/consultants/', statsLabel: 'کارشناس فعال', defaultCount: 12, badge: 'پشتیبانی زنده', }, ] export default function ServicesPage() { const { serviceKey, subKey } = useParams<{ serviceKey?: string; subKey?: string }>() // اگر مسیر /services/store بدون زیرمجموعه فراخوانی شد، به صفحه محصولات هدایت شود if (serviceKey === 'store' && !subKey) { return } const currentService = useMemo(() => { if (!serviceKey) return null const base = SERVICES_LIST.find((s) => s.key === serviceKey) if (!base) return null if (serviceKey === 'store' && subKey === 'categories') { return { ...base, title: 'دسته‌بندی‌های فروشگاه', titleEn: 'Store Categories', icon: 'folder' as const, description: 'مدیریت و ساماندهی دسته‌بندی‌های فعال فروشگاه، تعریف دسته‌بندی جدید و کنترل وضعیت نمایش در اپلیکیشن', } } if (serviceKey === 'store' && subKey === 'products') { return { ...base, title: 'محصولات فروشگاه معصومه', titleEn: 'Store Products', icon: 'store' as const, description: 'سوغات متبرک، ملزومات سفر اربعین و عتبات، کتب ادعیه، چفیه، سجاده و محصولات فرهنگی', } } return base }, [serviceKey, subKey]) if (!serviceKey || !currentService) { return } return (
{/* سربرگ بخش خدمات (برای شهرهای زیارتی به صورت یکپارچه داخل کامپوننت با دکمه لود مجدد مدیریت می‌شود) */} {serviceKey !== 'cities' && (

{currentService.title}

{currentService.titleEn}

{currentService.description}

{currentService.badge}
)} {/* رندرینگ محتوای اختصاصی سرویس مستقل */}
) } // ───────────────────────────────────────────────────────────────────────────── // رندرینگ محتوای اختصاصی هر سرویس بر اساس کلید آن // ───────────────────────────────────────────────────────────────────────────── function ServiceDetailRenderer({ service, subKey, }: { service: ServiceMeta subKey?: string }) { switch (service.key) { case 'simcard': return case 'zayer-guide': return case 'exchange': return case 'cities': return case 'duas': return case 'categories': return case 'shrines': return case 'trip-etiquette': return case 'consultant': return case 'faq': return case 'store': return ( ) case 'cost-estimate': return default: return
سرویس مورد نظر یافت نشد.
} } // ───────────────────────────────────────────────────────────────────────────── // ۳. صرافی آنلاین و تشریفات (Online Exchange) // ───────────────────────────────────────────────────────────────────────────── function ExchangeServiceView({ service }: { service: ServiceMeta }) { const [searchTerm, setSearchTerm] = useState('') const [statusFilter, setStatusFilter] = useState<'ALL' | 'CONFIRMED' | 'DONE' | 'PENDING'>('ALL') const rates = [ { pair: 'IRR / IQD', name: 'دینار عراق', rate: '0.021', change: '+1.2%', base: '100 هزار تومان = 2,100 دینار', flag: '🇮🇶' }, { pair: 'USD / IQD', name: 'دلار به دینار', rate: '1,530', change: '0.0%', base: '1 دلار آمریکا = 1,530 دینار', flag: '💵' }, { pair: 'IRR / SAR', name: 'ریال سعودی', rate: '0.000058', change: '-0.4%', base: '100 هزار تومان = 5.8 ریال سعودی', flag: '🇸🇦' }, { pair: 'USD / SAR', name: 'دلار به ریال', rate: '3.75', change: '0.0%', base: '1 دلار آمریکا = 3.75 ریال سعودی', flag: '🇸🇦' }, ] const recentOrders = [ { id: 981, user: 'محمد حسینی', from: '50,000,000 تومان', to: '1,050,000 دینار عراق', deliverType: 'تحویل نقدی در فرودگاه نجف', status: 'تایید شده و آماده تحویل', statusCode: 'CONFIRMED', date: '1403/07/08' }, { id: 982, user: 'علی کاظمی', from: '20,000,000 تومان', to: '420,000 دینار عراق', deliverType: 'حواله به کارت کی‌کارت عراق', status: 'انجام شد', statusCode: 'DONE', date: '1403/07/08' }, { id: 983, user: 'سارا احمدی', from: '100,000,000 تومان', to: '5,800 ریال سعودی', deliverType: 'تحویل نقدی در هتل مدینه', status: 'در حال بررسی', statusCode: 'PENDING', date: '1403/07/07' }, { id: 984, user: 'مهدی کریمی', from: '15,000,000 تومان', to: '315,000 دینار عراق', deliverType: 'تحویل نقدی در صحن حضرت زهرا (س)', status: 'انجام شد', statusCode: 'DONE', date: '1403/07/07' }, { id: 985, user: 'زهرا موسوی', from: '35,000,000 تومان', to: '2,030 ریال سعودی', deliverType: 'تحویل در فرودگاه جده', status: 'تایید شده و آماده تحویل', statusCode: 'CONFIRMED', date: '1403/07/06' }, ] const filteredOrders = useMemo(() => { return recentOrders.filter((ord) => { if (statusFilter !== 'ALL' && ord.statusCode !== statusFilter) return false if (searchTerm.trim()) { const q = searchTerm.toLowerCase().trim() const matchUser = ord.user.toLowerCase().includes(q) const matchId = String(ord.id).includes(q) const matchType = ord.deliverType.toLowerCase().includes(q) if (!matchUser && !matchId && !matchType) return false } return true }) }, [recentOrders, statusFilter, searchTerm]) return (
{/* ۱. کارت‌های آمار و شاخص‌های کلیدی صرافی */}
سفارشات ثبت‌شده امروز: {toFa(5)}
{toFa(28)}
+12% افزایش نسبت به هفته قبل
نرخ مبادله دینار عراق 🇮🇶
{toFa('2,100')} دینار
به‌ازای هر 100 هزار تومان
در انتظار تحویل مقصد نیازمند اقدام
{toFa(4)}
فرودگاه نجف و هتل‌های مدینه
حجم تبادلات ارزی
{toFa(450)} م.تومان
گردش مالی ماه جاری
{/* ۲. کارت‌های لحظه‌ای نرخ برابری ارزها */}

تابلوی زنده نرخ برابری ارزهای زیارتی

همگام با بازار نجف و صرافی مرکزی
{rates.map((r) => (
{r.flag} {r.pair}
{r.change}
{r.rate}
{r.base}
))}
{/* ۳. نوار جستجو و فیلترهای سفارشات */}
setSearchTerm(e.target.value)} placeholder="جستجوی زائر، کد سفارش یا محل تحویل..." className="h-9 ps-9 text-xs bg-surface-base rounded-xl border-border-soft" /> {searchTerm && ( )}
{/* ۴. جدول سفارشات ارزی با طراحی استاندارد پنل */}
فهرست سفارشات تبدیل و تحویل ارز زیارتی {toFa(filteredOrders.length)} سفارش
آخرین همگام‌سازی: چند لحظه پیش
{filteredOrders.length === 0 ? ( ) : ( filteredOrders.map((ord) => ( )) )}
کد پیگیری زائر متقاضی مبلغ مبدا (تومان) مبلغ مقصد (ارز تحویلی) محل و نحوه تحویل تاریخ وضعیت
هیچ سفارشی با این مشخصات یافت نشد.
#{ord.id}
{ord.user.slice(0, 1)}
{ord.user}
{ord.from} {ord.to}
{ord.deliverType}
{ord.date} {ord.status}
) } // ───────────────────────────────────────────────────────────────────────────── // ۴. آداب سفر و زیارت (Trip Etiquette) // ───────────────────────────────────────────────────────────────────────────── function TripEtiquetteServiceView({ service }: { service: ServiceMeta }) { const rituals = [ { id: 1, title: 'آداب تشرف به حرم امیرالمؤمنین (ع)', city: 'نجف اشرف', prayersCount: 14, audio: true }, { id: 2, title: 'زیارت عاشورا، وارث و آداب حرم سیدالشهدا (ع)', city: 'کربلای معلی', prayersCount: 22, audio: true }, { id: 3, title: 'اعمال و نمازهای مسجد کوفه و محراب شهادت', city: 'کوفه', prayersCount: 18, audio: true }, { id: 4, title: 'آداب احرام، طواف و مناسک عمره مفرده', city: 'مکه مکرمه', prayersCount: 30, audio: true }, { id: 5, title: 'زیارت جامعه کبیره و امین الله', city: 'مشترک عتبات', prayersCount: 10, audio: true }, ] return (
مجموع زیارات و ادعیه
{toFa(94)}
فهرست کامل مناسک
فایل‌های صوتی و ترتیل
{toFa(86)}
کیفیت استودیویی
زبان‌های ترجمه
5 زبان
فارسی، عربی، انگلیسی، روسی، اندونزیایی
شهرهای تحت پوشش
{toFa(6)}
عراق و عربستان سعودی
{rituals.map((r) => (
{r.city}
همراه با صوت و ترجمه

{r.title}

شامل {toFa(r.prayersCount)} فراز و دعای وارده مشاهده متن و صوت >
))}
) } // ───────────────────────────────────────────────────────────────────────────── // ۵. مشاوره و پشتیبانی (Consultant / Support) // ───────────────────────────────────────────────────────────────────────────── function ConsultantServiceView({ service }: { service: ServiceMeta }) { const [searchTerm, setSearchTerm] = useState('') const [specialtyFilter, setSpecialtyFilter] = useState('ALL') const consultants = [ { id: 1, name: 'دکتر علیرضا رضایی', specialty: 'پزشکی سفر، گرمازدگی و مراقبت‌های بهداشتی', category: 'medical', status: 'آنلاین و آماده پاسخ', isOnline: true, activeChats: 4, satisfaction: '99%', experience: '8 سال' }, { id: 2, name: 'حجت‌الاسلام سید هادی موسوی', specialty: 'احکام و مناسک حج، عمره و عتبات عالیات', category: 'rituals', status: 'آنلاین و آماده پاسخ', isOnline: true, activeChats: 6, satisfaction: '98%', experience: '12 سال' }, { id: 3, name: 'مهندس مهدی کمالی', specialty: 'لجستیک، حمل‌ونقل بین‌شهری، گذرنامه و امور گمشدگان', category: 'logistics', status: 'مشغول در تماس', isOnline: false, activeChats: 2, satisfaction: '97%', experience: '5 سال' }, { id: 4, name: 'سرکار خانم فاطمه سعیدی', specialty: 'مشاوره خانواده، بانوان، اقامت و کودکان در سفر', category: 'family', status: 'آنلاین و آماده پاسخ', isOnline: true, activeChats: 3, satisfaction: '100%', experience: '6 سال' }, ] const filteredConsultants = useMemo(() => { return consultants.filter((c) => { if (specialtyFilter !== 'ALL' && c.category !== specialtyFilter) return false if (searchTerm.trim()) { const q = searchTerm.toLowerCase().trim() const matchName = c.name.toLowerCase().includes(q) const matchSpec = c.specialty.toLowerCase().includes(q) if (!matchName && !matchSpec) return false } return true }) }, [consultants, specialtyFilter, searchTerm]) return (
{/* ۱. کارت‌های شاخص عملکرد مرکز پشتیبانی و مشاوره */}
مشاوران شیفت جاری آنلاین
{toFa(8)} نفر
از 12 کارشناس پشتیبانی 24 ساعته
مشاوره‌های امروز موفق
{toFa(64)}
پاسخگویی به مسائل بهداشتی و شرعی
میانگین زمان انتظار
45 ثانیه
استاندارد عالی (زیر 1 دقیقه)
رضایت‌مندی زائرین
98.7%
بر اساس 1,420 بازخورد ثبت‌شده
{/* ۲. فیلترها و نوار جستجوی کارشناسان */}
setSearchTerm(e.target.value)} placeholder="جستجوی نام یا حوزه تخصص..." className="h-9 ps-9 text-xs bg-surface-base rounded-xl border-border-soft" /> {searchTerm && ( )}
{/* ۳. کارت‌های کارشناسان با استایل مدرن */}

کادر کارشناسان پشتیبانی و مشاوره عقیله

{toFa(filteredConsultants.length)} کارشناس
پشتیبانی زنده صوتی و متنی زائرین
{filteredConsultants.map((c) => (
{c.status}

{c.name}

{c.specialty}

گفتگوهای فعال: {toFa(c.activeChats)} جلسه
رضایت مخاطبان: {c.satisfaction}
سابقه تخصصی: {c.experience}
))}
) } // ───────────────────────────────────────────────────────────────────────────── // ۶. فروشگاه معصومه (Massoumah Store) در components/StoreServiceView پیاده‌سازی شده است // ───────────────────────────────────────────────────────────────────────────── // ───────────────────────────────────────────────────────────────────────────── // ۷. تخمین هزینه سفر (Cost Estimate) // ───────────────────────────────────────────────────────────────────────────── function CostEstimateServiceView({ service }: { service: ServiceMeta }) { const [selectedDestination, setSelectedDestination] = useState('ALL') const [searchTerm, setSearchTerm] = useState('') const estimateCategories = [ { id: 1, title: 'هتل و اقامتگاه (نجف / کربلا / مکه / مدینه)', category: 'stay', standard: 'شبی 25 الی 40 دلار', vip: 'شبی 60 الی 120 دلار', notes: 'شامل صبحانه، اینترنت رایگان و نزدیکی به حرم' }, { id: 2, title: 'ترانسفر بین شهری و فرودگاهی (ون و سواری)', category: 'transfer', standard: 'هر مسیر 10 الی 15 دلار', vip: 'خودروی اختصاصی 30 الی 50 دلار', notes: 'مسیر نجف به کربلا، کاظمین، سامرا و بغداد' }, { id: 3, title: 'خوراک و پذیرایی روزانه', category: 'food', standard: 'روزانه 10 الی 15 دلار', vip: 'روزانه 25 الی 40 دلار', notes: 'رستوران‌های منتخب، غذای ایرانی و بوفه هتل' }, { id: 4, title: 'اینترنت و ارتباطات سیم‌کارت', category: 'simcard', standard: '10 الی 15 دلار برای کل سفر', vip: '25 دلار بسته نامحدود', notes: 'سیم‌کارت‌های زین، آسیاسل و کورک با دیتا پرسرعت' }, { id: 5, title: 'ویزا، عوارض خروج و بیمه زائر', category: 'visa', standard: 'رایگان (عراق) / 120 دلار (عربستان)', vip: 'ویزای تجاری و ترانزیت VIP', notes: 'بیمه درمان و حوادث تا سقف تعهدات کامل' }, ] const filteredCategories = useMemo(() => { return estimateCategories.filter((c) => { if (selectedDestination !== 'ALL' && c.category !== selectedDestination) return false if (searchTerm.trim()) { const q = searchTerm.toLowerCase().trim() const matchTitle = c.title.toLowerCase().includes(q) const matchNotes = c.notes.toLowerCase().includes(q) if (!matchTitle && !matchNotes) return false } return true }) }, [estimateCategories, selectedDestination, searchTerm]) return (
{/* ۱. کارت‌های شاخص‌های آماری تخمین هزینه */}
استعلام‌های این ماه زائرین
{toFa('12.8K')}
+18% رشد استعلام‌های اربعین و عمره
دقت برآورد هوشمند
96.2%
مطابقت با هزینه‌های واقعی سفر
سرفصل‌های هزینه‌ای پوشش کامل
{toFa(estimateCategories.length)} بخش اصلی
هتل، ترانسفر، خوراک، اینترنت، بیمه
وضعیت نرخ‌ها
امروز
همگام‌سازی لحظه‌ای با هتل‌ها و ترابری
{/* ۲. فیلترها و نوار جستجو */}
setSearchTerm(e.target.value)} placeholder="جستجوی سرفصل یا نکات هزینه..." className="h-9 ps-9 text-xs bg-surface-base rounded-xl border-border-soft" /> {searchTerm && ( )}
{/* ۳. جدول تخمین و بودجه‌بندی سفر با هدر کارتی مدرن */}
جدول برآورد تفکیکی مخارج سفر (اقتصادی و VIP) {toFa(filteredCategories.length)} آیتم
ارز مبنا: دلار و دینار
{filteredCategories.map((c) => ( ))}
بخش هزینه بسته اقتصادی (Standard) بسته ویژه (VIP) توضیحات و نکات اجرایی
{c.title} {c.standard} {c.vip} {c.notes}
) }