/* ============================================================
screen_chat.jsx — AI onboarding advisor (the wow)
Conversational, builds the profile live in a tray, then
hands off to the assembled profile / home.
============================================================ */
/* ---------- profile tray fact chip ---------- */
function TrayChip({ fk, lang, t, index }) {
const fact = TRAY[fk];
if (!fact) return null;
return (
{t[fact.key]}
{tr(fact.val, lang)}
);
}
function ProfileTray({ revealed, lang, t }) {
const pct = Math.min(86, Math.round((revealed.length / 6) * 86));
if (revealed.length === 0) return null;
return (
{t.trayTitle}
{t.profileAssembling}…
{revealed.map((fk, i) => )}
);
}
/* ---------- typing dots ---------- */
function Typing() {
return (
{[0, 1, 2].map(i => (
))}
);
}
function AdvisorDot() {
return (
);
}
/* ---------- bubbles ---------- */
function AiBubble({ children }) {
return (
);
}
function UserBubble({ children, file }) {
return (
);
}
/* ---------- upload card ---------- */
function UploadCard({ onUpload, t }) {
return (
{t.attach}
PDF · JPG · {t.voiceHint}
);
}
/* ---------- parsing overlay (inline) ---------- */
function ParsingCard({ t }) {
return (
{t.parsing}…
{[88, 64, 76].map((w, i) => (
))}
);
}
/* ---------- assemble overlay ---------- */
function AssembleOverlay({ t }) {
return (
{[0, 1, 2].map(i => (
))}
{t.profileAssembling}…
{t.value} · {t.skills} · {t.role}
);
}
/* ---------- main chat screen ---------- */
function ChatScreen({ lang, theme, setLang, setTheme, onFinish, onSkip, t }) {
const [items, setItems] = useState([]);
const [revealed, setRevealed] = useState([]);
const [typing, setTyping] = useState(false);
const [awaiting, setAwaiting] = useState(null);
const [special, setSpecial] = useState(null); // 'upload' | 'parsing' | 'assemble'
const [finished, setFinished] = useState(false);
const idx = useRef(0);
const scroller = useRef(null);
const started = useRef(false);
const push = (it) => setItems(p => [...p, { id: Math.random(), ...it }]);
const reveal = (keys) => {
keys.forEach((k, i) => setTimeout(() => setRevealed(p => p.includes(k) ? p : [...p, k]), i * 280));
};
const run = () => {
const step = CHAT[idx.current];
if (!step) { setFinished(true); return; }
if (step.who === 'ai') {
setTyping(true);
const len = tr(step.text, 'ru').length;
setTimeout(() => {
setTyping(false);
push({ who: 'ai', textObj: step.text });
if (step.add) reveal(step.add);
idx.current++;
setTimeout(run, 420);
}, Math.min(1500, 700 + len * 7));
} else if (step.who === 'choices') {
setAwaiting(step);
} else if (step.who === 'upload') {
setSpecial('upload');
} else if (step.who === 'assemble') {
setSpecial('assemble');
setTimeout(() => { setSpecial(null); idx.current++; run(); }, 2400);
}
};
useEffect(() => {
if (started.current) return;
started.current = true;
setTimeout(run, 500);
}, []);
useEffect(() => {
const el = scroller.current;
if (el) el.scrollTop = el.scrollHeight + 200;
}, [items, typing, special, awaiting, finished]);
const pick = (opt) => {
const step = awaiting;
setAwaiting(null);
push({ who: 'user', textObj: opt });
if (step.add) reveal(step.add);
idx.current++;
setTimeout(run, 350);
};
const doUpload = () => {
setSpecial('parsing');
setTimeout(() => {
push({ who: 'user', file: true, textObj: { ru: 'Диплом_маркетинг.pdf', uz: 'Diplom_marketing.pdf' } });
setSpecial(null);
idx.current++;
setTimeout(run, 450);
}, 2300);
};
return (
{special === 'assemble' &&
}
{/* advisor header */}
{t.advisor}
{typing ? t.typing + '…' : t.online}
{onSkip && (
{t.skip.split(' ')[0]}
)}
{/* messages */}
{items.map(it => (
it.who === 'ai'
?
{tr(it.textObj, lang)}
:
{tr(it.textObj, lang)}
))}
{special === 'upload' &&
}
{special === 'parsing' &&
}
{typing &&
}
{finished && (
{t.showProfile}
)}
{/* quick replies + input */}
{awaiting && (
{awaiting.options.map((o, i) => (
pick(o)} style={{
padding: '10px 16px', borderRadius: 'var(--r-full)', fontSize: 13.5, fontWeight: 700,
background: o.pick ? 'var(--brand)' : 'var(--surface)', color: o.pick ? '#fff' : 'var(--text-2)',
border: o.pick ? '1px solid transparent' : '1px solid var(--border)', boxShadow: 'var(--shadow-1)',
animation: `chipFly .4s var(--spring) ${i * 0.06}s both`,
}}>{tr(o, lang)}
))}
)}
{t.inputPh}
special === 'upload' && doUpload()} style={{ width: 46, height: 46, borderRadius: '50%', background: 'var(--surface)', border: '1px solid var(--border)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--text-2)', boxShadow: 'var(--shadow-1)' }}>
);
}
Object.assign(window, { ChatScreen });