import React, { useState, useEffect } from 'react'; import { useNavigate, useLocation, Link } from 'react-router-dom'; import api from '../api'; import { useAuth } from '../App'; interface LibraryEntry { plugin_id: number; name: string; category: string | null; preview_path: string | null; dev_name: string; amount_cents: number; purchased_at: string; } const ProfilePage = () => { const { user, login, logout, refreshUser } = useAuth(); const navigate = useNavigate(); const location = useLocation(); const [activeTab, setActiveTab] = useState('accountDetails'); useEffect(() => { const params = new URLSearchParams(location.search); const tab = params.get('tab'); if (tab === 'payouts') setActiveTab('payouts'); else if (tab === 'security') setActiveTab('security'); else if (tab === 'danger') setActiveTab('danger'); else if (tab === 'library') setActiveTab('library'); else setActiveTab('accountDetails'); }, [location]); const [formData, setFormData] = useState({ username: '', email: '', password: '' }); const [message, setMessage] = useState({ text: '', type: '' }); const [isStripeLoading, setIsStripeLoading] = useState(false); // Library state const [library, setLibrary] = useState([]); const [libraryLoading, setLibraryLoading] = useState(false); const [libraryError, setLibraryError] = useState(null); useEffect(() => { refreshUser?.(); }, []); useEffect(() => { if (user) { setFormData(prev => ({ ...prev, username: user.username || '', email: user.email || '' })); } }, [user]); // Fetch library when tab becomes active useEffect(() => { if (activeTab !== 'library') return; setLibraryLoading(true); setLibraryError(null); api.get('/user/library') .then(res => setLibrary(Array.isArray(res.data) ? res.data : [])) .catch(() => setLibraryError('Failed to load your library. Please try again.')) .finally(() => setLibraryLoading(false)); }, [activeTab]); const showMessage = (text: string, isError = false) => { setMessage({ text, type: isError ? 'error' : 'success' }); setTimeout(() => setMessage({ text: '', type: '' }), 4000); }; const handleUpdate = async (e: React.FormEvent, endpoint: string, payload: object) => { e.preventDefault(); try { const res = await api.post(endpoint, payload); if (res.data.token) login(res.data.token); showMessage(res.data.message || 'Updated successfully!'); } catch (err: any) { showMessage(err.response?.data?.error || 'Update failed.', true); } }; const handleLogout = () => { logout(); navigate('/login'); }; const handleConnectStripe = async () => { setIsStripeLoading(true); try { const res = await api.post('/stripe/onboard'); if (res.data.url) window.location.href = res.data.url; } catch (err: any) { showMessage(err.response?.data?.error || 'Failed to start Stripe onboarding.', true); setIsStripeLoading(false); } }; const handleGoToStripe = async () => { setIsStripeLoading(true); try { const res = await api.get('/stripe/dashboard'); if (res.data.url) window.location.href = res.data.url; } catch (err: any) { showMessage(err.response?.data?.error || 'Failed to open Stripe dashboard.', true); setIsStripeLoading(false); } }; const handleDeleteAccount = async () => { if (!window.confirm('Are you sure you want to delete your account? This action is irreversible.')) return; try { await api.delete('/user'); logout(); navigate('/login'); } catch (err: any) { showMessage(err.response?.data?.error || 'Failed to delete account.', true); } }; return (

User Profile

{message.text && (

{message.text}

)}
{/* ── Account Details ── */} {activeTab === 'accountDetails' && (

Change Account Details

handleUpdate(e, '/user/change-username', { newUsername: formData.username })}>
setFormData({ ...formData, username: e.target.value })} />
handleUpdate(e, '/user/change-email', { newEmail: formData.email })} style={{ marginTop: '2rem' }}>
setFormData({ ...formData, email: e.target.value })} />
)} {/* ── Library ── */} {activeTab === 'library' && (

My Library

{library.length > 0 && ( {library.length} plugin{library.length !== 1 ? 's' : ''} )}

Your purchased plugins. Click to visit the plugin page and download.

{libraryLoading && (
{[...Array(3)].map((_, i) => (
))}
)} {libraryError && (
⚠️ {libraryError}
)} {!libraryLoading && !libraryError && library.length === 0 && (
📦

Your library is empty

Purchased plugins will appear here, ready to download anytime.

Browse Plugins
)} {!libraryLoading && !libraryError && library.length > 0 && (
{library.map((entry, idx) => ( {/* Preview image */}
{entry.preview_path ? ( {entry.name} ) : (
{entry.name.charAt(0).toUpperCase()}
)} {/* Owned badge */}
Owned
{/* Category tag */} {entry.category && (
{entry.category}
)}
{/* Info */}
{entry.name}
by {entry.dev_name}
€{(entry.amount_cents / 100).toFixed(2)} {new Date(entry.purchased_at).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric', })}
{/* Hover arrow */}
→
))}
)}
)} {/* ── Payouts ── */} {activeTab === 'payouts' && (

Payout Settings

Connect your Stripe account to receive payouts for your plugin sales.

{user?.stripe_ready ? ( /* ── Fully connected ── */ <>
Stripe account connected
) : user?.stripe_account_id ? ( /* ── Account created but onboarding not finished ── */ <>
Finish Stripe connection

Your Stripe account was created but hasn't been fully activated yet.
Complete the onboarding to start receiving payouts.

) : ( /* ── No account at all ── */ <>
No Stripe account linked.
)}
)} {/* ── Security ── */} {activeTab === 'security' && (

Change Password

handleUpdate(e, '/user/settings', { newPassword: formData.password })}>
setFormData({ ...formData, password: e.target.value })} />
)} {/* ── Danger Zone ── */} {activeTab === 'danger' && (

Danger Zone

Proceeding will wipe your balance and all uploaded plugins from PumpkinMC.

)}
); }; export default ProfilePage;