129 lines
4.7 KiB
JavaScript
129 lines
4.7 KiB
JavaScript
// ------------------------------------------------------------------------
|
||
// components/RestoreModal.js - "Already subscribed? Restore access" popup.
|
||
//
|
||
// Replaces the old standalone restore.php page. Collects the subscriber's
|
||
// email, POSTs it to restore.php (now a JSON endpoint), and on an active
|
||
// subscription flips the app into Pro mode in place - no navigation.
|
||
//
|
||
// Reuses the .welcome-* overlay/card styling; input/error styling is inline
|
||
// to avoid new CSS. All open/close state lives in useAppState.
|
||
//
|
||
// Props:
|
||
// onClose - called when the user dismisses (×, backdrop, or Esc)
|
||
// setIsPro - state setter from useAppState; called with true on success
|
||
// ------------------------------------------------------------------------
|
||
|
||
import { h } from '../../vendor/preact.js';
|
||
import { useEffect, useState } from '../../vendor/preact-hooks.js';
|
||
import htm from '../../vendor/htm.js';
|
||
import { Wordmark } from './Wordmark.js';
|
||
|
||
const html = htm.bind(h);
|
||
|
||
export function RestoreModal({ onClose, setIsPro }) {
|
||
const [email, setEmail] = useState('');
|
||
const [error, setError] = useState('');
|
||
const [busy, setBusy] = useState(false);
|
||
|
||
// Dismiss on Esc.
|
||
useEffect(() => {
|
||
const onKey = (e) => { if (e.key === 'Escape') onClose(); };
|
||
document.addEventListener('keydown', onKey);
|
||
return () => document.removeEventListener('keydown', onKey);
|
||
}, [onClose]);
|
||
|
||
const submit = async (e) => {
|
||
e.preventDefault();
|
||
if (busy) return;
|
||
setError('');
|
||
setBusy(true);
|
||
try {
|
||
const res = await fetch('/restore.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||
body: new URLSearchParams({ email }),
|
||
});
|
||
const data = await res.json();
|
||
if (data.active) {
|
||
try {
|
||
localStorage.setItem('sunscope_pro', '1');
|
||
if (data.mode) localStorage.setItem('sunscope_pro_mode', data.mode);
|
||
if (data.customer) localStorage.setItem('sunscope_pro_customer', data.customer);
|
||
localStorage.setItem('sunscope_pro_checked_at', String(Date.now()));
|
||
} catch (err) { /* ignore */ }
|
||
setIsPro(true);
|
||
onClose();
|
||
return;
|
||
}
|
||
setError(data.error || 'No active SunScope Extra subscription found for that email.');
|
||
} catch (err) {
|
||
setError('Something went wrong. Please try again.');
|
||
}
|
||
setBusy(false);
|
||
};
|
||
|
||
return html`
|
||
<div class="welcome-overlay" onClick=${onClose}>
|
||
<div class="welcome-card" role="dialog" aria-modal="true" aria-labelledby="restore-title"
|
||
onClick=${(e) => e.stopPropagation()} style=${{ maxWidth: '420px' }}>
|
||
<button class="welcome-close" aria-label="Close" onClick=${onClose}>×</button>
|
||
<div class="welcome-head">
|
||
<${Wordmark} />
|
||
<div style=${{
|
||
fontFamily: 'Manrope, sans-serif',
|
||
fontWeight: 600,
|
||
fontSize: '11px',
|
||
letterSpacing: '0.12em',
|
||
textTransform: 'uppercase',
|
||
color: '#7a5c2a',
|
||
marginTop: '10px',
|
||
}}>See the world the way your skin does.</div>
|
||
</div>
|
||
<h2 class="welcome-title" id="restore-title" style=${{ textAlign: 'center', fontSize: '1.3rem', marginBottom: '8px' }}>
|
||
Restore your access
|
||
</h2>
|
||
<p class="welcome-intro">
|
||
Enter the email you subscribed with and we'll unlock${' '}
|
||
<strong>SunScope Extra</strong> on this browser.
|
||
</p>
|
||
<form onSubmit=${submit}>
|
||
<input
|
||
type="email"
|
||
required
|
||
autofocus
|
||
placeholder="your@email.com"
|
||
value=${email}
|
||
onInput=${(e) => setEmail(e.target.value)}
|
||
style=${{
|
||
width: '100%',
|
||
padding: '11px 14px',
|
||
border: '1.5px solid #c9b08a',
|
||
borderRadius: '8px',
|
||
fontFamily: 'Manrope, sans-serif',
|
||
fontSize: '0.95rem',
|
||
background: '#fff',
|
||
color: '#1e1208',
|
||
marginBottom: '12px',
|
||
outline: 'none',
|
||
boxSizing: 'border-box',
|
||
}}
|
||
/>
|
||
${error && html`<div style=${{
|
||
padding: '10px 14px',
|
||
background: '#fdf0e0',
|
||
border: '1px solid #c9b08a',
|
||
borderLeft: '3px solid #c8922a',
|
||
borderRadius: '6px',
|
||
fontFamily: 'Manrope, sans-serif',
|
||
fontSize: '0.85rem',
|
||
color: '#4a3420',
|
||
marginBottom: '12px',
|
||
}}>${error}</div>`}
|
||
<button class="welcome-cta" type="submit" disabled=${busy}>
|
||
${busy ? 'Checking…' : 'Restore access →'}
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>`;
|
||
}
|