const Profile = () => { const {user, setUser, logout, toast, go, tweaks, setTweaks} = useApp(); const t = window.t || (k => k); const [editProfile, setEditProfile] = useState(false); const [editPass, setEditPass] = useState(false); const [prof, setProf] = useState({name: user.name || '', license: user.license || '', phone: user.phone || ''}); const [pw, setPw] = useState({current: '', new1: '', new2: ''}); const [busy, setBusy] = useState(false); const [tickets, setTickets] = useState([]); const [ticketMsg, setTicketMsg] = useState(''); const [loadingTickets, setLoadingTickets] = useState(false); const [expandedTk, setExpandedTk] = useState({}); // Refresh user data + load tickets on mount useEffect(() => { api.me().then(r => { if (r && r.user) { setUser(u => ({...u, ...r.user})); try { localStorage.setItem('ap_user', JSON.stringify({...user, ...r.user})); } catch(e){} } }).catch(() => {}); api.supportMine().then(d => setTickets(d.tickets || [])).catch(() => {}); }, []); // Stripe redirect handling useEffect(() => { const params = new URLSearchParams(window.location.search); const stripe = params.get('stripe'); if (stripe === 'success') { toast(t('prof.upgrade_ok') || 'Plan actualizado correctamente'); // Refresh user data to get updated plan from backend api.me().then(r => { if (r && r.user) { setUser(u => ({...u, ...r.user})); try { localStorage.setItem('ap_user', JSON.stringify({...user, ...r.user})); } catch(e){} } }).catch(() => {}); } if (stripe === 'cancel') { toast(t('prof.upgrade_cancel') || 'Pago cancelado'); } if (stripe) window.history.replaceState({}, '', window.location.pathname); }, []); const handleUpgrade = async () => { setBusy(true); try { const r = await api.stripeCheckout(); if (r && r.url) window.location.href = r.url; } catch(e) { toast(t('common.error') + ': ' + (e.error || t('common.unknown'))); } setBusy(false); }; const handleManageSub = async () => { setBusy(true); try { const r = await api.stripePortal(); if (r && r.url) window.location.href = r.url; } catch(e) { toast(t('common.error') + ': ' + (e.error || t('common.unknown'))); } setBusy(false); }; const saveProfile = async () => { if (!prof.name.trim()) { toast(t('prof.name_required')); return; } setBusy(true); try { const r = await api.updateProfile(prof); if (r && r.user) { setUser(u => ({...u, name: r.user.name, license: r.user.license, phone: r.user.phone})); try { const stored = JSON.parse(localStorage.getItem('ap_user')||'{}'); localStorage.setItem('ap_user', JSON.stringify({...stored, name: r.user.name, license: r.user.license, phone: r.user.phone})); } catch(e){} } setEditProfile(false); toast(t('prof.profile_updated')); } catch(e) { toast(t('common.error') + ': ' + (e.error || t('common.unknown'))); } setBusy(false); }; const savePassword = async () => { if (!pw.current) { toast(t('prof.enter_current')); return; } if (pw.new1.length < 8) { toast(t('prof.pass_min8')); return; } if (pw.new1 !== pw.new2) { toast(t('prof.pass_mismatch')); return; } setBusy(true); try { await api.changePassword({current: pw.current, new: pw.new1}); setEditPass(false); setPw({current: '', new1: '', new2: ''}); toast(t('prof.pass_updated')); } catch(e) { toast(e.error === 'current_password_wrong' ? t('prof.pass_wrong') : t('common.error') + ': ' + (e.error || t('common.unknown'))); } setBusy(false); }; const sendTicket = async () => { if (!ticketMsg.trim()) { toast(t('prof.support_empty')); return; } setBusy(true); try { await api.supportSend(ticketMsg); setTicketMsg(''); toast(t('prof.support_sent')); // Reload tickets api.supportMine().then(d => setTickets(d.tickets || [])).catch(() => {}); } catch(e) { toast(t('common.error') + ': ' + (e.error || t('common.unknown'))); } setBusy(false); }; const planLabel = user.is_trialing ? 'Premium (prueba 7 días)' : user.plan === 'premium' ? 'Premium' : user.plan === 'gifted' ? 'Premium (cortesía)' : user.plan === 'admin' ? 'Admin' : 'Free'; const isPremium = user.plan === 'premium' || user.plan === 'gifted' || user.plan === 'admin'; return
{t('prof.your_account')}

{t('prof.title')}{' '} {t('prof.title2')}

{t('prof.subtitle')}

{/* Datos personales */}
{(user.name||'?')[0]}
{user.name}
{user.email}
{user.license &&
{user.license}
}
{!editProfile && }
{editProfile &&
setProf({...prof,name:e.target.value})}/>
setProf({...prof,phone:e.target.value})} placeholder="+34..."/>
}
{/* Cambiar contrasena */}

{t('prof.password')}

{!editPass && }
{editPass &&
setPw({...pw,current:e.target.value})}/>
setPw({...pw,new1:e.target.value})} placeholder="8+ caracteres"/>
setPw({...pw,new2:e.target.value})}/>
}
{/* Suscripcion */}

{t('prof.subscription')}

{planLabel}
{isPremium ? <>
{'\u221E'}
{user.is_trialing ? 'Periodo de prueba — 7 días gratis' : t('prof.unlimited')}
Planes
Envíos
Soporte
{user.plan === 'gifted' &&
{user.plan_until ? `Cortesía hasta ${new Date(user.plan_until * 1000).toLocaleDateString('es',{day:'2-digit',month:'long',year:'numeric'})}` : 'Cortesía vitalicia ♾'}
} {user.plan === 'premium' && user.has_subscription &&
} : <>
3
Planes
3
Envíos/mes
Soporte
{t('prof.go_premium')}
{t('prof.premium_desc')}
}
{t('prof.member_since')}
{user.created_at ? new Date(user.created_at*1000).toLocaleDateString('es',{day:'2-digit',month:'short',year:'numeric'}) : user.memberSince || '—'}
{isPremium && user.plan_until &&
{t('prof.renewal')}
{new Date(user.plan_until*1000).toLocaleDateString('es',{day:'2-digit',month:'short',year:'numeric'})}
}
{/* Idioma */}

{t('settings.language')}

{[{v:'es',l:'Español'},{v:'en',l:'English'}].map(l=>)}
{/* ENAIRE note */}

{t('prof.enaire_title')}

{t('prof.enaire_note')}

{/* Soporte */} {isPremium &&

{t('prof.support')}

{(() => { const openTicket = tickets.find(tk => tk.status !== 'closed'); const closedTickets = tickets.filter(tk => tk.status === 'closed'); const msgs = openTicket?.messages || []; const replyToTicket = async () => { if (!ticketMsg.trim() || !openTicket) return; setBusy(true); try { await api.supportReply(openTicket.id, ticketMsg); setTicketMsg(''); api.supportMine().then(d => setTickets(d.tickets || [])).catch(() => {}); } catch(e) { toast(t('common.error') + ': ' + (e.error || t('common.unknown'))); } setBusy(false); }; return <> {!openTicket ? <>

{t('prof.support_desc')}