Subscription store, paywall on locked units, profile subscription bar, Tadrisino branding
- Store opens with two choices (subscription / question packs); 3- and 6-month cards show per-month price and saving. - Units that need a subscription show a crown badge and open the store; a 402 from the quiz goes there too. «ادامه بده» skips locked units. - Profile: subscription card with an animated days-left bar (planDurationDays). - BrandMark (SVG) on splash, home header and footer; copyright footer; floating math glyphs on splash. CSS transform/opacity only; honours reduced motion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Bell, ChevronLeft, Coins, Flame, Hand, PartyPopper, Star } from 'lucide-react';
|
||||
import { Bell, ChevronLeft, Coins, Crown, Flame, Hand, PartyPopper, Star } from 'lucide-react';
|
||||
import type { HomeNode } from '@/api';
|
||||
import { useAppData } from '@/state/AppData';
|
||||
import { findContinue, unitColor, unitProgress } from '@/state/curriculum';
|
||||
@@ -11,6 +11,8 @@ import { EmptyState, ErrorState, LoadingState, Screen, Sep } from '@/components/
|
||||
import { onWhite, shade } from '@/lib/color';
|
||||
import { toFa } from '@/lib/format';
|
||||
import { MathText } from '@/lib/MathText';
|
||||
import { BrandFooter } from '@/components/BrandFooter';
|
||||
import { BrandMark } from '@/components/BrandMark';
|
||||
|
||||
/**
|
||||
* خانه = خودِ مسیر، مثلِ دولینگو: همهی فصلهای پایه پشتِ هم، و جزیرهی فعلی با
|
||||
@@ -20,6 +22,8 @@ import { MathText } from '@/lib/MathText';
|
||||
export function HomeScreen() {
|
||||
const { profile, gradeTitle, summary, home, homeError, companion, unreadCount, refreshHome } = useAppData();
|
||||
const nav = useNav();
|
||||
// فصلِ غیرِ اول بیاشتراک: زدنِ جزیره یکراست فهرستِ اشتراکها را باز میکند.
|
||||
const paywall = () => nav.push({ name: 'subscription', view: 'subscription' });
|
||||
const [openNode, setOpenNode] = useState<{ node: HomeNode; color: string } | null>(null);
|
||||
const currentRef = useRef<HTMLDivElement>(null);
|
||||
const scrolled = useRef(false);
|
||||
@@ -52,6 +56,7 @@ export function HomeScreen() {
|
||||
<Screen>
|
||||
<header className="relative z-20 flex-shrink-0 rounded-b-[28px] bg-coral px-4 pb-4 pt-safe text-white shadow-md shadow-coral/20">
|
||||
<div className="flex items-center gap-2 pt-4">
|
||||
<BrandMark size={26} withName={false} />
|
||||
{gradeTitle && (
|
||||
<button type="button" onClick={() => nav.switchTab('profile')} className="hit rounded-full bg-white/20 px-3 py-1.5 text-xs font-black active:scale-95">
|
||||
{gradeTitle}
|
||||
@@ -111,6 +116,7 @@ export function HomeScreen() {
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="text-[11px] font-bold text-white/80">
|
||||
فصلِ {toFa(i + 1)}<Sep />{toFa(p.done)} از {toFa(p.total)} جزیره
|
||||
{unit.requiresSubscription && <span className="mr-1.5 inline-flex h-5 items-center gap-1 rounded-full bg-white/25 px-2 align-middle leading-none"><Crown size={11} /> با اشتراک</span>}
|
||||
{isCurrentUnit && <span className="mr-1.5 inline-flex h-5 items-center rounded-full bg-white/25 px-2 align-middle leading-none">الان اینجایی</span>}
|
||||
</div>
|
||||
<div className="mt-0.5 truncate text-[15px] font-black">{unit.title.replace(/^فصل\s*\S+\s*[::]\s*/, '')}</div>
|
||||
@@ -123,13 +129,14 @@ export function HomeScreen() {
|
||||
nodes={unit.nodes}
|
||||
color={color}
|
||||
currentId={isCurrentUnit ? cont!.node.id : null}
|
||||
onOpen={(node) => setOpenNode({ node, color })}
|
||||
onStart={(node) => nav.push({ name: 'quiz', nodeId: node.id })}
|
||||
onOpen={(node) => (unit.requiresSubscription ? paywall() : setOpenNode({ node, color }))}
|
||||
onStart={(node) => (unit.requiresSubscription ? paywall() : nav.push({ name: 'quiz', nodeId: node.id }))}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
})}
|
||||
<BrandFooter />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user