auth-yes/ui/components/RegisterPage.tsx

165 lines
4.9 KiB
TypeScript

import { Layout } from "./Layout.tsx";
export const RegisterPage = (
{ initialCode = "" }: { initialCode?: string },
) => {
return (
<Layout title="Register">
<div style={{ textAlign: "center" }}>
<h1 style={{ marginBottom: "0.5rem" }}>Create Account</h1>
<p
style={{ color: "#666", marginBottom: "1.5rem", fontSize: "0.95rem" }}
>
Register a secure hardware token or passkey using your invite code.
</p>
<div style={{ textAlign: "left", marginBottom: "1rem" }}>
<label
for="username"
style={{
display: "block",
marginBottom: "0.25rem",
fontWeight: "bold",
}}
>
Username
</label>
<input
type="text"
id="username"
placeholder="e.g. pilot_alice"
required
autofocus={!initialCode}
/>
</div>
<div style={{ textAlign: "left", marginBottom: "1.5rem" }}>
<label
for="inviteCode"
style={{
display: "block",
marginBottom: "0.25rem",
fontWeight: "bold",
}}
>
Invite Code
</label>
<input
type="text"
id="inviteCode"
placeholder="Invite Code (e.g. 00000000-... or custom code)"
value={initialCode}
required
/>
</div>
<div
id="instructionBox"
style={{
background: "#e8f4fd",
padding: "0.75rem",
borderRadius: "6px",
marginBottom: "1.5rem",
fontSize: "0.85rem",
color: "#0c5460",
border: "1px solid #bee5eb",
textAlign: "left",
}}
>
<strong>Tip:</strong>{" "}
You can use your phone (via QR code / Bluetooth), biometric sensor
(Touch ID, Windows Hello), password manager (1Password, Bitwarden,
Chrome), or USB security key (YubiKey).
</div>
<button
type="button"
id="registerBtn"
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
gap: "0.5rem",
fontWeight: "bold",
background: "#28a745",
}}
>
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
</svg>
Register Passkey
</button>
<div
id="loadingIndicator"
style={{
display: "none",
marginTop: "1rem",
color: "#28a745",
fontSize: "0.9rem",
}}
>
Setting up passkey... Follow the prompt on your device.
</div>
<div id="statusMessage" class="error" style={{ marginTop: "1rem" }}>
</div>
<div class="links" style={{ marginTop: "2rem" }}>
Already have an account? <a href="/login">Login here</a>
</div>
</div>
<script src="/public/auth-client.js?v=5"></script>
<script
dangerouslySetInnerHTML={{
__html: `
// Auto-populate invite code from URL if present
const urlParams = new URLSearchParams(window.location.search);
const codeParam = urlParams.get('code');
if (codeParam) {
const input = document.getElementById('inviteCode');
if (input) {
input.value = codeParam;
document.getElementById('username').focus();
}
}
document.getElementById('registerBtn').addEventListener('click', async () => {
const username = document.getElementById('username').value.trim();
const inviteCode = document.getElementById('inviteCode').value.trim();
if (!username || !inviteCode) {
document.getElementById('statusMessage').textContent = "Username and Invite Code are required.";
document.getElementById('statusMessage').className = "error";
return;
}
document.getElementById('loadingIndicator').style.display = 'block';
document.getElementById('registerBtn').disabled = true;
document.getElementById('statusMessage').textContent = '';
try {
await startWebAuthnRegistration(username, inviteCode);
} finally {
document.getElementById('loadingIndicator').style.display = 'none';
document.getElementById('registerBtn').disabled = false;
}
});
`,
}}
>
</script>
</Layout>
);
};