steelforesight/src/pages/Home/sections/PlansSection.tsx

351 lines
12 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useState } from 'react'
import { plans } from '@/data/plans'
/* ─── Star icon (for "popular" badge) ──────────────── */
function Star() {
return (
<svg width="11" height="11" viewBox="0 0 16 16" fill="currentColor" style={{ flexShrink: 0 }}>
<path d="M8 1l2.09 4.23L14.78 6l-3.39 3.31.8 4.69L8 11.77 3.81 14l.8-4.69L1.22 6l4.69-.77L8 1z" />
</svg>
)
}
/* ─── Check icon ──────────────────────────────────── */
function Check({ featured }: { featured: boolean }) {
return (
<svg
width="14" height="14" viewBox="0 0 16 16" fill="none"
style={{ flexShrink: 0, marginTop: 3 }}
>
<path
d="M3 8.5l3 3 7-7"
stroke={featured ? 'rgba(244,239,231,0.85)' : 'var(--ink)'}
strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"
/>
</svg>
)
}
/* ─── Plan tagline lookup ─────────────────────────── */
const TAGLINE: Record<string, string> = {
individual: 'برای کارشناسان و محققان',
organizational: 'برای شرکت‌ها و سازمان‌ها',
ministry: 'برای نهادهای دولتی',
}
/* ─── Individual plan card ────────────────────────── */
function PlanCard({ plan, isMiddle }: { plan: (typeof plans)[0]; isMiddle: boolean }) {
const [hovered, setHovered] = useState(false)
const featured = plan.featured
return (
<div
style={{
position: 'relative',
background: featured ? 'var(--ink)' : 'var(--paper)',
border: '1px solid var(--rule-thin)',
display: 'flex',
flexDirection: 'column',
boxShadow: isMiddle ? '0 12px 40px rgba(26,23,18,0.14)' : 'none',
zIndex: isMiddle ? 1 : 0,
transform: isMiddle ? 'translateY(-4px)' : 'none',
}}
>
{/* "Popular" badge — top right */}
{plan.badge && (
<div style={{
position: 'absolute',
top: 12,
right: 12,
background: 'var(--red)',
color: 'white',
padding: '5px 10px',
fontSize: 10,
fontWeight: 700,
letterSpacing: '1.5px',
display: 'flex',
alignItems: 'center',
gap: 5,
zIndex: 10,
}}>
<Star />
{plan.badge}
</div>
)}
{/* Header */}
<div style={{
background: featured ? 'rgba(255,255,255,0.04)' : 'var(--paper-2)',
borderBottom: featured ? '1px solid rgba(255,255,255,0.08)' : '1px solid var(--rule-thin)',
padding: '20px 22px',
}}>
<div style={{
fontSize: 15,
fontWeight: 800,
color: featured ? 'var(--paper)' : 'var(--ink)',
marginBottom: 4,
}}>
{plan.name}
</div>
<p style={{
fontSize: 12,
color: featured ? 'rgba(244,239,231,0.55)' : 'var(--ink-4)',
marginBottom: 14,
fontWeight: 400,
lineHeight: 1.5,
}}>
{TAGLINE[plan.id]}
</p>
<div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
<span style={{
fontSize: 26,
fontWeight: 900,
letterSpacing: '-0.8px',
lineHeight: 1,
color: featured ? 'var(--paper)' : 'var(--ink)',
fontVariantNumeric: 'tabular-nums',
}}>
{plan.price === 0 ? 'تماس' : plan.price.toLocaleString('fa-IR')}
</span>
{plan.price > 0 ? (
<span style={{
fontSize: 11,
color: featured ? 'rgba(244,239,231,0.55)' : 'var(--ink-4)',
fontWeight: 500,
}}>
تومان / {plan.period}
</span>
) : (
<span style={{
fontSize: 11,
color: featured ? 'rgba(244,239,231,0.55)' : 'var(--ink-4)',
fontWeight: 500,
}}>
· {plan.period}
</span>
)}
</div>
</div>
{/* Features */}
<div style={{
padding: '18px 22px',
display: 'flex',
flexDirection: 'column',
gap: 10,
flex: 1,
}}>
{plan.features.map(f => (
<div key={f} style={{ display: 'flex', alignItems: 'flex-start', gap: 9 }}>
<Check featured={featured} />
<span style={{
fontSize: 12,
lineHeight: 1.55,
color: featured ? 'rgba(244,239,231,0.8)' : 'var(--ink-3)',
fontWeight: 400,
}}>
{f}
</span>
</div>
))}
</div>
{/* CTA */}
<div style={{
borderTop: featured ? '1px solid rgba(255,255,255,0.08)' : '1px solid var(--rule-thin)',
padding: '12px 22px 14px',
}}>
<button
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
style={{
width: '100%',
padding: '10px',
border: featured
? 'none'
: hovered ? 'none' : '1px solid var(--ink)',
background: featured
? hovered ? 'var(--paper-2)' : 'var(--paper)'
: hovered ? 'var(--ink)' : 'transparent',
color: featured
? 'var(--ink)'
: hovered ? 'var(--paper)' : 'var(--ink)',
fontSize: 12,
fontWeight: 700,
fontFamily: 'Vazir, sans-serif',
cursor: 'pointer',
borderRadius: 0,
letterSpacing: '0.5px',
transition: 'background 180ms, color 180ms, border 180ms',
}}
>
{plan.ctaLabel}
</button>
</div>
</div>
)
}
/* ─── Enterprise bottom card ─────────────────────── */
const enterpriseFeatures = [
'پروژه‌های نامحدود',
'پشتیبانی تیمی اختصاصی',
'فاکتور رسمی سازمانی',
'بدون سقف توکن یا داده',
'دعوت اعضای نامحدود',
'قرارداد SLA معتبر',
'نقش‌های سفارشی کاربری',
'امنیت پیشرفته سازمانی',
'API اتصال به سیستم داخلی',
'گزارش‌دهی اختصاصی',
'کارگاه‌های تخصصی دوره‌ای',
'مشاوره راهبردی مستقیم',
]
function EnterpriseCard() {
const [hov, setHov] = useState(false)
return (
<div
style={{
border: '1px solid var(--rule-thin)',
background: 'var(--paper)',
padding: '28px 32px',
display: 'grid',
gap: '32px',
alignItems: 'start',
}}
className="grid grid-cols-2 max-md:grid-cols-1 max-md:gap-6 max-md:p-6"
>
{/* Left: description */}
<div>
<div style={{
fontSize: 10, fontWeight: 700, letterSpacing: '1.5px',
textTransform: 'uppercase', color: 'var(--ink-5)', marginBottom: 8,
}}>
وزارتخانه / سازمان دولتی
</div>
<h3 style={{
fontSize: 18, fontWeight: 900, letterSpacing: '-0.4px',
color: 'var(--ink)', marginBottom: 10,
}}>
راهکار سازمانی کامل
</h3>
<p style={{
fontSize: 12, lineHeight: 1.75, color: 'var(--ink-3)',
fontWeight: 400, marginBottom: 20,
}}>
به راهکارهای سفارشی، پشتیبانی اختصاصی یا قیمتگذاری حجمی نیاز دارید؟
با کارشناسان ما درباره پلن منحصربهفرد سازمانتان صحبت کنید.
</p>
<button
onMouseEnter={() => setHov(true)}
onMouseLeave={() => setHov(false)}
style={{
padding: '11px 24px',
border: '1px solid var(--ink)',
background: hov ? 'var(--ink)' : 'transparent',
color: hov ? 'var(--paper)' : 'var(--ink)',
fontSize: 12, fontWeight: 700,
fontFamily: 'Vazir, sans-serif',
cursor: 'pointer',
borderRadius: 0,
transition: 'background 180ms, color 180ms',
letterSpacing: '0.5px',
}}
>
تماس با تیم فروش
</button>
</div>
{/* Right: feature grid */}
<div
className="grid grid-cols-2 max-sm:grid-cols-1"
style={{ gap: '8px 18px' }}
>
{enterpriseFeatures.map(f => (
<div key={f} style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
<Check featured={false} />
<span style={{ fontSize: 11, color: 'var(--ink-3)', lineHeight: 1.4, fontWeight: 400 }}>
{f}
</span>
</div>
))}
</div>
</div>
)
}
/* ─── Section ────────────────────────────────────── */
export default function PlansSection() {
return (
<section style={{
background: 'var(--paper)',
}}>
<div className="max-w-6xl mx-auto px-12 py-16 max-md:px-5 max-md:py-12">
{/* Header */}
<div style={{ textAlign: 'center', marginBottom: 64 }}>
<div style={{
fontSize: 10, fontWeight: 700, letterSpacing: '2.5px',
textTransform: 'uppercase', color: 'var(--red)',
marginBottom: 12,
}}>
اشتراک و دسترسی
</div>
<h2 style={{
fontSize: 'clamp(22px, 2.4vw, 32px)',
fontWeight: 900,
letterSpacing: '-1px',
color: 'var(--ink)',
marginBottom: 10,
}}>
پلن مناسب خود را انتخاب کنید
</h2>
<p style={{
fontSize: 13, lineHeight: 1.7,
color: 'var(--ink-4)', fontWeight: 400,
maxWidth: 460, margin: '0 auto',
}}>
از دسترسی پایه برای پژوهشگران تا راهکار کامل برای وزارتخانهها
هر سطحی از نیاز را پوشش میدهیم.
</p>
</div>
{/* 3-col plan cards */}
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(3, 1fr)',
gap: 16,
marginBottom: 20,
alignItems: 'stretch',
}}
className="mq-stack max-md:grid-cols-1 max-md:gap-4"
>
{plans.map((plan, idx) => (
<PlanCard
key={plan.id}
plan={plan}
isMiddle={idx === 1}
/>
))}
</div>
{/* Enterprise bottom card */}
<EnterpriseCard />
{/* Money-back note */}
<div style={{
textAlign: 'center',
marginTop: 18,
fontSize: 11,
color: 'var(--ink-5)',
fontWeight: 400,
}}>
&nbsp; ضمانت بازگشت وجه ۱۴ روزه &nbsp;·&nbsp; بدون قرارداد اجباری
</div>
</div>
</section>
)
}