diff --git a/README.md b/README.md index f578bb2..d189eb0 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,18 @@ VITE_DEV_PROXY_TARGET=https://mathapi.tadrisino2.ir - **سمتِ بک‌اند** هم دامنه‌ی تازه‌ی فرانت باید مجاز باشد (`FRONTEND_URL` در `.env` بک‌اند). جزئیات در `docs/operations.md` همان ریپو. +## روش‌های پرداخت + +برگه‌ی پرداخت روش‌ها را از `paymentMethods` در `dist/config.js` می‌خواند (`src/lib/paymentMethods.ts`)، جدا برای +مرورگر (`web`) و داخلِ اپِ اندروید (`app`)؛ مقدارها `"zarinpal"` و `"bazaar"`. پیش‌فرض: مرورگر فقط زرین‌پال، اپ هر دو. +نسخه‌ای که فقط در کافه‌بازار است: `paymentMethods: { app: ["bazaar"] }`؛ build لازم نیست، فقط کشِ CDNِ این فایل را پاک کنید. + +## متنِ فارسی + +هیچ اعرابی (کسره، فتحه، تشدید، …) و هیچ «ی»ِ اضافه‌ی نوشته‌شده («پایه‌ی سوم») به کاربر نمی‌رسد (تصمیمِ شرکت، +۲۰۲۶-۱۰-۱۴)؛ تنوین («قبلاً») می‌ماند. متنِ تازه را همین‌طور بنویسید. متنِ سرور را بک‌اند هنگامِ ساختنِ پاسخ پاک می‌کند +و `plainPersian` در `MathText` همان کار را برای پاسخِ زنده‌ی دستیار. + ## دیپلوی روی سرور (`~/mathapp_frontend_new`، که nginxِ `math.tadrisino2.ir` از `dist/`ش سرو می‌کند): diff --git a/index.html b/index.html index 0df6ad0..8d78ed4 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - + تدریسینو @@ -24,9 +24,9 @@ .boot-splash { position: fixed; inset: 0; z-index: 50; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 20px; background: #fff; } .boot-splash img { width: 144px; height: 144px; display: block; } - /* داخلِ اپِ اندروید اسپلشِ بومی روی صفحه است و سایت زیرش بار می‌شود؛ اسپلشِ وب نباید یک بار دیگر - «عوض شدن» نشان دهد. APKِ تازه (appReady دارد): اسپلشِ وب نامرئی است. APKِ قدیمی: فقط آیکون، - بی‌نام، تا کمتر از اسپلشِ سیستم فرق کند. */ + /* داخل اپ اندروید اسپلش بومی روی صفحه است و سایت زیرش بار می‌شود؛ اسپلش وب نباید یک بار دیگر + «عوض شدن» نشان دهد. APK تازه (appReady دارد): اسپلش وب نامرئی است. APK قدیمی: فقط آیکون، + بی‌نام، تا کمتر از اسپلش سیستم فرق کند. */ .in-app .boot-splash > * { visibility: hidden; } .in-old-app .boot-splash span { display: none; } .in-old-app .boot-splash img { width: 160px; height: 160px; } diff --git a/pay.html b/pay.html index 07a2463..f8c6b8c 100644 --- a/pay.html +++ b/pay.html @@ -20,7 +20,7 @@
-

داریم می‌ریم به درگاهِ پرداخت…

+

داریم می‌ریم به درگاه پرداخت…

رفتن به درگاه
diff --git a/public/config.js b/public/config.js index 91378a6..7679fdf 100644 --- a/public/config.js +++ b/public/config.js @@ -4,6 +4,10 @@ // برای جابه‌جا کردنِ بک‌اند بدونِ build دوباره، آدرسِ کامل را اینجا بنویسید: // apiBaseUrl: "https://api.new-domain.ir/api", // اگر CDN (آروان) جلوی سایت است، بعد از ویرایش کشِ این فایل را پاک کنید. +// +// paymentMethods: روش‌های پرداختی که برگه‌ی پرداخت نشان می‌دهد، به همین ترتیب؛ «zarinpal» و «bazaar». +// web = سایت در مرورگر، app = داخلِ اپِ اندروید. نسخه‌ی کافه‌بازار: app: ["bazaar"]. +// نبودنِ این کلید یعنی پیش‌فرضِ src/lib/paymentMethods.ts. window.__TADRISINO_CONFIG__ = { apiBaseUrl: "", }; diff --git a/src/api/http.ts b/src/api/http.ts index bc8a281..c31195e 100644 --- a/src/api/http.ts +++ b/src/api/http.ts @@ -254,7 +254,7 @@ export function createHttpClient(options: HttpClientOptions) { } catch (err) { if (opts.signal?.aborted) throw err; const timedOut = err instanceof DOMException && (err.name === 'TimeoutError' || err.name === 'AbortError'); - throw new ApiError(0, timedOut ? 'زمانِ درخواست تمام شد' : 'ارتباط با سرور برقرار نشد', {}, timedOut); + throw new ApiError(0, timedOut ? 'زمان درخواست تمام شد' : 'ارتباط با سرور برقرار نشد', {}, timedOut); } } diff --git a/src/app/MainApp.tsx b/src/app/MainApp.tsx index 639f6f0..2caf221 100644 --- a/src/app/MainApp.tsx +++ b/src/app/MainApp.tsx @@ -332,14 +332,14 @@ function PaymentResult({ payment }: { payment: PaymentReturn }) {
{paid ? : }

