This commit is contained in:
2026-04-26 16:28:38 -05:00
parent a97f372a76
commit 32a00b3706
2 changed files with 119 additions and 6 deletions

View File

@@ -169,11 +169,106 @@ function modal(html) {
function renderCreateMailboxModal() {
const domain = state.selectedDomain || '';
const d = modal(`<h2>New mailbox</h2><form id="createForm" class="form-grid"><label>Email<input name="email" type="email" value="@${esc(domain)}" placeholder="@${esc(domain)}" required></label><label>Password<input name="password" type="password" value="" minlength="8" autocomplete="new-password" required></label><div><button>Create</button></div></form>`);
const input = d.querySelector('input[name="email"]');
input.focus();
input.setSelectionRange(0, 0);
d.querySelector('#createForm').onsubmit = guard(async e => { e.preventDefault(); const f = new FormData(e.target); await api('/api/mailboxes', { method:'POST', body: JSON.stringify({ email:f.get('email'), password:f.get('password') }) }); d.remove(); await loadDomains(false); render(); });
const d = modal(`
<h2>New mailbox</h2>
<div class="form-grid">
<label>
Email
<input
id="createEmail"
type="email"
value="@${esc(domain)}"
placeholder="@${esc(domain)}"
autocomplete="off"
required
>
</label>
<label>
Password
<input
id="createPassword"
type="password"
value=""
minlength="8"
autocomplete="new-password"
required
>
</label>
<div>
<button type="button" id="createMailboxSubmit">Create</button>
</div>
</div>
`);
const emailInput = d.querySelector('#createEmail');
const passwordInput = d.querySelector('#createPassword');
const submitButton = d.querySelector('#createMailboxSubmit');
emailInput.focus();
// Cursor before the @domain, so you can directly type "test".
try {
emailInput.setSelectionRange(0, 0);
} catch {
// Some browsers do not allow selection on email inputs.
}
const createMailbox = guard(async () => {
const email = String(emailInput.value || '').trim().toLowerCase();
const password = String(passwordInput.value || '');
if (!email || !email.includes('@')) {
throw new Error('Please enter a valid email address.');
}
if (!email.endsWith(`@${domain}`)) {
throw new Error(`Mailbox must belong to ${domain}.`);
}
if (password.length < 8) {
throw new Error('Password must have at least 8 characters.');
}
submitButton.disabled = true;
submitButton.textContent = 'Creating...';
await api('/api/mailboxes', {
method: 'POST',
body: JSON.stringify({
email,
password,
}),
});
d.remove();
state.message = `Mailbox created: ${email}`;
await loadDomains(false);
await loadMailboxes(true);
render();
});
submitButton.onclick = createMailbox;
passwordInput.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
event.preventDefault();
createMailbox();
}
});
emailInput.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
event.preventDefault();
passwordInput.focus();
}
});
}
function renderDeleteModal(email) {