This commit is contained in:
2026-03-22 23:31:19 -04:00
parent 64522764cb
commit 2d164958d8
4 changed files with 111 additions and 4 deletions

View File

@@ -16,7 +16,9 @@ export default function ProfileModal({ onClose }) {
const [newPw, setNewPw] = useState('');
const [confirmPw, setConfirmPw] = useState('');
const [loading, setLoading] = useState(false);
const [tab, setTab] = useState('profile'); // 'profile' | 'password'
const [tab, setTab] = useState('profile'); // 'profile' | 'password' | 'notifications'
const [pushTesting, setPushTesting] = useState(false);
const [pushResult, setPushResult] = useState(null);
const [hideAdminTag, setHideAdminTag] = useState(!!user?.hide_admin_tag);
const [allowDm, setAllowDm] = useState(user?.allow_dm !== 0);
@@ -101,6 +103,7 @@ export default function ProfileModal({ onClose }) {
<div className="flex gap-2" style={{ marginBottom: 20 }}>
<button className={`btn btn-sm ${tab === 'profile' ? 'btn-primary' : 'btn-secondary'}`} onClick={() => setTab('profile')}>Profile</button>
<button className={`btn btn-sm ${tab === 'password' ? 'btn-primary' : 'btn-secondary'}`} onClick={() => setTab('password')}>Change Password</button>
<button className={`btn btn-sm ${tab === 'notifications' ? 'btn-primary' : 'btn-secondary'}`} onClick={() => { setTab('notifications'); setPushResult(null); }}>Notifications</button>
</div>
{tab === 'profile' && (
@@ -167,6 +170,56 @@ export default function ProfileModal({ onClose }) {
</div>
)}
{tab === 'notifications' && (
<div className="flex-col gap-3">
<div style={{ fontSize: 14, color: 'var(--text-secondary)', lineHeight: 1.5 }}>
<p style={{ margin: '0 0 8px' }}>Tap <strong>Send Test Notification</strong> to trigger a push to this device. The notification will arrive shortly if everything is configured correctly.</p>
<p style={{ margin: 0 }}>If it doesn't arrive, check:<br/>
• Notification permission granted (browser prompt)<br/>
• Android Settings → Apps → RosterChirp → Notifications → Enabled<br/>
• App is backgrounded when the test fires
</p>
</div>
<button
className="btn btn-primary"
disabled={pushTesting}
onClick={async () => {
setPushTesting(true);
setPushResult(null);
try {
const { results } = await api.testPush();
setPushResult({ ok: true, results });
} catch (e) {
setPushResult({ ok: false, error: e.message });
} finally {
setPushTesting(false);
}
}}
>
{pushTesting ? 'Sending' : 'Send Test Notification'}
</button>
{pushResult && (
<div style={{
padding: '10px 12px',
borderRadius: 8,
background: pushResult.ok ? 'var(--surface-variant)' : '#fdecea',
color: pushResult.ok ? 'var(--text-primary)' : '#c62828',
fontSize: 13,
}}>
{pushResult.ok ? (
pushResult.results.map((r, i) => (
<div key={i}>
<strong>{r.device}</strong>: {r.status === 'sent' ? ' Sent check your device for the notification' : `✗ Failed — ${r.error}`}
</div>
))
) : (
<div>✗ {pushResult.error}</div>
)}
</div>
)}
</div>
)}
{tab === 'password' && (
<div className="flex-col gap-3">
<div className="flex-col gap-1">