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

@@ -40,7 +40,7 @@ export function StreakScreen() {
return (
<Screen>
<ScreenHeader title="زنجیره‌ی روزها" subtitle="هر روز حداقل یه درس، زنجیره‌ت رو زنده نگه می‌داره" color="#FF7A3D" back mascot={{ mood: 'excited', size: 56 }} />
<ScreenHeader title="زنجیره روزها" subtitle="هر روز حداقل یه درس، زنجیره‌ت رو زنده نگه می‌داره" color="#FF7A3D" back mascot={{ mood: 'excited', size: 56 }} />
<ScreenBody className="flex flex-col gap-4">
{calendar.loading ? (
<LoadingState />
@@ -50,7 +50,7 @@ export function StreakScreen() {
<>
<div className="grid grid-cols-2 gap-3">
{[
{ label: 'زنجیره‌ی فعلی', value: calendar.data.currentStreak },
{ label: 'زنجیره فعلی', value: calendar.data.currentStreak },
{ label: 'بیشترین زنجیره', value: calendar.data.longestStreak },
].map((s, i) => (
<div key={s.label} className="flex flex-col items-center rounded-3xl border border-line bg-white py-4">
@@ -106,18 +106,18 @@ function StreakGoal({ current, doneToday, lost }: { current: number; doneToday:
// زنجیره‌ی صفر: «۳ روز دیگه می‌شه زنجیره‌ی ۳ روزه» هدفی دور بود؛ قدمِ امروز کوچک و روشن گفته می‌شود.
// زنجیره‌ی روشن و امروزِ خالی: یادآوریِ این‌که امروز چیزی مانده تا زنجیره نسوزد.
const today = current === 0 && lost > 0
? `زنجیره‌ی ${toFa(lost)} روزه‌ت یخ زد! امروز یه درس بزن تا دوباره آتیشش روشن بشه.`
? `زنجیره ${toFa(lost)} روزه‌ت یخ زد! امروز یه درس بزن تا دوباره آتیشش روشن بشه.`
: current === 0
? 'امروز فقط یه درس یا یه جزیره تموم کن تا زنجیره‌ت روشن بشه.'
: !doneToday
? `امروز هنوز تمرین نکردی؛ یه درس بزن تا زنجیره‌ی ${toFa(current)} روزه‌ت نسوزه.`
? `امروز هنوز تمرین نکردی؛ یه درس بزن تا زنجیره ${toFa(current)} روزه‌ت نسوزه.`
: null;
return (
<div className="rounded-3xl border border-line bg-[#FFF3E8] px-4 py-3">
{today && <p className="mb-1 text-xs font-bold leading-6 text-[#B4501C]">{today}</p>}
<p className="text-sm font-black leading-7 text-ink">
{reached ? <><Flame size={16} fill="#FF7A3D" className="mb-0.5 ml-1 inline text-orange" />{toFa(current)} روزه‌ای! </> : null}
{next ? `${toFa(next - current)} روز دیگه می‌شه زنجیره‌ی ${toFa(next)} روزه.` : 'از همه‌ی نقطه‌عطف‌ها رد شدی، افسانه‌ای!'}
{next ? `${toFa(next - current)} روز دیگه می‌شه زنجیره ${toFa(next)} روزه.` : 'از همه نقطه‌عطف‌ها رد شدی، افسانه‌ای!'}
</p>
{next && (
<div className="mt-2 h-2 overflow-hidden rounded-full bg-white">