No diacritics or written ezafe ی in the UI; map without the speech banner, companions cheering along the path; familiar payment sheet with gateway logos and per-channel methods; account deletion moved under «حساب کاربری»

- Text: kasra/fatha/damma/shadda/sukun/hamza-above and «ه‌ی» ezafe removed from every user-visible string (comments untouched); tanwin kept. Stale copy fixed (question packs are no longer sold), awkward onboarding sentences rewritten, سؤال → سوال. plainPersian() in MathText cleans the live tutor stream.
- Home: the mascot + speech bubble header is gone; the selected companion hops beside the current island and sits at every third bend (CSS transform animations only).
- Checkout: order summary, payment-method rows with Zarinpal/Bazaar icons and radio, amount on the pay button, lock trust line, darker overlay. paymentMethods in config.js per channel (web: zarinpal, app: zarinpal+bazaar by default).
- Profile: «ورود با حساب دیگر» removed (it was logout); new «حساب کاربری» sheet shows phone/ID and holds «حذف حساب کاربری»; logout is a red row. Delete sheet tells Bazaar subscribers to cancel renewal in Bazaar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 16:55:17 +03:30
parent 4a661f504f
commit ca96a91dee
48 changed files with 492 additions and 337 deletions

30
src/lib/paymentMethods.ts Normal file
View File

@@ -0,0 +1,30 @@
import { inAndroidApp } from './bazaar';
export type PaymentMethod = 'zarinpal' | 'bazaar';
const KNOWN: PaymentMethod[] = ['zarinpal', 'bazaar'];
/**
* پیش‌فرض: در مرورگر فقط زرین‌پال (خریدِ بازار بیرون از اپِ اندروید ممکن نیست)، داخلِ اپ هر دو، زرین‌پال اول.
* برای نسخه‌ای که فقط در کافه‌بازار منتشر می‌شود، `app: ["bazaar"]` در dist/config.js؛ build لازم نیست.
*/
const DEFAULTS: Record<'web' | 'app', PaymentMethod[]> = {
web: ['zarinpal'],
app: ['zarinpal', 'bazaar'],
};
/**
* روش‌های پرداختِ این‌جا (مرورگر یا اپ)، به ترتیبِ نمایش. نامِ ناشناخته در config.js نادیده گرفته نمی‌شود که
* بی‌صدا یک روش گم شود: در کنسول خطا می‌دهد و فهرستِ پیش‌فرض به کار می‌رود.
*/
export function enabledPaymentMethods(): PaymentMethod[] {
const channel = inAndroidApp() ? 'app' : 'web';
const configured = window.__TADRISINO_CONFIG__?.paymentMethods?.[channel];
if (!configured) return DEFAULTS[channel];
const unknown = configured.filter((m) => !KNOWN.includes(m as PaymentMethod));
if (unknown.length || !configured.length) {
console.error(`config.js: paymentMethods.${channel} نامعتبر است`, configured);
return DEFAULTS[channel];
}
return configured as PaymentMethod[];
}