import { useState, useEffect } from 'react' import { NOVICE_LETTERS, MORSE, validatePhrase, suggestPhrases } from '../lib/morse' type Props = { token: string onComplete: () => void } const LETTERS = NOVICE_LETTERS // ['A','E','T','I','N','S','H','R','D','L','U','O'] export function MnemonicBuilder({ token, onComplete }: Props) { const [index, setIndex] = useState(0) const [phrase, setPhrase] = useState('') const [saving, setSaving] = useState(false) const [error, setError] = useState(null) const [suggestions, setSuggestions] = useState([]) const letter = LETTERS[index] const pattern = MORSE[letter] ?? '' // Display pattern as dots/dashes: '.' → '·', '-' → '—' const display = pattern.split('').map(c => c === '.' ? '·' : '—').join(' ') const validation = phrase.trim() ? validatePhrase(phrase.trim(), letter) : null useEffect(() => { setSuggestions(suggestPhrases(letter, 5)) setPhrase('') setError(null) }, [letter]) async function save() { if (!validation?.valid) return setSaving(true) setError(null) try { const r = await fetch('/api/mnemonics', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, body: JSON.stringify({ letter, phrase: phrase.trim() }), }) if (!r.ok) throw new Error('Failed to save') advance() } catch { setError('Failed to save. Try again.') } finally { setSaving(false) } } function advance() { if (index + 1 >= LETTERS.length) { onComplete() } else { setIndex(i => i + 1) } } return (
{/* Progress */}

Letter {index + 1} of {LETTERS.length}

{/* Letter display */}
{letter}
{display}
{pattern.length} {pattern.length === 1 ? 'word' : 'words'} needed
{/* Phrase input */}

{pattern.length} word{pattern.length !== 1 ? 's' : ''} — {' '}≤3 letters for dots ·, 4+ letters for dashes —. {' '}Start a word with "{letter}" to anchor it!

{ setPhrase(e.target.value); setError(null) }} placeholder={suggestions.length > 0 ? `e.g. "${suggestions[0]}"` : ''} disabled={saving} style={{ marginBottom: '0.5rem' }} /> {/* Validation feedback */} {validation && !validation.valid && (

{validation.message}

)} {validation?.valid && (

Looks good!

)} {error && (

{error}

)} {/* Suggestions */}
Suggestions — click to use:
{suggestions.map(s => ( ))}
{/* Actions */}
) }