feat: email field in settings — lets users set address for self-service password reset
This commit is contained in:
@@ -51,6 +51,25 @@ import Base from '../../layouts/Base.astro';
|
||||
<p id="display-name-status" class="text-xs mt-2 hidden"></p>
|
||||
</section>
|
||||
|
||||
<!-- Email card -->
|
||||
<section class="mb-6 rounded-xl bg-zinc-900 border border-zinc-800 p-5">
|
||||
<h2 class="text-sm font-semibold text-zinc-400 uppercase tracking-wider mb-1">Email</h2>
|
||||
<p class="text-xs text-zinc-500 mb-4">Used to receive a reset link when you forget your password.</p>
|
||||
<form id="email-form" class="flex gap-2 items-end">
|
||||
<div class="flex-1">
|
||||
<label class="block text-xs text-zinc-500 mb-1" for="email-input">Email address</label>
|
||||
<input id="email-input" type="email" autocomplete="email"
|
||||
class="w-full px-3 py-2 rounded-lg bg-zinc-800 border border-zinc-700 text-white placeholder-zinc-500 focus:outline-none focus:border-[--accent] text-sm"
|
||||
placeholder="you@example.com" />
|
||||
</div>
|
||||
<button type="submit"
|
||||
class="px-4 py-2 rounded-lg text-sm bg-zinc-700 hover:bg-zinc-600 text-white transition-colors shrink-0">
|
||||
Save
|
||||
</button>
|
||||
</form>
|
||||
<p id="email-status" class="text-xs mt-2 hidden"></p>
|
||||
</section>
|
||||
|
||||
<!-- Password card -->
|
||||
<section class="mb-6 rounded-xl bg-zinc-900 border border-zinc-800 p-5">
|
||||
<h2 class="text-sm font-semibold text-zinc-400 uppercase tracking-wider mb-4">Password</h2>
|
||||
@@ -602,10 +621,48 @@ import Base from '../../layouts/Base.astro';
|
||||
}
|
||||
});
|
||||
|
||||
// ── Email ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
const emailForm = document.getElementById('email-form') as HTMLFormElement;
|
||||
const emailInput = document.getElementById('email-input') as HTMLInputElement;
|
||||
const emailStatus = document.getElementById('email-status') as HTMLElement;
|
||||
|
||||
async function loadEmail() {
|
||||
const authUrl: string = (window as any).__bincioAuthUrl ?? '';
|
||||
if (!authUrl) return; // single-user / no bincio-auth
|
||||
try {
|
||||
const r = await fetch(`${authUrl}/api/me/email`, { credentials: 'include' });
|
||||
if (r.ok) {
|
||||
const { email } = await r.json();
|
||||
if (email) emailInput.value = email;
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
emailForm.addEventListener('submit', async e => {
|
||||
e.preventDefault();
|
||||
const authUrl: string = (window as any).__bincioAuthUrl ?? '';
|
||||
if (!authUrl) { setStatus(emailStatus, 'Not available on this instance.', false); return; }
|
||||
const email = emailInput.value.trim();
|
||||
try {
|
||||
const r = await fetch(`${authUrl}/api/me/email`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email }),
|
||||
});
|
||||
const d = await r.json().catch(() => ({}));
|
||||
setStatus(emailStatus, r.ok ? 'Saved.' : (d.detail ?? 'Failed.'), r.ok);
|
||||
} catch {
|
||||
setStatus(emailStatus, 'Could not reach server.', false);
|
||||
}
|
||||
});
|
||||
|
||||
// ── Init ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
loadMe();
|
||||
loadStorage();
|
||||
loadEmail();
|
||||
loadNavPrefs();
|
||||
loadActivityDefaults();
|
||||
loadStravaCreds();
|
||||
|
||||
Reference in New Issue
Block a user