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>
|
<p id="display-name-status" class="text-xs mt-2 hidden"></p>
|
||||||
</section>
|
</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 -->
|
<!-- Password card -->
|
||||||
<section class="mb-6 rounded-xl bg-zinc-900 border border-zinc-800 p-5">
|
<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>
|
<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 ─────────────────────────────────────────────────────────────────────
|
// ── Init ─────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
loadMe();
|
loadMe();
|
||||||
loadStorage();
|
loadStorage();
|
||||||
|
loadEmail();
|
||||||
loadNavPrefs();
|
loadNavPrefs();
|
||||||
loadActivityDefaults();
|
loadActivityDefaults();
|
||||||
loadStravaCreds();
|
loadStravaCreds();
|
||||||
|
|||||||
Reference in New Issue
Block a user