// Editor screen — WYSIWYG resume with highlighted issues function HighlightedText({ text, issues, onIssueClick, activeId }) { if (!issues || issues.length === 0) return <>{text}; // Build spans. Find each issue word in order. const parts = []; let cursor = 0; const sorted = [...issues].map(iss => ({ ...iss, idx: text.indexOf(iss.word, 0) })).filter(i => i.idx >= 0).sort((a,b) => a.idx - b.idx); sorted.forEach((iss, n) => { if (iss.idx > cursor) parts.push({text.slice(cursor, iss.idx)}); parts.push( onIssueClick(iss)} className={ISSUE_META[iss.type]?.cls} style={{ cursor: 'pointer', borderRadius: 3, padding: '0 2px', outline: activeId === iss.id ? `2px solid ${ISSUE_META[iss.type].color}` : 'none', outlineOffset: 1, }}>{iss.word} ); cursor = iss.idx + iss.word.length; }); if (cursor < text.length) parts.push({text.slice(cursor)}); return <>{parts}; } function EditorScreen({ platform, onBack, onFix, onIssueTap, onExport, fixedIds = new Set(), activeIssue }) { const [view, setView] = React.useState('resume'); // resume | list const issues = allIssues(); const remaining = issues.filter(i => !fixedIds.has(i.id)); const applyIfFixed = (text, issueList) => { // When the fix-all is applied, swap in the fixed copy. let out = text; issueList.forEach(iss => { if (fixedIds.has(iss.id) && FIXES[iss.id]) { out = out.replace(FIXES[iss.id].from, FIXES[iss.id].to); } }); return out; }; const liveIssues = (issueList) => issueList.filter(i => !fixedIds.has(i.id)); return (
} /> {/* view toggle */}
{['resume','issues'].map(v => ( ))}
{view === 'resume' && (
{/* resume paper */}
{/* name */}
{RESUME.name}
{RESUME.title}
{RESUME.contact.map((c,i) => {c})}

{/* summary */}
summary

{/* experience */}
experience
{RESUME.experience.map((exp, ei) => (
{exp.role}, {exp.company}
{exp.dates}
    {exp.bullets.map((b, bi) => (
  • ))}
))} {/* education */}
education
{RESUME.education.school} · {RESUME.education.degree}
{/* missing section prompt */} {liveIssues(RESUME.missingSections.map((s,i) => ({ id: `m${i}`, type: 'missing', word: s }))).length > 0 && (
onIssueTap({ id: 'm0', type: 'missing', word: 'Skills' })}> + missing: skills section — tap to add
)}
)} {view === 'list' && (
{remaining.length === 0 ? (
all fixed ✨
your aura is glowing.
) : (
{remaining.map(iss => (
onIssueTap(iss)} style={{ background: '#fffdf7', borderRadius: 14, padding: '12px 14px', border: '1px solid rgba(26,13,46,0.08)', display: 'flex', gap: 12, alignItems: 'flex-start', cursor: 'pointer', }}>
{ISSUE_META[iss.type].icon}
{ISSUE_META[iss.type].label} · {iss.section}
"{iss.word}"
))}
)}
)} {/* sticky fix-all + export bar */}
{remaining.length > 0 ? ( <> fix all {remaining.length} download ) : ( download resume )}
); } window.EditorScreen = EditorScreen; window.HighlightedText = HighlightedText;