import { useState, useEffect } from 'react' import { api } from './api' import styles from './Platform.module.css' // Phase 5A §5/§6 — one screen for both flows the credential token mechanism serves: // activation (first login, purpose='activation') and forgot-password (purpose='reset'). Same // UI, different API call and success copy. export default function SetPasswordScreen({ token, purpose, onDone, onCancel }) { const [preview, setPreview] = useState(null) const [previewError, setPreviewError] = useState(null) const [password, setPassword] = useState('') const [confirm, setConfirm] = useState('') const [loading, setLoading] = useState(false) const [error, setError] = useState(null) useEffect(() => { api.credentialTokenPreview(purpose, token).then(setPreview).catch((e) => setPreviewError(e.message)) }, [token, purpose]) const submit = async (e) => { e.preventDefault() if (password.length < 10) { setError('Password must be at least 10 characters.'); return } if (password !== confirm) { setError('Passwords do not match.'); return } setLoading(true) setError(null) try { if (purpose === 'activation') { const student = await api.activate(token, password) onDone(student) } else { await api.resetPassword(token, password) onDone(null) // reset doesn't log the browser in — every existing session was revoked, sign in fresh } } catch (err) { setError(err.message) } finally { setLoading(false) } } return (
⎈ RootNode Academy

{purpose === 'activation' ? 'Set up your account' : 'Choose a new password'}

{previewError && (
This link is invalid or has expired. Ask your instructor for a new one.
)} {preview &&

Hi, {preview.display_name}.

} {error &&
{error}
} {!previewError && (
setPassword(e.target.value)} required minLength={10} /> setConfirm(e.target.value)} required minLength={10} />
)}

) }