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

View File

@@ -10,18 +10,18 @@ type Kind = 'question' | 'lesson';
const REASONS: Record<Kind, { id: string; label: string }[]> = {
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 }) {
<ThumbsDown size={16} strokeWidth={2.4} /> خوب نبود
</button>
<button type="button" onClick={() => setOpen(true)} className={`${base} ${idle}`}>
<Flag size={16} strokeWidth={2.4} /> گزارشِ ایراد
<Flag size={16} strokeWidth={2.4} /> گزارش ایراد
</button>
</div>
<ReportSheet open={open} kind={kind} id={id} onClose={() => setOpen(false)} />
@@ -121,11 +121,11 @@ function ReportSheet({ open, kind, id, onClose }: { open: boolean; kind: Kind; i
<textarea
value={note}
onChange={(e) => setNote(e.target.value.slice(0, 500))}
placeholder="توضیحِ بیشتر (اختیاری)"
placeholder="توضیح بیشتر (اختیاری)"
rows={2}
className="mb-4 w-full resize-none rounded-2xl border-2 border-line px-4 py-3 text-sm outline-none focus:border-coral"
/>
<PrimaryButton disabled={!reason} loading={sending} onClick={() => void send()}>ارسالِ گزارش</PrimaryButton>
<PrimaryButton disabled={!reason} loading={sending} onClick={() => void send()}>ارسال گزارش</PrimaryButton>
</Sheet>
);
}