/* BioReveal — Reveal page (v0.9 — analysis-first).
*
* Renders the AI's REAL analysis of the patient. No raw biomarker numbers
* displayed — the AI interpreted them and wrote the read. Same render path
* for both Claude and rules-engine output (they share schema).
*/
const PEPTIDE_PRICES = {
"Sermorelin": 179, "NAD+": 189, "BPC-157": 149, "Glutathione": 119,
"Ipamorelin": 169, "GHK-Cu": 159, "Selank": 139, "DSIP": 129,
"B12 / MIC": 99, "CJC-1295": 169, "TB-500": 219, "Tesamorelin": 199,
"Epitalon": 149, "Semax": 149, "PT-141": 119,
};
const StepAnalysis = ({ onStart, error, onRetry }) => {
const lines = [
"Reading what you said you want fixed",
"Cross-checking your health background",
"Reading the bioscan",
"Picking the right peptides for you",
"Cross-referencing 47,000+ outcomes",
"Drafting your personal read",
"Sequencing the protocol",
"Adding lifestyle plays",
"Finalizing the dose schedule",
];
const [i, setI] = React.useState(0);
const [elapsed, setElapsed] = React.useState(0);
const startedRef = React.useRef(false);
React.useEffect(() => { if (!startedRef.current) { startedRef.current = true; onStart(); } }, []);
// Keep cycling through the lines indefinitely until the parent flips to
// reveal stage. Synth can take 30-60+ seconds when OAuth is contended,
// so we never want a frozen "Writing your analysis…" with no movement.
React.useEffect(() => {
if (error) return;
const t = setTimeout(() => setI((prev) => (prev + 1) % lines.length), 1100);
return () => clearTimeout(t);
}, [i, error]);
// Elapsed-time counter so the user can see something is still moving
React.useEffect(() => {
if (error) return;
const t = setInterval(() => setElapsed((s) => s + 1), 1000);
return () => clearInterval(t);
}, [error]);
// Show "still working" hint after 15s. The OAuth backoff chain can take
// 60s+ when our Claude credits are contended — be honest about it.
const slowHint = elapsed >= 15;
const verySlowHint = elapsed >= 45;
return (
{error ? "Synthesis paused" : "Writing your analysis"}