forked from Tadrisino/MathApp_frontend
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,6 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { motion } from 'motion/react';
|
||||
import { Brain, Check, ChevronDown, Lock, PartyPopper, Play, Sparkles } from 'lucide-react';
|
||||
import { Brain, Check, ChevronDown, Crown, Lock, PartyPopper, Play, Sparkles } from 'lucide-react';
|
||||
import { api, type HomeNode, type HomeUnit } from '@/api';
|
||||
import { useAppData } from '@/state/AppData';
|
||||
import { findContinue, unitColor, unitProgress } from '@/state/curriculum';
|
||||
@@ -115,6 +115,8 @@ function UnitCard({
|
||||
const complete = p.total > 0 && p.done === p.total;
|
||||
const untouched = unit.nodes.every((n) => n.status === 'locked');
|
||||
const Icon = iconFor(unit.nodes[0]?.icon, index);
|
||||
const nav = useNav();
|
||||
const premium = unit.requiresSubscription;
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
@@ -123,7 +125,7 @@ function UnitCard({
|
||||
className="overflow-hidden rounded-2xl bg-white"
|
||||
style={{ border: `2px solid ${open ? color : '#e9e6f7'}`, boxShadow: open ? `0 4px 0 ${color}40` : '0 2px 0 #e9e6f7' }}
|
||||
>
|
||||
<button type="button" onClick={onToggle} aria-expanded={open} className="flex w-full items-center gap-3 px-3.5 py-3.5 text-right">
|
||||
<button type="button" onClick={premium ? () => nav.push({ name: 'subscription', view: 'subscription' }) : onToggle} aria-expanded={open} className="flex w-full items-center gap-3 px-3.5 py-3.5 text-right">
|
||||
<span
|
||||
className="flex h-[52px] w-[52px] flex-shrink-0 items-center justify-center rounded-2xl"
|
||||
style={{ backgroundColor: complete ? color : `${color}22`, color: complete ? '#fff' : color, opacity: untouched ? 0.55 : 1 }}
|
||||
@@ -133,6 +135,7 @@ function UnitCard({
|
||||
<span className="min-w-0 flex-1">
|
||||
<span className="block text-[11px] font-bold" style={{ color }}>
|
||||
{complete ? <><PartyPopper size={12} className="mb-0.5 ml-1 inline" />تموم شد</> : `${toFa(p.total)} جزیره`}
|
||||
{premium && <span className="mr-1.5 inline-flex items-center gap-0.5 rounded-full bg-[#FFF4D6] px-1.5 text-[10px] text-[#A86A00]"><Crown size={10} /> با اشتراک</span>}
|
||||
</span>
|
||||
<span className="block text-sm font-black leading-6 text-ink"><MathText text={unit.title} /></span>
|
||||
<span className="mt-1 flex items-center gap-2">
|
||||
@@ -140,9 +143,9 @@ function UnitCard({
|
||||
<span className="text-[11px] text-muted">{toFa(p.done)}/{toFa(p.total)}</span>
|
||||
</span>
|
||||
</span>
|
||||
<ChevronDown size={18} className={`flex-shrink-0 text-muted transition-transform ${open ? 'rotate-180' : ''}`} />
|
||||
{premium ? <Crown size={18} className="flex-shrink-0 text-[#E0A200]" /> : <ChevronDown size={18} className={`flex-shrink-0 text-muted transition-transform ${open ? 'rotate-180' : ''}`} />}
|
||||
</button>
|
||||
{open && (
|
||||
{open && !premium && (
|
||||
<ul className="flex flex-col gap-1.5 border-t border-line bg-[#fbfaff] px-3 py-3">
|
||||
{unit.nodes.map((node, ni) => (
|
||||
<NodeRow
|
||||
|
||||
Reference in New Issue
Block a user