Import source: cshare-app/src/pages/PricingPage

Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
arsam
2026-09-18 23:15:02 +03:30
parent e68704c335
commit d1b2470fd3
+171
View File
@@ -0,0 +1,171 @@
import { useNavigate } from 'react-router-dom';
import { CheckIcon, ZapIcon, ShieldIcon, GlobeIcon } from '../components/Icons';
const PLANS = [
{
name: 'Free',
price: null,
desc: 'For casual sharing. No card required.',
cta: 'Get started free',
ctaPath: '/upload',
primary: false,
features: [
'5 uploads per month',
'100 MB max per file',
'7-day link expiry',
'Basic view tracking',
'Copy share link',
],
missing: ['Custom expiry', 'Password protection', 'Analytics dashboard', 'Priority support'],
},
{
name: 'Pro',
price: 9,
desc: 'For individuals who share files seriously.',
cta: 'Start Pro trial',
ctaPath: '/upload',
primary: true,
features: [
'Unlimited uploads',
'500 MB max per file',
'Custom expiry (1h → 90 days)',
'Full analytics dashboard',
'Password-protected links',
'Download tracking',
'Priority support',
],
missing: ['Team dashboard', 'SSO / SAML'],
},
{
name: 'Team',
price: 24,
desc: 'For small teams that need shared oversight.',
cta: 'Talk to us',
ctaPath: '/contact',
primary: false,
features: [
'Everything in Pro',
'Up to 10 seats',
'Shared team dashboard',
'Centralized billing',
'Role-based permissions',
'API access',
'SLA + dedicated support',
],
missing: [],
},
];
export default function PricingPage() {
const navigate = useNavigate();
return (
<div className="page-enter" style={{ minHeight: '100vh' }}>
{/* Header */}
<section style={{ padding: 'clamp(64px, 10vh, 100px) 24px 48px', textAlign: 'center', position: 'relative', overflow: 'hidden' }}>
<div style={{ position: 'absolute', inset: 0, background: 'radial-gradient(ellipse 70% 60% at 50% 0%, rgba(74,144,255,0.06) 0%, transparent 70%)', pointerEvents: 'none' }} />
<div style={{ position: 'relative', zIndex: 1, maxWidth: '640px', margin: '0 auto' }}>
<div style={{ display: 'inline-flex', alignItems: 'center', gap: '8px', marginBottom: '20px' }}>
<span style={{ color: 'var(--accent)', fontFamily: 'var(--font-heading)', fontWeight: 700 }}>//</span>
<span style={{ color: 'var(--text-muted)', fontFamily: 'var(--font-heading)', fontWeight: 600, fontSize: '0.75rem', letterSpacing: '0.12em', textTransform: 'uppercase' }}>Pricing</span>
</div>
<h1 className="heading-lg" style={{ marginBottom: '16px' }}>Simple, honest pricing.</h1>
<p style={{ color: 'var(--text-secondary)', fontSize: '1.0625rem', lineHeight: 1.7 }}>
No per-file fees, no storage surprises. Pay for what you need, cancel any time.
</p>
</div>
</section>
{/* Plan cards */}
<section style={{ padding: '0 24px 80px', maxWidth: '1080px', margin: '0 auto' }}>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: '20px', alignItems: 'start' }}>
{PLANS.map((plan) => (
<div
key={plan.name}
className="card"
style={{
padding: '32px',
position: 'relative',
border: plan.primary ? '1px solid var(--accent-border)' : '1px solid var(--border-subtle)',
boxShadow: plan.primary ? '0 0 40px rgba(74,144,255,0.08)' : 'none',
}}
>
{plan.primary && (
<>
<div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: '2px', background: 'linear-gradient(90deg, transparent, var(--accent), transparent)' }} />
<div style={{
position: 'absolute', top: '16px', right: '16px',
padding: '3px 10px', background: 'var(--accent)', borderRadius: '999px',
fontSize: '0.6875rem', fontFamily: 'var(--font-body)', fontWeight: 600,
color: '#fff', letterSpacing: '0.04em',
}}>
Most popular
</div>
</>
)}
<div style={{ marginBottom: '24px' }}>
<div style={{ fontFamily: 'var(--font-heading)', fontWeight: 700, fontSize: '1rem', color: 'var(--text-secondary)', letterSpacing: '0.04em', textTransform: 'uppercase', marginBottom: '12px' }}>
{plan.name}
</div>
<div style={{ display: 'flex', alignItems: 'baseline', gap: '4px', marginBottom: '8px' }}>
{plan.price ? (
<>
<span style={{ fontFamily: 'var(--font-heading)', fontWeight: 800, fontSize: '2.75rem', letterSpacing: '-0.04em', lineHeight: 1 }}>
${plan.price}
</span>
<span style={{ color: 'var(--text-muted)', fontSize: '0.875rem' }}>/mo</span>
</>
) : (
<span style={{ fontFamily: 'var(--font-heading)', fontWeight: 800, fontSize: '2.75rem', letterSpacing: '-0.04em', lineHeight: 1 }}>
Free
</span>
)}
</div>
<p style={{ color: 'var(--text-muted)', fontSize: '0.875rem', lineHeight: 1.6 }}>{plan.desc}</p>
</div>
<button
className={`btn ${plan.primary ? 'btn-primary' : 'btn-secondary'}`}
style={{ width: '100%', marginBottom: '28px' }}
onClick={() => navigate(plan.ctaPath)}
>
{plan.cta}
</button>
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
{plan.features.map((f) => (
<div key={f} style={{ display: 'flex', alignItems: 'center', gap: '10px', fontSize: '0.875rem', color: 'var(--text-secondary)' }}>
<CheckIcon size={14} style={{ color: 'var(--success)', flexShrink: 0 }} />
{f}
</div>
))}
{plan.missing.map((f) => (
<div key={f} style={{ display: 'flex', alignItems: 'center', gap: '10px', fontSize: '0.875rem', color: 'var(--text-muted)', opacity: 0.5 }}>
<div style={{ width: '14px', height: '14px', borderRadius: '50%', border: '1.5px solid var(--border)', flexShrink: 0 }} />
{f}
</div>
))}
</div>
</div>
))}
</div>
{/* FAQ strip */}
<div style={{ marginTop: '64px', display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: '20px' }}>
{[
{ icon: <ZapIcon size={18} />, q: 'Can I upgrade or downgrade?', a: 'Yes, any time. Changes take effect immediately and are prorated to the day.' },
{ icon: <ShieldIcon size={18} />, q: 'What happens when a free link expires?', a: 'The file and link are permanently deleted from our servers. No recovery.' },
{ icon: <GlobeIcon size={18} />, q: 'Do recipients need an account?', a: 'Never. Anyone with the link can download — no sign-up wall on their end.' },
].map(({ icon, q, a }) => (
<div key={q} className="card" style={{ padding: '24px' }}>
<div style={{ color: 'var(--accent)', marginBottom: '10px' }}>{icon}</div>
<div style={{ fontFamily: 'var(--font-heading)', fontWeight: 600, fontSize: '0.9375rem', marginBottom: '8px' }}>{q}</div>
<p style={{ color: 'var(--text-secondary)', fontSize: '0.875rem', lineHeight: 1.65 }}>{a}</p>
</div>
))}
</div>
</section>
</div>
);
}