/* global React, ReactDOM */
const { useState, useEffect, useRef } = React;
// ============================================================================
// Recovery methods — surfaced in the picker, in order of recommendation.
// Each carries: id, label, icon, blurb, badge?, time-estimate, channel.
// ============================================================================
const METHODS = [];
const PROVIDERS = [];
// ============================================================================
// Step rail — visual progress indicator
// ============================================================================
function Stepper({ step }) {
const steps = [];
return (
{steps.map((s, i) => (
{i + 1}. {s}
{i < steps.length - 1 && }
))}
);
}
// ============================================================================
// Step 1 — method picker
// ============================================================================
function MethodPicker({ email, setEmail, onPick }) {
return (
Account email
setEmail(e.target.value)}
placeholder="you@conceptualhealth.com"
autoFocus
/>
How would you like to verify?
{METHODS.map(m => (
onPick(m.id)}
>
{m.icon}
{m.title}
{m.badge && {m.badge} }
{m.blurb}
{m.estimate}
→
))}
For HIPAA-protected accounts we always require a second factor on the new device, even after recovery. If you don't recognize this device, the link won't work.
);
}
// ============================================================================
// Step 2 — verification (varies by method)
// ============================================================================
function VerifyEmail({ email, onBack, onContinue }) {
const [sent, setSent] = useState(true);
const [seconds, setSeconds] = useState(30);
useEffect(() => {
if (seconds <= 0) return;
const t = setTimeout(() => setSeconds(s => s - 1), 1000);
return () => clearTimeout(t);
}, [seconds]);
return (
Email verification
Check your inbox.
We sent a one-time link to {email} . Open it on this device to continue. The link expires in 15 minutes.
Recovery link sent.
From noreply@conceptualhealth.com · subject "Recover your account"
If the email doesn't arrive within 5 minutes, check your spam folder, or pick a different verification method below.
← Choose another method
0} onClick={() => setSeconds(30)}>
{seconds > 0 ? `Resend in ${seconds}s` : "Resend email"}
I clicked the link →
);
}
function VerifySMS({ onBack, onContinue }) {
const [code, setCode] = useState(["", "", "", "", "", ""]);
const refs = useRef([]);
function setDigit(i, v) {
const next = [...code];
next[i] = v.slice(-1);
setCode(next);
if (v && i < 5) refs.current[i + 1]?.focus();
}
return (
SMS verification
Enter the 6-digit code.
We texted +1 ••• ••• 4127 . The code expires in 10 minutes.
{code.map((d, i) => (
(refs.current[i] = el)}
value={d}
onChange={e => setDigit(i, e.target.value)}
onKeyDown={e => { if (e.key === "Backspace" && !d && i > 0) refs.current[i - 1]?.focus(); }}
inputMode="numeric"
maxLength={1}
autoFocus={i === 0}
/>
))}
← Choose another method
Resend code
Verify code →
);
}
function VerifyPasskey({ onBack, onContinue }) {
const [scanning, setScanning] = useState(false);
return (
Passkey verification
Verify with your device.
Use Face ID, Touch ID, Windows Hello, or your security key. We never see your biometric — your device proves it locally.
{scanning ? "Listening for passkey…" : "Ready to verify"}
← Choose another method
{!scanning
? { setScanning(true); setTimeout(onContinue, 1500); }}>Use passkey →
: Verifying… }
);
}
function VerifyCodes({ onBack, onContinue }) {
const [code, setCode] = useState("");
return (
Backup recovery code
Enter one of your 10 single-use codes.
You saved these when you set up your account. Each code works once. After you sign in, we'll regenerate the unused ones.
Recovery code
setCode(e.target.value.toUpperCase().replace(/[^A-Z0-9-]/g, ""))}
placeholder="XXXX-XXXX-XXXX"
autoFocus
style={{ fontFamily: "var(--font-mono)", letterSpacing: "0.12em" }}
/>
Lost your codes? Use email, SMS, or a passkey instead — or ask your provider to verify you.
← Choose another method
Use this code →
);
}
function VerifyProvider({ onBack, onContinue }) {
const [picked, setPicked] = useState(null);
return (
Provider attestation
Ask your care team to vouch for you.
A verified provider on your record can confirm your identity. They'll get a notice in their Clinical Portal — once they approve, you'll be back in within minutes.
{picked ? (
<>
{picked.initials}
{picked.name}
{picked.role}
● Notified
Request sent to {picked.name} at {picked.site}. We'll text you when they approve. You can close this tab — or, if you're with them right now, continue.
>
) : (
{PROVIDERS.map(p => (
{p.initials}
{p.name}
{p.role} · {p.site}
setPicked(p)}>Send request
))}
)}
← Choose another method
{picked && They've approved → }
);
}
// ============================================================================
// Step 3 — set new password
// ============================================================================
function NewPassword({ onSubmit, onBack }) {
const [pw, setPw] = useState("");
const [confirm, setConfirm] = useState("");
// very lightweight strength scoring (visual demo, not security)
const strength = (() => {
let s = 0;
if (pw.length >= 10) s++;
if (/[A-Z]/.test(pw) && /[a-z]/.test(pw)) s++;
if (/[0-9]/.test(pw)) s++;
if (/[^A-Za-z0-9]/.test(pw)) s++;
return Math.min(s, 4);
})();
const strengthLabel = [][strength];
const valid = pw.length >= 10 && pw === confirm && strength >= 3;
return (
Set a new password
Almost done.
Your password protects every axis on your record. Make it long. Make it unique. The rest will sleep better.
New password
setPw(e.target.value)} placeholder="At least 10 characters" autoFocus />
Strength · {strengthLabel}
Confirm password
setConfirm(e.target.value)} placeholder="Type it again" />
We salt and hash your password with Argon2id; we never store the plaintext. After you sign in, we'll prompt you to add a passkey so you don't need a password next time.
);
}
// ============================================================================
// Step 4 — success
// ============================================================================
function Done({ method }) {
return (
You're back in.
Password reset · verified by {method}. We've signed every other session out of your account; sign back in on those devices when you're ready.
);
}
// ============================================================================
// Top-level orchestrator
// ============================================================================
function App() {
const [step, setStep] = useState(0); // 0 picker · 1 verify · 2 new pw · 3 done
const [email, setEmail] = useState("ray@conceptualhealth.com");
const [method, setMethod] = useState(null);
function pick(id) { setMethod(id); setStep(1); }
function backToPicker() { setMethod(null); setStep(0); }
function verified() { setStep(2); }
function reset() { setStep(3); }
const methodLabel = METHODS.find(m => m.id === method)?.title.toLowerCase().replace(/^./, "") || "verification";
return (
{/* Top brand bar */}
{/* Header */}
Account recovery
{step === 3 ? <>Welcome back. > : <>Let's get you back in. >}
{step !== 3 && (
Five ways to verify it's really you. Pick the one that fits — every path lands at the same place: a new password, in your hands, in under two minutes.
)}
{/* Step rail */}
{step < 3 &&
}
{/* Step body */}
{step === 0 &&
}
{step === 1 && method === "email" &&
}
{step === 1 && method === "sms" &&
}
{step === 1 && method === "passkey" &&
}
{step === 1 && method === "codes" &&
}
{step === 1 && method === "provider" &&
}
{step === 2 &&
setStep(1)} />}
{step === 3 && }
{/* Footer */}
"Integrity in all we do™."
);
}
ReactDOM.createRoot(document.getElementById("root")).render( );