- {paid ? 'پرداخت موفق بود! 🎉' : state === 'unknown' ? 'وضعیتِ پرداخت معلوم نشد' : 'پرداخت انجام نشد'} + {paid ? 'پرداخت موفق بود! 🎉' : state === 'unknown' ? 'وضعیت پرداخت معلوم نشد' : 'پرداخت انجام نشد'}

{paid ? 'اشتراکت فعال شد؛ از الان قلب‌هات نامحدوده.' : state === 'unknown' - ? 'چند دقیقه‌ی دیگه از «پرداخت‌ها و فاکتورها» در پروفایل نگاه کن. اگه مبلغی کم شده، یا خریدت فعال می‌شه یا پول خودکار برمی‌گرده.' - : 'اگه مبلغی از حسابت کم شده، نگران نباش؛ طیِ چند ساعت خودکار برمی‌گرده یا اشتراکت فعال می‌شه.'} + ? 'چند دقیقه دیگه از «پرداخت‌ها و فاکتورها» در پروفایل نگاه کن. اگه مبلغی کم شده، یا خریدت فعال می‌شه یا پول خودکار برمی‌گرده.' + : 'اگه مبلغی از حسابت کم شده، نگران نباش؛ طی چند ساعت خودکار برمی‌گرده یا اشتراکت فعال می‌شه.'}

setOpen(false)}>باشه
diff --git a/src/assets/pay/bazaar.png b/src/assets/pay/bazaar.png new file mode 100644 index 0000000..2037bbb Binary files /dev/null and b/src/assets/pay/bazaar.png differ diff --git a/src/assets/pay/zarinpal.png b/src/assets/pay/zarinpal.png new file mode 100644 index 0000000..e37463a Binary files /dev/null and b/src/assets/pay/zarinpal.png differ diff --git a/src/components/BirthDatePicker.tsx b/src/components/BirthDatePicker.tsx index 9f83cd3..f087c25 100644 --- a/src/components/BirthDatePicker.tsx +++ b/src/components/BirthDatePicker.tsx @@ -102,15 +102,15 @@ export function BirthDatePicker({ return (
- setD(e.target.value ? +e.target.value : '')} className={`${select} ${tone(d)}`}> {Array.from({ length: days }, (_, i) => i + 1).map((n) => )} - setM(e.target.value ? +e.target.value : '')} className={`${select} ${tone(m)}`}> {JALALI_MONTHS.map((name, i) => )} - setY(e.target.value ? +e.target.value : '')} className={`${select} ${tone(y)}`}> {years.map((n) => )} diff --git a/src/components/BrandFooter.tsx b/src/components/BrandFooter.tsx index 375f0c3..8480a22 100644 --- a/src/components/BrandFooter.tsx +++ b/src/components/BrandFooter.tsx @@ -6,8 +6,8 @@ export function BrandFooter() { return ( ); } diff --git a/src/components/FeedbackBar.tsx b/src/components/FeedbackBar.tsx index 1402e76..bbec9ed 100644 --- a/src/components/FeedbackBar.tsx +++ b/src/components/FeedbackBar.tsx @@ -10,18 +10,18 @@ type Kind = 'question' | 'lesson'; const REASONS: Record = { question: [ - { id: 'wrong_answer', label: 'جوابِ درست اشتباهه' }, - { id: 'unclear', label: 'صورتِ سوال گنگه' }, - { id: 'typo', label: 'غلطِ تایپی داره' }, + { id: 'wrong_answer', label: 'جواب درست اشتباهه' }, + { id: 'unclear', label: 'صورت سوال گنگه' }, + { id: 'typo', label: 'غلط تایپی داره' }, { id: 'too_hard', label: 'برای این درس خیلی سخته' }, - { id: 'other', label: 'یه چیزِ دیگه' }, + { id: 'other', label: 'یه چیز دیگه' }, ], lesson: [ - { id: 'wrong_content', label: 'مطلبِ درس اشتباهه' }, + { id: 'wrong_content', label: 'مطلب درس اشتباهه' }, { id: 'unclear', label: 'توضیح گنگه' }, - { id: 'typo', label: 'غلطِ تایپی داره' }, + { id: 'typo', label: 'غلط تایپی داره' }, { id: 'bad_figure', label: 'شکل ایراد داره' }, - { id: 'other', label: 'یه چیزِ دیگه' }, + { id: 'other', label: 'یه چیز دیگه' }, ], }; @@ -72,7 +72,7 @@ export function FeedbackBar({ kind, id }: { kind: Kind; id: string }) { خوب نبود
setOpen(false)} /> @@ -121,11 +121,11 @@ function ReportSheet({ open, kind, id, onClose }: { open: boolean; kind: Kind; i