feat: implement OTP sending via Kavenegar VerifyLookup and add image cropping modal

- Added support for sending OTP messages using Kavenegar's VerifyLookup method, ensuring compliance with specified token formatting and template usage.
- Updated OtpService to handle new template parameters and fallback mechanisms.
- Introduced ImageCropModal component for cropping images with a user-friendly interface.
- Created utility function for cropping images and generating downloadable files.
This commit is contained in:
hamed
2026-07-04 21:50:55 +03:30
parent 1bb9cedd22
commit 6ade17a5b4
10 changed files with 822 additions and 2185 deletions
+3 -1
View File
@@ -484,7 +484,9 @@ Updated template with `status: "rejected"`.
> تگ‌ها: `otp`، `payment`، `clinic_invitation`، `pre_registration`، `notification_mobile`، `welcome`، `secretary`، `doctor_appointment`. (پیامک قالبیِ کاربر با تگ `user_template` جداگانه از طریق `POST /api/v1/sms/template` مدیریت می‌شود.)
>
> تگ `otp`: کد تأیید ورود. placeholderها: `{code}` (کد ۵ رقمی)، `{site}` (**اختیاری** — اسم سایتِ شهرِ درخواست‌کننده برای شخصی‌سازی متن). مقدار `{site}` از فیلد `domain` در `POST /api/v1/user/send-code` گرفته می‌شود: `site_name` شهرِ متناظر در جدول `cities`؛ اگر `domain` نیامد یا شهر پیدا نشد → «کلینیک پرو». برای فعال‌کردن اسم سایت کافی است `{site}` را در body قالب بگذارید (مثلاً `کد تأیید شما در {site}: {code}`)؛ اگر نگذارید، اسم سایت نمایش داده نمی‌شود. متن از قالب DB (fallback به `DEFAULTS`).
> تگ `otp`: کد تأیید ورود. مقدار `site` از فیلد `domain` در `POST /api/v1/user/send-code` گرفته می‌شود: `site_name` شهرِ متناظر در جدول `cities`؛ اگر `domain` نیامد یا شهر پیدا نشد → «کلینیک پرو».
>
> **ارسال OTP از طریق Kavenegar VerifyLookup (پترن):** اگر متغیر محیطی `KAVENEGAR_OTP_TEMPLATE` (نام پترن مصوب پنل کاوه‌نگار) ست باشد، OTP با `verify/lookup.json` ارسال می‌شود — **متنِ پیام از پترن ثابتِ مصوب کاوه‌نگار می‌آید، نه از body قابل‌ویرایش DB** (body صرفاً برای رکورد `SmsLog` رندر می‌شود). map توکن‌ها طبق قانون فاصله‌ی کاوه‌نگار: `token` = کد ۵ رقمی (بدون فاصله)، `token10` = اسم سایت (تا ۵ فاصله مجاز). اگر پترن مصوب فقط `%token` داشته باشد، `token10` نادیده گرفته می‌شود (اسم سایت نمایش داده نمی‌شود). اگر `KAVENEGAR_OTP_TEMPLATE` خالی باشد → fallback به ارسال متن‌آزاد `send` با متنِ قالب DB (placeholderهای `{code}`، `{site}`). نیازمند اشتراک advanced کاوه‌نگار.
>
> تگ `welcome`: پیامک خوش‌آمد که هنگام افزودن پزشک/کلینیک توسط نماینده (`POST /api/v1/representation/doctor|clinic`) به‌صورت async به موبایل پزشک/مالک ارسال می‌شود. متن فعلاً ثابت است (نام + `site_name`)، نه از قالب DB.
>