feat: redesign pricing section with beta notice and i18n pricing
- 4-card layout: Free / Monthly / Quarterly / Lifetime License - zh shows RMB ¥, en shows $ with localized prices - Monthly ¥19.9 (edu ¥12.9 / $1.99), Quarterly ¥49.9 (edu ¥29.9 / $7.99) - Diagonal corner ribbons (green "限时免费") on Monthly & Quarterly - Desktop card renamed to "永久授权 / Lifetime License" with Coming Soon ribbon - Desktop tag badge distinguishes it as a native offline app - Beta notice banner: all plans free during beta, no payment required - CTA unified to "免费体验 / Try Free" linking to /app - Cards use flex-column + align-items:stretch for consistent equal height Made-with: Cursor
This commit is contained in:
@@ -2,6 +2,7 @@ import { useState, useEffect, useRef } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { useLanguage } from '../../contexts/LanguageContext';
|
||||
import { useAuth } from '../../contexts/AuthContext';
|
||||
import AuthModal from '../AuthModal';
|
||||
|
||||
export default function MarketingNavbar() {
|
||||
const { language, setLanguage } = useLanguage();
|
||||
@@ -11,6 +12,7 @@ export default function MarketingNavbar() {
|
||||
const [scrolled, setScrolled] = useState(false);
|
||||
const [activeSection, setActiveSection] = useState('');
|
||||
const [userMenuOpen, setUserMenuOpen] = useState(false);
|
||||
const [showAuthModal, setShowAuthModal] = useState(false);
|
||||
const userMenuRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Scroll: sticky style + active nav section
|
||||
@@ -52,90 +54,94 @@ export default function MarketingNavbar() {
|
||||
: [];
|
||||
|
||||
return (
|
||||
<nav style={{ opacity: scrolled ? 1 : undefined }}>
|
||||
<div className="nav-inner">
|
||||
<Link to="/" className="nav-logo">
|
||||
<div className="logo-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="2">
|
||||
<path d="M4 6h16M4 10h10M4 14h12M4 18h8" />
|
||||
</svg>
|
||||
</div>
|
||||
<span style={{ fontFamily: "'Lora', serif" }}>TexPixel</span>
|
||||
</Link>
|
||||
<>
|
||||
<nav style={{ opacity: scrolled ? 1 : undefined }}>
|
||||
<div className="nav-inner">
|
||||
<Link to="/" className="nav-logo">
|
||||
<div className="logo-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="2">
|
||||
<path d="M4 6h16M4 10h10M4 14h12M4 18h8" />
|
||||
</svg>
|
||||
</div>
|
||||
<span style={{ fontFamily: "'Lora', serif" }}>TexPixel</span>
|
||||
</Link>
|
||||
|
||||
<ul className="nav-links">
|
||||
{navLinks.map((link) => (
|
||||
<li key={link.href}>
|
||||
<Link
|
||||
to={link.href}
|
||||
className={location.pathname === link.href ? 'active' : ''}
|
||||
>
|
||||
{link.label}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
{anchorLinks.map((link) => (
|
||||
<li key={link.href}>
|
||||
<a
|
||||
href={link.href}
|
||||
className={activeSection === link.href.slice(1) ? 'active' : ''}
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<ul className="nav-links">
|
||||
{navLinks.map((link) => (
|
||||
<li key={link.href}>
|
||||
<Link
|
||||
to={link.href}
|
||||
className={location.pathname === link.href ? 'active' : ''}
|
||||
>
|
||||
{link.label}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
{anchorLinks.map((link) => (
|
||||
<li key={link.href}>
|
||||
<a
|
||||
href={link.href}
|
||||
className={activeSection === link.href.slice(1) ? 'active' : ''}
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<div className="nav-right">
|
||||
<button
|
||||
className="lang-switch"
|
||||
onClick={() => setLanguage(language === 'zh' ? 'en' : 'zh')}
|
||||
>
|
||||
{language === 'zh' ? 'EN' : '中文'}
|
||||
</button>
|
||||
<div className="nav-right">
|
||||
<button
|
||||
className="lang-switch"
|
||||
onClick={() => setLanguage(language === 'zh' ? 'en' : 'zh')}
|
||||
>
|
||||
{language === 'zh' ? 'EN' : '中文'}
|
||||
</button>
|
||||
|
||||
{user ? (
|
||||
<div className="nav-user" ref={userMenuRef} style={{ position: 'relative' }}>
|
||||
<div
|
||||
className="nav-avatar"
|
||||
onClick={() => setUserMenuOpen((o) => !o)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8">
|
||||
<circle cx="12" cy="8" r="4" />
|
||||
<path d="M4 20c0-4 3.6-7 8-7s8 3 8 7" />
|
||||
</svg>
|
||||
</div>
|
||||
{userMenuOpen && (
|
||||
<div className="nav-user-menu" style={{ display: 'block' }}>
|
||||
<div className="nav-menu-divider" />
|
||||
<Link to="/app" className="nav-menu-item" onClick={() => setUserMenuOpen(false)}>
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8">
|
||||
<rect x="2" y="3" width="20" height="14" rx="2" />
|
||||
<path d="M8 21h8M12 17v4" />
|
||||
</svg>
|
||||
{language === 'zh' ? '启动应用' : 'Launch App'}
|
||||
</Link>
|
||||
<div className="nav-menu-divider" />
|
||||
<button
|
||||
className="nav-menu-item nav-menu-logout"
|
||||
onClick={() => { signOut(); setUserMenuOpen(false); }}
|
||||
style={{ background: 'none', border: 'none', width: '100%', textAlign: 'left', cursor: 'pointer' }}
|
||||
>
|
||||
{language === 'zh' ? '退出登录' : 'Sign Out'}
|
||||
</button>
|
||||
{user ? (
|
||||
<div className="nav-user" ref={userMenuRef} style={{ position: 'relative' }}>
|
||||
<div
|
||||
className="nav-avatar"
|
||||
onClick={() => setUserMenuOpen((o) => !o)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8">
|
||||
<circle cx="12" cy="8" r="4" />
|
||||
<path d="M4 20c0-4 3.6-7 8-7s8 3 8 7" />
|
||||
</svg>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="nav-login-btn">
|
||||
<Link to="/app" className="btn-cta" style={{ display: 'inline-block', lineHeight: '52px', padding: '0 24px', textDecoration: 'none' }}>
|
||||
{language === 'zh' ? '免费试用' : 'Try Free'}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
{userMenuOpen && (
|
||||
<div className="nav-user-menu" style={{ display: 'block' }}>
|
||||
<div className="nav-menu-divider" />
|
||||
<Link to="/app" className="nav-menu-item" onClick={() => setUserMenuOpen(false)}>
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8">
|
||||
<rect x="2" y="3" width="20" height="14" rx="2" />
|
||||
<path d="M8 21h8M12 17v4" />
|
||||
</svg>
|
||||
{language === 'zh' ? '启动应用' : 'Launch App'}
|
||||
</Link>
|
||||
<div className="nav-menu-divider" />
|
||||
<button
|
||||
className="nav-menu-item nav-menu-logout"
|
||||
onClick={() => { signOut(); setUserMenuOpen(false); }}
|
||||
style={{ background: 'none', border: 'none', width: '100%', textAlign: 'left', cursor: 'pointer' }}
|
||||
>
|
||||
{language === 'zh' ? '退出登录' : 'Sign Out'}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="nav-login-btn">
|
||||
<button className="btn-cta" onClick={() => setShowAuthModal(true)}>
|
||||
{language === 'zh' ? '登录' : 'Login'}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
|
||||
{showAuthModal && <AuthModal onClose={() => setShowAuthModal(false)} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user