@@ -197,10 +203,10 @@ export default function Categories() {
- openModal(cat)} className="p-2 text-blue-600 hover:bg-blue-50 rounded-lg transition-colors">
+ openModal(cat)} className="p-2 text-blue-600 hover:bg-blue-50 rounded-lg transition-colors cursor-pointer">
- setDeleteTargetId(cat.id)} className="p-2 text-red-600 hover:bg-red-50 rounded-lg transition-colors">
+ setDeleteTargetId(cat.id)} className="p-2 text-red-600 hover:bg-red-50 rounded-lg transition-colors cursor-pointer">
@@ -220,120 +226,120 @@ export default function Categories() {
{/* Modal */}
{isModalOpen && (
-
-
-
-
- {editingCategory ? 'ویرایش دستهبندی' : 'افزودن دستهبندی جدید'}
-
-
setIsModalOpen(false)} className="text-gray-400 hover:text-red-500 transition-colors">
-
-
+
setIsModalOpen(false)}
+ title={editingCategory ? 'ویرایش دستهبندی' : 'افزودن دستهبندی جدید'}
+ icon={FolderTree}
+ maxWidth="2xl"
+ footer={
+
+ setIsModalOpen(false)}
+ >
+ انصراف
+
+
+ ذخیره دستهبندی
+
-
-
+
)}
{/* Media Selector Modal */}
+
setIsMediaSelectorOpen(false)}
diff --git a/frontend/admin-panel/src/pages/Coupons.tsx b/frontend/admin-panel/src/pages/Coupons.tsx
index 053cba1..7fd47df 100644
--- a/frontend/admin-panel/src/pages/Coupons.tsx
+++ b/frontend/admin-panel/src/pages/Coupons.tsx
@@ -165,12 +165,17 @@ export default function Coupons() {
مدیریت کدهای تخفیف با اهداف چندگانه (کاربران، حیوانات، محصولات و ...)
-
openModal()} className="bg-purple-600 hover:bg-purple-700 text-white px-5 py-2.5 rounded-xl flex items-center gap-2 font-bold transition-all shadow-md shadow-purple-200">
-
+ openModal()}
+ >
کد تخفیف جدید
-
+
+
diff --git a/frontend/admin-panel/src/pages/FAQManager.tsx b/frontend/admin-panel/src/pages/FAQManager.tsx
index ebf9921..751567e 100644
--- a/frontend/admin-panel/src/pages/FAQManager.tsx
+++ b/frontend/admin-panel/src/pages/FAQManager.tsx
@@ -4,6 +4,9 @@ import { toast } from 'react-hot-toast';
import api from '../services/api';
import Spinner from '../components/ui/Spinner';
import ConfirmModal from '../components/ui/ConfirmModal';
+import Button from '../components/ui/Button';
+import Modal from '../components/ui/Modal';
+
interface FAQ {
id: string;
@@ -129,13 +132,14 @@ export default function FAQManager() {
سوالات و پاسخهایی که در صفحه اصلی سایت نمایش داده میشوند — با Schema.org FAQPage برای SEO
-
openModal()}
- className="bg-orange-500 hover:bg-orange-600 text-white px-5 py-2.5 rounded-xl flex items-center gap-2 font-bold transition-all shadow-md shadow-orange-200"
>
-
افزودن سوال جدید
-
+
{/* Info Box */}
@@ -147,7 +151,7 @@ export default function FAQManager() {
{isLoading ? (
-
+
) : faqs.length === 0 ? (
@@ -155,56 +159,71 @@ export default function FAQManager() {
هیچ سوالی ثبت نشده است
openModal()}
- className="mt-4 text-orange-500 font-bold hover:underline text-sm"
+ className="mt-4 text-purple-600 font-bold hover:underline text-sm cursor-pointer"
>
اولین سوال را اضافه کنید
) : (
- faqs.map((faq, idx) => (
+ faqs.map((faq) => (
-
-
-
- {idx + 1}
-
-
-
-
{faq.question}
- {!faq.isActive && (
-
- غیرفعال
-
- )}
+
+
+
+
+
+
+
+
+ ترتیب: {faq.order}
+
+
+ {faq.isActive ? 'فعال' : 'غیرفعال'}
+
+
+
{faq.question}
+
+ {faq.answer}
+
-
{faq.answer}
-
+
+
toggleActive(faq)}
- className={`p-2 rounded-lg transition-colors ${
+ title={faq.isActive ? 'غیرفعالسازی' : 'فعالسازی'}
+ className={`p-2 rounded-xl transition-colors cursor-pointer ${
faq.isActive
? 'text-green-600 hover:bg-green-50'
- : 'text-gray-400 hover:bg-gray-50'
+ : 'text-gray-400 hover:bg-gray-100'
}`}
- title={faq.isActive ? 'غیرفعال کردن' : 'فعال کردن'}
>
- {faq.isActive ? : }
+ {faq.isActive ? (
+
+ ) : (
+
+ )}
openModal(faq)}
- className="p-2 text-blue-600 hover:bg-blue-50 rounded-lg transition-colors"
+ className="p-2 text-blue-600 hover:bg-blue-50 rounded-xl transition-colors cursor-pointer"
>
setDeleteTargetId(faq.id)}
- className="p-2 text-red-500 hover:bg-red-50 rounded-lg transition-colors"
+ className="p-2 text-red-600 hover:bg-red-50 rounded-xl transition-colors cursor-pointer"
>
@@ -215,31 +234,49 @@ export default function FAQManager() {
)}
- {/* Form Modal */}
+ {/* Modal */}
{isModalOpen && (
-
-
-
-
- {editingFaq ? 'ویرایش سوال متداول' : 'افزودن سوال جدید'}
-
-
setIsModalOpen(false)} className="p-2 hover:bg-gray-100 rounded-lg">
-
-
+
setIsModalOpen(false)}
+ title={editingFaq ? 'ویرایش سوال متداول' : 'افزودن سوال جدید'}
+ icon={HelpCircle}
+ maxWidth="2xl"
+ footer={
+
+ setIsModalOpen(false)}
+ >
+ انصراف
+
+
+ ذخیره سوال
+
-
-
+ }
+ >
+
@@ -264,44 +301,28 @@ export default function FAQManager() {
type="number"
value={formData.order}
onChange={(e) => setFormData({ ...formData, order: Number(e.target.value) })}
- className="w-full px-4 py-2.5 rounded-xl border border-gray-200 focus:border-orange-400 outline-none text-sm"
+ className="w-full px-4 py-2.5 rounded-xl border border-gray-200 focus:border-purple-500 outline-none text-sm"
/>
-
- ✅ فعال و قابل نمایش
+
+ ✅ فعال و قابل نمایش
setFormData({ ...formData, isActive: e.target.checked })}
- className="rounded text-orange-500 focus:ring-orange-400"
+ className="rounded text-purple-600 focus:ring-purple-500"
/>
-
-
- setIsModalOpen(false)}
- className="px-5 py-2.5 rounded-xl border border-gray-200 text-gray-600 font-bold hover:bg-gray-50 transition-colors"
- >
- انصراف
-
-
- {isSaving && }
- ذخیره
-
-
-
+
)}
+
+
{deleteTargetId && (
-
openModal()}
- className="bg-blue-600 hover:bg-blue-700 text-white px-5 py-2.5 rounded-xl flex items-center gap-2 font-bold transition-all shadow-md shadow-blue-200"
>
-
آیتم جدید
-
+
+
{/* Tabs */}
{MENU_TABS.map((tab) => (
@@ -292,27 +298,45 @@ export default function MenuManager() {
)}
- {/* Form Modal */}
+ {/* Modal */}
{isModalOpen && (
-
-
-
-
- {editingItem ? 'ویرایش آیتم منو' : 'افزودن آیتم جدید'}
-
-
setIsModalOpen(false)} className="p-2 hover:bg-gray-100 rounded-lg">
-
-
+
setIsModalOpen(false)}
+ title={editingItem ? 'ویرایش آیتم منو' : 'افزودن آیتم جدید'}
+ icon={Menu}
+ maxWidth="xl"
+ footer={
+
+ setIsModalOpen(false)}
+ >
+ انصراف
+
+
+ ذخیره
+
-
-
+ }
+ >
+
+
@@ -377,7 +401,7 @@ export default function MenuManager() {
value={formData.badge}
onChange={(e) => setFormData({ ...formData, badge: e.target.value })}
placeholder="مثال: جدید"
- className="w-full px-4 py-2.5 rounded-xl border border-gray-200 focus:border-blue-400 outline-none text-sm"
+ className="w-full px-4 py-2.5 rounded-xl border border-gray-200 focus:border-purple-500 outline-none text-sm"
/>
@@ -389,7 +413,7 @@ export default function MenuManager() {
type="number"
value={formData.order}
onChange={(e) => setFormData({ ...formData, order: Number(e.target.value) })}
- className="w-full px-4 py-2.5 rounded-xl border border-gray-200 focus:border-blue-400 outline-none text-sm"
+ className="w-full px-4 py-2.5 rounded-xl border border-gray-200 focus:border-purple-500 outline-none text-sm"
/>
@@ -411,29 +435,12 @@ export default function MenuManager() {
/>
-
-
- setIsModalOpen(false)}
- className="px-5 py-2.5 rounded-xl border border-gray-200 text-gray-600 font-bold hover:bg-gray-50"
- >
- انصراف
-
-
- {isSaving && }
- ذخیره
-
-
-
+
)}
+
{deleteTargetId && (
('gateways');
@@ -490,18 +493,20 @@ export default function PaymentGatewaysPage() {
-
- {isSaving ? : }
- ذخیره کلیه تنظیمات درگاه زیبال
-
+ ذخیره کلیه تنظیمات درگاه زیبال
+
)}
+
{activeTab === 'wallets' && (
{/* Wallets Overview */}
diff --git a/frontend/admin-panel/src/pages/Products.tsx b/frontend/admin-panel/src/pages/Products.tsx
index fff609b..e721ae0 100644
--- a/frontend/admin-panel/src/pages/Products.tsx
+++ b/frontend/admin-panel/src/pages/Products.tsx
@@ -8,6 +8,9 @@ import Pagination from '../components/ui/Pagination';
import MediaSelector from '../components/ui/MediaSelector';
import ConfirmModal from '../components/ui/ConfirmModal';
import PriceInput from '../components/ui/PriceInput';
+import Button from '../components/ui/Button';
+
+
export interface Category {
id: string;
@@ -435,15 +438,17 @@ export default function Products() {
افزودن و ویرایش پیشرفته محصولات با تنظیمات سئو
-
openModal()}
- className="bg-purple-600 hover:bg-purple-700 text-white px-5 py-2.5 rounded-xl flex items-center gap-2 font-bold transition-all shadow-md shadow-purple-200"
>
-
محصول جدید
-
+
+
{/* Filters Bar */}
@@ -1650,18 +1655,29 @@ export default function Products() {
-
-
setIsModalOpen(false)} className="px-5 py-2.5 rounded-xl font-bold text-gray-600 hover:bg-gray-200 transition-colors">
+
+ setIsModalOpen(false)}
+ >
انصراف
-
-
+
+
ذخیره محصول
-
+
)}
+
{/* Media Selector Modal */}
آمار فروش، رفتار کاربران و عملکرد تخفیفها
- {
if (!reportData) return;
const rows = [
@@ -119,13 +126,12 @@ export default function Reports() {
link.click();
document.body.removeChild(link);
}}
- className="bg-white border-2 border-purple-200 text-purple-700 hover:bg-purple-50 px-5 py-2.5 rounded-xl flex items-center gap-2 font-bold transition-all shadow-sm"
>
-
خروجی اکسل (Excel)
-
+
+
{/* Overview Cards */}
diff --git a/frontend/admin-panel/src/pages/Reviews.tsx b/frontend/admin-panel/src/pages/Reviews.tsx
index e2f7e08..b44392b 100644
--- a/frontend/admin-panel/src/pages/Reviews.tsx
+++ b/frontend/admin-panel/src/pages/Reviews.tsx
@@ -18,6 +18,10 @@ import {
import { toast } from 'react-hot-toast';
import api from '../services/api';
import Spinner from '../components/ui/Spinner';
+import Button from '../components/ui/Button';
+import Modal from '../components/ui/Modal';
+
+
interface ProductReview {
id: string;
@@ -434,21 +438,34 @@ export default function Reviews() {
{/* Reply Modal */}
{replyingReview && (
-
-
-
-
-
- پاسخ به دیدگاه {replyingReview.userName}
-
-
setReplyingReview(null)}
+ title={`پاسخ به دیدگاه ${replyingReview.userName}`}
+ icon={Reply}
+ maxWidth="lg"
+ footer={
+
+ setReplyingReview(null)}
- className="p-1 text-gray-400 hover:text-gray-600 rounded-lg hover:bg-gray-100"
>
- ✕
-
+ انصراف
+
+
+ ثبت و انتشار پاسخ
+
-
+ }
+ >
+
متن دیدگاه خریدار:
{replyingReview.comment}
@@ -466,28 +483,10 @@ export default function Reviews() {
className="w-full p-3 border border-gray-200 rounded-xl text-sm font-medium outline-none focus:ring-2 focus:ring-purple-500 resize-none leading-relaxed"
/>
-
-
- setReplyingReview(null)}
- className="px-4 py-2.5 text-xs font-bold text-gray-600 hover:bg-gray-100 rounded-xl transition-all"
- >
- انصراف
-
-
- {isSavingReply && }
- ثبت و انتشار پاسخ
-
-
-
+
)}
);
}
+
diff --git a/frontend/admin-panel/src/pages/Tickets.tsx b/frontend/admin-panel/src/pages/Tickets.tsx
index 615d80f..6296fca 100644
--- a/frontend/admin-panel/src/pages/Tickets.tsx
+++ b/frontend/admin-panel/src/pages/Tickets.tsx
@@ -20,6 +20,8 @@ import {
} from 'lucide-react';
import api from '../services/api';
import { toast } from 'react-hot-toast';
+import Button from '../components/ui/Button';
+import Modal from '../components/ui/Modal';
interface TicketMessage {
id: string;
@@ -340,47 +342,63 @@ export default function Tickets() {
{/* Ticket Details & Admin Reply Modal */}
{selectedTicket && (
-
-
- {/* Modal Header */}
-
-
-
-
{selectedTicket.subject}
-
- {selectedTicket.ticketNumber}
-
-
-
- کاربر: {selectedTicket.user?.firstName} {selectedTicket.user?.lastName} ({selectedTicket.user?.mobile})
- {selectedTicket.pet && (
- • 🐾 {selectedTicket.pet.name} ({selectedTicket.pet.breed || selectedTicket.pet.type})
- )}
-
+
setSelectedTicket(null)}
+ title={`تیکت ${selectedTicket.ticketNumber}: ${selectedTicket.subject}`}
+ icon={MessageSquare}
+ maxWidth="3xl"
+ footer={
+
+ setSelectedTicket(null)}
+ >
+ بستن
+
+
+ ارسال پاسخ به کاربر
+
+
+ }
+ >
+
+ {/* Header meta */}
+
+
+ کاربر: {selectedTicket.user?.firstName} {selectedTicket.user?.lastName} ({selectedTicket.user?.mobile})
+ {selectedTicket.pet && (
+ 🐾 {selectedTicket.pet.name} ({selectedTicket.pet.breed || selectedTicket.pet.type})
+ )}
+
+ تغییر وضعیت:
handleUpdateStatus(e.target.value)}
- className="px-2.5 py-1.5 border border-gray-200 rounded-xl text-xs font-bold bg-gray-50 focus:border-canina-blue outline-none"
+ className="px-2.5 py-1.5 border border-gray-200 rounded-xl text-xs font-bold bg-white focus:ring-2 focus:ring-purple-500 outline-none"
>
در انتظار پاسخ
در حال بررسی
پاسخ داده شد
بسته شده
- setSelectedTicket(null)}
- className="w-8 h-8 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-600 flex items-center justify-center font-bold text-sm cursor-pointer"
- >
- ✕
-
{/* Messages Chat Scroll */}
-
+
{(selectedTicket.messages || []).map((msg) => {
const isAdminOrVet = msg.senderRole === 'ADMIN' || msg.senderRole === 'VET_DOCTOR';
return (
@@ -388,7 +406,7 @@ export default function Tickets() {
key={msg.id}
className={`p-4 rounded-2xl max-w-[85%] text-xs font-medium leading-relaxed ${
isAdminOrVet
- ? 'bg-emerald-50 border border-emerald-200 text-emerald-950 mr-auto'
+ ? 'bg-purple-50 border border-purple-200 text-purple-950 mr-auto'
: 'bg-blue-50 border border-blue-200 text-blue-950 ml-auto'
}`}
>
@@ -396,8 +414,8 @@ export default function Tickets() {
{isAdminOrVet ? (
<>
-
- {msg.senderName} (تیم پزشکی / ادمین)
+
+ {msg.senderName} (تیم پزشکی / ادمین)
>
) : (
<>
@@ -417,7 +435,7 @@ export default function Tickets() {
{/* Admin Response Composer */}
-
+
ارسال پاسخ دامپزشک / پشتیبانی:
@@ -439,29 +457,13 @@ export default function Tickets() {
placeholder="متن پاسخ تخصصی به کاربر را وارد کنید..."
value={replyMessage}
onChange={(e) => setReplyMessage(e.target.value)}
- className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl text-xs font-medium focus:border-canina-blue outline-none"
+ className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl text-xs font-medium focus:border-purple-500 focus:ring-2 focus:ring-purple-200 outline-none resize-none leading-relaxed"
/>
-
- setSelectedTicket(null)}
- className="px-4 py-2 rounded-xl text-xs font-bold text-gray-600 bg-gray-100 hover:bg-gray-200 cursor-pointer"
- >
- بستن
-
-
-
- {sendingReply ? 'در حال ارسال...' : 'ارسال پاسخ به کاربر'}
-
-
-
+
)}
);
}
+
diff --git a/frontend/admin-panel/src/pages/Users.tsx b/frontend/admin-panel/src/pages/Users.tsx
index f766c9e..081de78 100644
--- a/frontend/admin-panel/src/pages/Users.tsx
+++ b/frontend/admin-panel/src/pages/Users.tsx
@@ -265,13 +265,15 @@ export default function Users() {
-
setShowCreateModal(true)}
- className="w-full sm:w-auto flex items-center justify-center gap-2 bg-purple-600 hover:bg-purple-700 text-white px-4 py-2.5 rounded-xl font-bold text-xs shadow-md shadow-purple-200 transition-all cursor-pointer"
>
-
افزودن کاربر جدید
-
+
+
- handleOpenModal()}
- className="bg-purple-600 hover:bg-purple-700 text-white px-5 py-3 rounded-xl font-black text-sm flex items-center gap-2 shadow-lg shadow-purple-600/20 transition-all hover:scale-105 shrink-0 cursor-pointer"
>
-
- افزودن ویدئوی جدید
-
+ افزودن ویدئوی جدید
+
+
@@ -310,22 +315,35 @@ export default function Videos() {
)}
{isModalOpen && (
-
-
-
-
-
- {editingVideo ? 'ویرایش ویدئوی آموزشی' : 'افزودن ویدئوی جدید به آکادمی'}
-
-
setIsModalOpen(false)}
+ title={editingVideo ? 'ویرایش ویدئوی آموزشی' : 'افزودن ویدئوی جدید به آکادمی'}
+ icon={VideoIcon}
+ maxWidth="2xl"
+ footer={
+
+ setIsModalOpen(false)}
- className="p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-50 rounded-xl transition-colors cursor-pointer"
>
-
-
+ انصراف
+
+
+ ذخیره اطلاعات
+
-
-
+ }
+ >
+
@@ -437,14 +456,15 @@ export default function Videos() {
placeholder="https://... یا کد آیفرم آپارات/یوتیوب"
className="flex-1 bg-gray-50 border border-gray-200 rounded-xl py-3 px-4 text-xs font-mono focus:outline-none focus:ring-2 focus:ring-purple-500/20"
/>
-
setIsVideoMediaOpen(true)}
- className="px-4 py-3 bg-purple-50 text-purple-700 hover:bg-purple-100 rounded-xl text-xs font-black flex items-center gap-1.5 border border-purple-200 shrink-0 cursor-pointer"
>
-
- انتخاب ویدئو
-
+ انتخاب ویدئو
+
@@ -471,27 +491,12 @@ export default function Videos() {
نمایش به عنوان ویدئوی ویژه در بخش «مشاوره ویدئویی» صفحه اصلی سایت
-
-
- setIsModalOpen(false)}
- className="px-5 py-2.5 rounded-xl border border-gray-200 text-gray-600 font-bold text-sm hover:bg-gray-50 cursor-pointer"
- >
- انصراف
-
-
- ذخیره اطلاعات
-
-
-
+
)}
+
{/* Cover Thumbnail Media Selector Modal */}
مدیریت اصطلاحات علمی، مواد تشکیلدهنده و خواص درمانی
-
openModal()}
- className="bg-purple-600 hover:bg-purple-700 text-white px-5 py-2.5 rounded-xl flex items-center gap-2 font-bold transition-all shadow-md shadow-purple-200"
>
-
مفهوم جدید
-
+
@@ -184,8 +188,8 @@ export default function Wiki() {
{t.definition}
- openModal(t)} className="p-2 text-blue-600 hover:bg-blue-50 rounded-lg transition-colors">
- setDeleteTargetKey(t.key)} className="p-2 text-red-600 hover:bg-red-50 rounded-lg transition-colors">
+ openModal(t)} className="p-2 text-blue-600 hover:bg-blue-50 rounded-lg transition-colors cursor-pointer">
+ setDeleteTargetKey(t.key)} className="p-2 text-red-600 hover:bg-red-50 rounded-lg transition-colors cursor-pointer">
@@ -202,99 +206,109 @@ export default function Wiki() {
{isModalOpen && (
-
-
-
-
- {editingTerm ? 'ویرایش دانشنامه' : 'افزودن مفهوم جدید'}
-
-
setIsModalOpen(false)} className="text-gray-400 hover:text-red-500 transition-colors">
-
-
+
setIsModalOpen(false)}
+ title={editingTerm ? 'ویرایش دانشنامه' : 'افزودن مفهوم جدید'}
+ icon={BookOpen}
+ maxWidth="2xl"
+ footer={
+
+ setIsModalOpen(false)}
+ >
+ انصراف
+
+
+ ذخیره
+
-
-
-
-
-
+ }
+ >
+
+
+
- توضیح علمی *
- setFormData({ ...formData, definition: e.target.value })} rows={5} className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-purple-500 outline-none">
+ شناسه یکتا (Key) *
+ setFormData({ ...formData, key: e.target.value })} className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-purple-500 outline-none font-mono text-sm disabled:bg-gray-100" />
-
- {/* Related Products Selector (TASK-2.23) */}
-
-
محصولات مرتبط با این مقاله علمی (TASK-2.23)
-
{
- const prodId = e.target.value;
- if (prodId && !formData.relatedProducts.includes(prodId)) {
- setFormData({ ...formData, relatedProducts: [...formData.relatedProducts, prodId] });
- }
- }}
- className="w-full px-3 py-2 border rounded-xl text-xs bg-white"
- >
- + انتخاب محصول جهت افزودن به لیست مرتبط
- {productsList.map(p => (
- {p.nameFa} ({p.artNo})
- ))}
-
-
-
- {formData.relatedProducts.map(pId => {
- const prod = productsList.find(p => p.id === pId);
- return (
-
- {prod ? prod.nameFa : pId}
- setFormData({ ...formData, relatedProducts: formData.relatedProducts.filter(id => id !== pId) })}
- className="hover:text-red-600 font-black text-sm"
- >
- ×
-
-
- );
- })}
-
+
+ نام اصطلاح (Term) *
+ setFormData({ ...formData, term: e.target.value })} className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-purple-500 outline-none" />
+
-
-
تنظیمات سئو (SEO)
-
- عنوان متا
- setFormData({ ...formData, metaTitle: e.target.value })} className="w-full px-3 py-2 rounded-lg border border-gray-200 focus:border-purple-500 outline-none text-sm" />
-
-
- کلمات کلیدی
- setFormData({ ...formData, keywords: e.target.value })} className="w-full px-3 py-2 rounded-lg border border-gray-200 focus:border-purple-500 outline-none text-sm" />
-
-
- توضیحات متا
- setFormData({ ...formData, metaDescription: e.target.value })} className="w-full px-3 py-2 rounded-lg border border-gray-200 focus:border-purple-500 outline-none text-sm">
-
+
+ توضیح علمی *
+ setFormData({ ...formData, definition: e.target.value })} rows={5} className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-purple-500 outline-none">
+
+
+ {/* Related Products Selector */}
+
+
محصولات مرتبط با این مقاله علمی
+
{
+ const prodId = e.target.value;
+ if (prodId && !formData.relatedProducts.includes(prodId)) {
+ setFormData({ ...formData, relatedProducts: [...formData.relatedProducts, prodId] });
+ }
+ }}
+ className="w-full px-3 py-2 border rounded-xl text-xs bg-white"
+ >
+ + انتخاب محصول جهت افزودن به لیست مرتبط
+ {productsList.map(p => (
+ {p.nameFa} ({p.artNo})
+ ))}
+
+
+
+ {formData.relatedProducts.map(pId => {
+ const prod = productsList.find(p => p.id === pId);
+ return (
+
+ {prod ? prod.nameFa : pId}
+ setFormData({ ...formData, relatedProducts: formData.relatedProducts.filter(id => id !== pId) })}
+ className="hover:text-red-600 font-black text-sm cursor-pointer"
+ >
+ ×
+
+
+ );
+ })}
+
-
-
-
-
- setIsModalOpen(false)} className="px-5 py-2.5 rounded-xl font-bold text-gray-600 hover:bg-gray-200 transition-colors">انصراف
- ذخیره
-
+
+
تنظیمات سئو (SEO)
+
+ عنوان متا
+ setFormData({ ...formData, metaTitle: e.target.value })} className="w-full px-3 py-2 rounded-lg border border-gray-200 focus:border-purple-500 outline-none text-sm" />
+
+
+ کلمات کلیدی
+ setFormData({ ...formData, keywords: e.target.value })} className="w-full px-3 py-2 rounded-lg border border-gray-200 focus:border-purple-500 outline-none text-sm" />
+
+
+ توضیحات متا
+ setFormData({ ...formData, metaDescription: e.target.value })} className="w-full px-3 py-2 rounded-lg border border-gray-200 focus:border-purple-500 outline-none text-sm">
+
+
+
-
+
)}
+
('refunds');
@@ -378,25 +381,27 @@ export default function ZibalPortalPage() {
{/* Top Bar with Filter & Search Controls */}
-
-
+ downloadCSV(refunds, 'zibal-refunds')}
- className="bg-indigo-600 hover:bg-indigo-700 text-white text-xs font-bold px-4 py-2.5 rounded-xl flex items-center gap-2 shadow-sm transition-colors cursor-pointer"
>
-
- دانلود گزارش
-
+ دانلود گزارش
+
-
-
-
+ />
+
{/* Filter Inputs Bar */}
{/* Date Filter */}
@@ -634,25 +639,27 @@ export default function ZibalPortalPage() {
{activeMainTab === 'checkouts' && (
-
-
+ downloadCSV(checkouts, 'zibal-checkouts')}
- className="bg-indigo-600 hover:bg-indigo-700 text-white text-xs font-bold px-4 py-2.5 rounded-xl flex items-center gap-2 shadow-sm transition-colors cursor-pointer"
>
-
- دانلود گزارش
-
+ دانلود گزارش
+
-
-
-
+ />
+
{/* Filter Inputs Bar */}
@@ -851,25 +858,27 @@ export default function ZibalPortalPage() {
{activeMainTab === 'gateway_transactions' && (
-
-
+ downloadCSV(gatewayTxList, 'zibal-ipg-transactions')}
- className="bg-indigo-600 hover:bg-indigo-700 text-white text-xs font-bold px-4 py-2.5 rounded-xl flex items-center gap-2 shadow-sm transition-colors cursor-pointer"
>
-
- دانلود گزارش درگاه
-
+ دانلود گزارش درگاه
+
-
-
-
+ />
+
{/* Filter Inputs */}
@@ -1013,25 +1022,40 @@ export default function ZibalPortalPage() {
)}
{/* ======================================================== */}
- {/* MODAL: SUBMIT NEW REFUND / REVERSE */}
+ {/* MODAL: NEW REFUND SUBMIT */}
{/* ======================================================== */}
{newRefundModal && (
-
-
-
-
-
- ثبت درخواست استرداد وجه (Refund / Reverse)
-
-
setNewRefundModal(false)}
+ title="ثبت و ارسال استرداد وجه جدید (Refund / Reverse)"
+ icon={RotateCcw}
+ maxWidth="lg"
+ footer={
+
+ setNewRefundModal(false)}
- className="text-gray-400 hover:text-gray-700 font-bold text-lg cursor-pointer"
>
- ✕
-
+ انصراف
+
+
+ ارسال به زیبال
+
-
-
+ }
+ >
+
+
شماره تراکنش شاپرک (Track ID) *
-
-
- setNewRefundModal(false)}
- className="px-5 py-2.5 rounded-xl font-bold bg-gray-100 hover:bg-gray-200 text-gray-600 cursor-pointer"
- >
- انصراف
-
-
- {isSubmittingRefund ? : }
- ارسال به زیبال
-
-
-
+
)}
{/* ======================================================== */}
{/* MODAL: DETAIL / INQUIRY VIEWER */}
{/* ======================================================== */}
{detailModalItem && (
-
-
-
-
{detailModalItem.title}
-
setDetailModalItem(null)} className="text-gray-400 font-bold text-lg">
- ✕
-
+
setDetailModalItem(null)}
+ title={detailModalItem.title}
+ maxWidth="lg"
+ footer={
+
+ setDetailModalItem(null)}
+ >
+ بستن
+
-
- {JSON.stringify(detailModalItem.data, null, 2)}
-
-
-
+ }
+ >
+
+ {JSON.stringify(detailModalItem.data, null, 2)}
+
+
)}
);
}
+