+
+
+ شمارههای موبایل دریافتکننده (Custom Phone Numbers) *
+
+ انتخاب از کاربران/مدیران سیستم یا درج مستقیم
+
+
+
+ {/* Searchable User Selector */}
+
+
+
+
+ {
+ const q = e.target.value;
+ setUserSearchQuery(q);
+ setIsUserDropdownOpen(true);
+ fetchSystemUsers(q);
+ }}
+ onFocus={() => {
+ setIsUserDropdownOpen(true);
+ if (systemUsers.length === 0) fetchSystemUsers();
+ }}
+ placeholder="جستجوی کاربر یا مدیر در سیستم (نام، شماره تماس)..."
+ className="w-full pr-8 pl-3 py-2 bg-white border border-amber-300 rounded-xl text-xs outline-none focus:ring-2 focus:ring-amber-500"
+ />
+
+
setIsUserDropdownOpen((prev) => !prev)}
+ className="px-3 py-2 bg-amber-200/70 hover:bg-amber-200 text-amber-900 rounded-xl text-xs font-bold shrink-0 transition-all flex items-center gap-1 cursor-pointer"
+ >
+
+ لیست کاربران
+
+
+
+ {/* Dropdown list */}
+ {isUserDropdownOpen && (
+
+
+ انتخاب کاربر برای اضافه شدن به لیست شمارهها:
+ setIsUserDropdownOpen(false)}
+ className="text-gray-400 hover:text-gray-700 cursor-pointer"
+ >
+
+
+
+ {isLoadingUsers ? (
+
در حال بارگذاری کاربران...
+ ) : systemUsers.length === 0 ? (
+
کاربری یافت نشد
+ ) : (
+ systemUsers.map((u) => {
+ const uName = (u.firstName ? `${u.firstName} ${u.lastName || ''}` : 'بدون نام').trim();
+ const uPhone = u.mobile || '';
+ const isAlreadySelected = uPhone && ruleFormCustomPhone.includes(uPhone);
+ const roleBadge = u.role === 'Admin' ? 'مدیر' : u.role === 'Vet' ? 'دامپزشک' : 'کاربر';
+
+ return (
+
{
+ if (!uPhone) {
+ toast.error('این کاربر شماره همراه ثبتشده ندارد');
+ return;
+ }
+ const currentPhones = ruleFormCustomPhone
+ .split(/[,;\s]+/)
+ .map((p) => p.trim())
+ .filter(Boolean);
+ if (currentPhones.includes(uPhone)) {
+ // Remove
+ const filtered = currentPhones.filter((p) => p !== uPhone);
+ setRuleFormCustomPhone(filtered.join(' ، '));
+ toast.success(`${uName} از گیرندگان حذف شد`);
+ } else {
+ // Add
+ const next = [...currentPhones, uPhone];
+ setRuleFormCustomPhone(next.join(' ، '));
+ toast.success(`${uName} (${uPhone}) به گیرندگان اضافه شد`);
+ }
+ }}
+ className={`w-full p-2.5 text-right flex items-center justify-between hover:bg-amber-50/50 transition-colors text-xs cursor-pointer ${
+ isAlreadySelected ? 'bg-amber-50' : ''
+ }`}
+ >
+
+
+ {uName.charAt(0)}
+
+
+
+ {uName}
+
+ {roleBadge}
+
+
+
+ {uPhone || 'بدون شماره'}
+
+
+
+
+ {isAlreadySelected ? (
+
+ انتخاب شده
+
+ ) : (
+
+ + افزودن
+
+ )}
+
+
+ );
+ })
+ )}
+
+ )}
+
+
+
setRuleFormTitle(e.target.value)}
- placeholder="مثلاً: ارسال مشخصات گیرنده به شرکت پست / انبار"
- className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-amber-500 text-sm font-bold"
+ value={ruleFormCustomPhone}
+ onChange={(e) => setRuleFormCustomPhone(e.target.value)}
+ placeholder="مثلاً: 09123456789 (برای چند شماره با کاما یا ویرگول جدا کنید)"
+ className="w-full border border-amber-300 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-amber-500 text-xs font-mono font-bold bg-white"
+ dir="ltr"
/>
- {/* Event & Recipient Grid */}
-
- {/* Trigger Event */}
-
- رویداد تحریککننده (Trigger Event) *
- {
- const newEv = e.target.value;
- setRuleFormEvent(newEv);
- const def = eventDefinitions.find((ed) => ed.event === newEv);
- if (def && def.variables.length > 0) {
- setRuleFormVariables(def.variables.slice(0, 3).map((v) => v.key));
- }
- }}
- className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-amber-500 text-xs font-bold bg-white"
- >
- {eventDefinitions.length > 0 ? (
- eventDefinitions.map((ed) => (
-
- {ed.label}
-
- ))
- ) : (
- <>
- پرداخت موفق سفارش (Order Paid)
- ثبت سفارش کارت به کارت / در انتظار
- ارسال مرسوله و صدور بارکد پستی
- شارژ و افزایش موجودی کیف پول
- ثبت درخواست همکاری B2B
- ثبت پیام در فرم تماس با ما
- >
- )}
-
-
+
+ 💡 میتوانید از جستجوی بالا مدیر یا کاربر مدنظرتان را انتخاب کنید یا شمارهها را مستقیماً تایپ نمایید.
+
+
+ )}
- {/* Recipient Type */}
-
- گیرنده پیامک (Recipient) *
- setRuleFormRecipientType(e.target.value as any)}
- className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-amber-500 text-xs font-bold bg-white"
- >
- خریدار / مشتری (شماره ثبتشده در سفارش یا فرم)
- مدیر سایت (شمارههای تنظیمشده در پنل)
- شماره همراه دلخواه (انبار، واحد ارسال، حسابداری)
-
-
+ {/* Pattern ID Selection */}
+
+
+
+ شناسه الگوی ملی پیامک (Pattern Body ID) *
+
+ انتخاب از الگوها یا درج دستی
+
+
+
+ {/* Select from registered patterns */}
+
+ setRuleFormPatternId(e.target.value)}
+ className="w-full border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-amber-500 text-xs font-bold bg-white"
+ >
+ انتخاب از لیست الگوهای موجود...
+ {patterns.map((p) => (
+
+ #{p.id} - {p.title}
+
+ ))}
+
- {/* Custom Phone Number Input / User Picker if custom */}
- {ruleFormRecipientType === 'custom' && (
-
-
-
- شمارههای موبایل دریافتکننده (Custom Phone Numbers) *
-
-
- انتخاب از کاربران/مدیران سیستم یا درج مستقیم
-
-
+ {/* Or Manual Body ID Input */}
+
+ setRuleFormPatternId(e.target.value)}
+ placeholder="یا وارد کردن شناسه پترن جدید (مثلاً: 508081)"
+ className="w-full border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-amber-500 text-xs font-mono font-bold bg-white"
+ dir="ltr"
+ />
+
+
- {/* Searchable User Selector */}
-
-
-
-
- {
- const q = e.target.value;
- setUserSearchQuery(q);
- setIsUserDropdownOpen(true);
- fetchSystemUsers(q);
- }}
- onFocus={() => {
- setIsUserDropdownOpen(true);
- if (systemUsers.length === 0) fetchSystemUsers();
- }}
- placeholder="جستجوی کاربر یا مدیر در سیستم (نام، شماره تماس)..."
- className="w-full pr-8 pl-3 py-2 bg-white border border-amber-300 rounded-xl text-xs outline-none focus:ring-2 focus:ring-amber-500"
- />
-
+ {/* Show Preview of Selected Pattern Text if found */}
+ {(() => {
+ const selPat = patterns.find((p) => String(p.id) === String(ruleFormPatternId));
+ if (!selPat) return null;
+ return (
+
+ متن الگو:
+ {selPat.body}
+
+ );
+ })()}
+
+
+ {/* Dynamic Variables Mapper */}
+
+
+
+ تخصیص متغیرها به ترتیب پارامترهای پترن ({'{0}'}, {'{1}'}, ...)
+
+
+ کلیک روی متغیرها برای افزودن یا حذف
+
+
+
+ {/* Current mapped variables */}
+
+ {ruleFormVariables.length === 0 ? (
+
+ هیچ متغیری انتخاب نشده است. از لیست زیر متغیرهای مورد نظر را اضافه کنید.
+
+ ) : (
+ ruleFormVariables.map((vKey, idx) => {
+ const curEventDef = eventDefinitions.find((ed) => ed.event === ruleFormEvent);
+ const varMeta = curEventDef?.variables.find((v) => v.key === vKey);
+ return (
+
+ {`{${idx}}`}:
+ {varMeta ? varMeta.label : vKey}
setIsUserDropdownOpen((prev) => !prev)}
- className="px-3 py-2 bg-amber-200/70 hover:bg-amber-200 text-amber-900 rounded-xl text-xs font-bold shrink-0 transition-all flex items-center gap-1 cursor-pointer"
+ onClick={() => {
+ const updated = [...ruleFormVariables];
+ updated.splice(idx, 1);
+ setRuleFormVariables(updated);
+ }}
+ className="text-gray-400 hover:text-rose-600 p-0.5 rounded"
+ title="حذف این متغیر"
>
-
- لیست کاربران
+
-
- {/* Dropdown list */}
- {isUserDropdownOpen && (
-
-
- انتخاب کاربر برای اضافه شدن به لیست شمارهها:
- setIsUserDropdownOpen(false)}
- className="text-gray-400 hover:text-gray-700 cursor-pointer"
- >
-
-
-
- {isLoadingUsers ? (
-
در حال بارگذاری کاربران...
- ) : systemUsers.length === 0 ? (
-
کاربری یافت نشد
- ) : (
- systemUsers.map((u) => {
- const uName = (u.firstName ? `${u.firstName} ${u.lastName || ''}` : 'بدون نام').trim();
- const uPhone = u.mobile || '';
- const isAlreadySelected = uPhone && ruleFormCustomPhone.includes(uPhone);
- const roleBadge = u.role === 'Admin' ? 'مدیر' : u.role === 'Vet' ? 'دامپزشک' : 'کاربر';
-
- return (
-
{
- if (!uPhone) {
- toast.error('این کاربر شماره همراه ثبتشده ندارد');
- return;
- }
- const currentPhones = ruleFormCustomPhone
- .split(/[,;\s]+/)
- .map((p) => p.trim())
- .filter(Boolean);
- if (currentPhones.includes(uPhone)) {
- // Remove
- const filtered = currentPhones.filter((p) => p !== uPhone);
- setRuleFormCustomPhone(filtered.join(' ، '));
- toast.success(`${uName} از گیرندگان حذف شد`);
- } else {
- // Add
- const next = [...currentPhones, uPhone];
- setRuleFormCustomPhone(next.join(' ، '));
- toast.success(`${uName} (${uPhone}) به گیرندگان اضافه شد`);
- }
- }}
- className={`w-full p-2.5 text-right flex items-center justify-between hover:bg-amber-50/50 transition-colors text-xs cursor-pointer ${
- isAlreadySelected ? 'bg-amber-50' : ''
- }`}
- >
-
-
- {uName.charAt(0)}
-
-
-
- {uName}
-
- {roleBadge}
-
-
-
- {uPhone || 'بدون شماره'}
-
-
-
-
- {isAlreadySelected ? (
-
- انتخاب شده
-
- ) : (
-
- + افزودن
-
- )}
-
-
- );
- })
- )}
-
- )}
-
-
-
- setRuleFormCustomPhone(e.target.value)}
- placeholder="مثلاً: 09123456789 (برای چند شماره با کاما یا ویرگول جدا کنید)"
- className="w-full border border-amber-300 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-amber-500 text-xs font-mono font-bold bg-white"
- dir="ltr"
- />
-
-
-
- 💡 میتوانید از جستجوی بالا مدیر یا کاربر مدنظرتان را انتخاب کنید یا شمارهها را مستقیماً تایپ نمایید.
-
-
- )}
-
- {/* Pattern ID Selection */}
-
-
-
- شناسه الگوی ملی پیامک (Pattern Body ID) *
-
- انتخاب از الگوها یا درج دستی
-
-
-
- {/* Select from registered patterns */}
-
- setRuleFormPatternId(e.target.value)}
- className="w-full border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-amber-500 text-xs font-bold bg-white"
- >
- انتخاب از لیست الگوهای موجود...
- {patterns.map((p) => (
-
- #{p.id} - {p.title}
-
- ))}
-
-
-
- {/* Or Manual Body ID Input */}
-
- setRuleFormPatternId(e.target.value)}
- placeholder="یا وارد کردن شناسه پترن جدید (مثلاً: 508081)"
- className="w-full border border-gray-200 rounded-xl p-2.5 outline-none focus:ring-2 focus:ring-amber-500 text-xs font-mono font-bold bg-white"
- dir="ltr"
- />
-
-
-
- {/* Show Preview of Selected Pattern Text if found */}
- {(() => {
- const selPat = patterns.find((p) => String(p.id) === String(ruleFormPatternId));
- if (!selPat) return null;
- return (
-
- متن الگو:
- {selPat.body}
-
);
- })()}
-
+ })
+ )}
+
- {/* Dynamic Variables Mapper */}
-
-
-
- تخصیص متغیرها به ترتیب پارامترهای پترن ({'{0}'}, {'{1}'}, ...)
-
-
- کلیک روی متغیرها برای افزودن یا حذف
+ {/* Available Variables for the selected event */}
+ {(() => {
+ const curEventDef = eventDefinitions.find((ed) => ed.event === ruleFormEvent);
+ if (!curEventDef || curEventDef.variables.length === 0) return null;
+
+ return (
+
+
+ متغیرهای در دسترس برای رویداد «{curEventDef.label}»:
-
-
- {/* Current mapped variables */}
-
- {ruleFormVariables.length === 0 ? (
-
- هیچ متغیری انتخاب نشده است. از لیست زیر متغیرهای مورد نظر را اضافه کنید.
-
- ) : (
- ruleFormVariables.map((vKey, idx) => {
- const curEventDef = eventDefinitions.find((ed) => ed.event === ruleFormEvent);
- const varMeta = curEventDef?.variables.find((v) => v.key === vKey);
- return (
-
- {`{${idx}}`}:
- {varMeta ? varMeta.label : vKey}
- {
- const updated = [...ruleFormVariables];
- updated.splice(idx, 1);
- setRuleFormVariables(updated);
- }}
- className="text-gray-400 hover:text-rose-600 p-0.5 rounded"
- title="حذف این متغیر"
- >
-
-
-
- );
- })
- )}
-
-
- {/* Available Variables for the selected event */}
- {(() => {
- const curEventDef = eventDefinitions.find((ed) => ed.event === ruleFormEvent);
- if (!curEventDef || curEventDef.variables.length === 0) return null;
-
- return (
-
-
- متغیرهای در دسترس برای رویداد «{curEventDef.label}»:
-
-
+
{curEventDef.variables.map((v) => (
setIsRuleModalOpen(false)}
- className="px-5 py-2.5 rounded-xl border border-gray-200 text-xs font-bold text-gray-600 hover:bg-gray-50"
+ className="px-5 py-2.5 rounded-xl border border-gray-200 text-xs font-bold text-gray-600 hover:bg-gray-50 cursor-pointer"
>
انصراف
{editingRule ? 'ذخیره تغییرات سناریو' : 'ثبت و فعالسازی سناریو'}
-
-
- )}
+
{/* Modal: Add New Pattern */}
- {isAddModalOpen && (
-
-
-
-
-
- درج الگوی جدید در سامانه ملی پیامک
-
-
setIsAddModalOpen(false)}
- className="text-gray-400 hover:text-gray-600 p-1 rounded-lg"
- >
-
-
+
setIsAddModalOpen(false)}
+ title="درج الگوی جدید در سامانه ملی پیامک"
+ icon={Plus}
+ maxWidth="xl"
+ >
+