Import source: app/src/pages/MembershipPage

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:25:19 +03:30
parent f08e69fd13
commit 8f4e3cfd4c
+92
View File
@@ -0,0 +1,92 @@
import { useState, useEffect } from 'react';
import { useNav, useAuth, useToast } from '../../teknav-ui.jsx';
import { iconNode } from '../../src/lib/icon.jsx';
import crownIcon from '../../src/assets/icons/crown.svg';
import bookOpenIcon from '../../src/assets/icons/book-open.svg';
import gradCapIcon from '../../src/assets/icons/graduation-cap.svg';
export function MembershipPage() {
const { navigate } = useNav();
const { user } = useAuth();
const toast = useToast();
const [loading, setLoading] = useState(false);
const [status, setStatus] = useState(null);
useEffect(() => {
fetch('/api/v1/membership/status', { credentials: 'include' })
.then((r) => r.ok ? r.json() : null)
.then((d) => d && setStatus(d))
.catch(() => {});
}, []);
const subscribe = async () => {
if (!user) { navigate('/login'); return; }
setLoading(true);
try {
const res = await fetch('/api/v1/membership/subscribe', {
method: 'POST', credentials: 'include',
headers: { 'Content-Type': 'application/json' },
});
const data = await res.json();
if (data.redirectUrl) {
window.location.href = data.redirectUrl;
} else {
toast(data.error === 'payment_unavailable' ? 'درگاه پرداخت در دسترس نیست' : 'خطا در اتصال به درگاه پرداخت');
setLoading(false);
}
} catch {
toast('خطا در ارتباط با سرور');
setLoading(false);
}
};
const isPremium = status?.active;
return (
<div style={{ paddingTop: 80, background: '#FAF7F0', minHeight: '100vh', fontFamily: 'Vazirmatn,sans-serif', direction: 'rtl' }}>
<div style={{ maxWidth: 900, margin: '0 auto', padding: '44px 24px' }}>
<h1 style={{ fontSize: 32, fontWeight: 900, color: '#263238', margin: '0 0 8px' }}>عضویت پریمیوم تکناو</h1>
<p style={{ color: '#5F6B6D', lineHeight: 1.9, marginBottom: 28 }}>
تجربه بدون تبلیغ، مقاله‌های اختصاصی، دوره‌های کوتاه و گزارش‌های عمیق برای خوانندگان حرفه‌ای.
</p>
{isPremium && (
<div style={{ background: '#0F6B7318', border: '1px solid #0F6B7340', borderRadius: 12, padding: '16px 20px', marginBottom: 28, color: '#0F6B73', fontWeight: 700 }}>
✓ شما در حال حاضر عضو ویژه هستید
{status?.expiresAt && ` — اعتبار تا ${new Date(status.expiresAt).toLocaleDateString('fa-IR')}`}
</div>
)}
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(240px,1fr))', gap: 16, marginBottom: 32 }}>
{[
[crownIcon, 'بدون تبلیغ', 'خواندن آرام و سریع‌تر بدون جایگاه‌های تبلیغاتی.'],
[bookOpenIcon, 'محتوای اختصاصی', 'تحلیل‌های عمیق‌تر و پرونده‌های تخصصی برای اعضا.'],
[gradCapIcon, 'تخفیف دوره‌ها', 'دسترسی زودتر و تخفیف روی دوره‌های فارسی تکناو.'],
].map(([icon, title, body]) => (
<section key={title} style={{ background: '#fff', border: '1px solid #E4DDD2', borderRadius: 12, padding: 20 }}>
<div style={{ fontSize: 24, marginBottom: 8 }}>{iconNode(icon)}</div>
<h2 style={{ margin: '0 0 8px', fontSize: 18, color: '#263238' }}>{title}</h2>
<p style={{ margin: 0, color: '#5F6B6D', lineHeight: 1.8 }}>{body}</p>
</section>
))}
</div>
{!isPremium && (
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: 13, color: '#5F6B6D', marginBottom: 16 }}>
سالانه — ۵۰۰,۰۰۰ تومان
</div>
<button onClick={subscribe} disabled={loading} style={{
background: 'linear-gradient(135deg, #D49A2A, #B8821E)', color: '#fff',
border: 'none', borderRadius: 10, padding: '14px 36px', fontSize: 16, fontWeight: 700,
cursor: loading ? 'not-allowed' : 'pointer', opacity: loading ? 0.7 : 1,
fontFamily: 'Vazirmatn,sans-serif',
}}>
{loading ? 'در حال اتصال به درگاه...' : 'شروع عضویت ویژه'}
</button>
</div>
)}
</div>
</div>
);
}