{% extends "base.html" %}
{% block title %}Create an account{% endblock %}
{% block chrome %}{% endblock %}
{% block content %}
<form class="card" id="signup-form">
<h1>Create an account</h1>
<p class="muted">This creates an organisation with you as its owner.</p>
<label>Email
<input type="email" name="email" autocomplete="username" required autofocus>
</label>
<label>Organisation
<input type="text" name="org_name" autocomplete="organization"
placeholder="Optional - we'll use your address otherwise">
</label>
<label>Password
{# minlength matches auth.MIN_PASSWORD_LENGTH. The browser check is a
courtesy; hash_password enforces it, and that is the one that counts. #}
<input type="password" name="password" autocomplete="new-password"
minlength="12" required>
<span class="hint">At least 12 characters. Length beats punctuation.</span>
</label>
<p class="error" id="signup-error" hidden></p>
<button type="submit" id="signup-submit">Create account</button>
{% if google_enabled() %}
<div class="divider"><span>or</span></div>
<a class="button-secondary" href="/auth/google/start">Continue with Google</a>
{% endif %}
<p class="muted">Already have one? <a href="/login">Sign in</a>.</p>
</form>
{# Replaces the form rather than sitting beside it: leaving a filled-in sign-up
form on screen after it succeeded invites a second submission. #}
<div class="card" id="signup-done" hidden>
<h1>Check your inbox</h1>
<p>We've sent a confirmation link to <strong id="signup-email"></strong>.
Open it within a day to finish setting up your account.</p>
<p class="muted">Nothing arrived?
<button type="button" class="linkbtn" id="resend">Send it again</button>
</p>
<p class="note" id="resent" hidden>Sent. Give it a minute.</p>
</div>
{% endblock %}
{% block scripts %}
<script>
const form = document.getElementById("signup-form");
const done = document.getElementById("signup-done");
const error = document.getElementById("signup-error");
const button = document.getElementById("signup-submit");
let email = "";
form.addEventListener("submit", async (e) => {
e.preventDefault();
error.hidden = true;
button.disabled = true;
const data = new FormData(form);
email = data.get("email");
try {
await api.post("/api/signup", {
email,
password: data.get("password"),
org_name: data.get("org_name") || null,
});
document.getElementById("signup-email").textContent = email;
form.hidden = true;
done.hidden = false;
} catch (err) {
error.textContent = err.message;
error.hidden = false;
button.disabled = false;
}
});
document.getElementById("resend").addEventListener("click", async () => {
await api.post("/api/signup/resend", { email });
document.getElementById("resent").hidden = false;
});
</script>
{% endblock %}