import { useState, useMemo } from 'react' import { useNavigate } from 'react-router-dom' import { COMPANIES } from '../lib/companies' import VoiceSettings from './VoiceSettings' import { buildInterviewUrl, buildWatchUrl } from '../lib/sessionConfig' import { VX_SERVER } from '../lib/webrtc' const DEFAULT_KEY = 'vk_Qg95CQBuNFuiiHMCVtgo9bh9kx0N1ACnaj8zdJyg5qsBDWTjxt2ZoegM2UCdKfCY' export default function InterviewSetup() { const navigate = useNavigate() const sessionId = useMemo(() => crypto.randomUUID(), []) const [phase, setPhase] = useState('setup') // 'setup' | 'ready' const [name, setName] = useState('') const [company, setCompany] = useState(null) const [error, setError] = useState('') const [voiceSettings, setVoiceSettings] = useState({}) // Generated URLs — only set after clicking Create const [interviewUrl, setInterviewUrl] = useState('') const [watchUrl, setWatchUrl] = useState('') // Copy states per link const [copiedInterview, setCopiedInterview] = useState(false) const [copiedWatch, setCopiedWatch] = useState(false) function copy(text, setDone) { navigator.clipboard.writeText(text).then(() => { setDone(true) setTimeout(() => setDone(false), 2000) }) } function handleCreate() { if (!name.trim()) return setError('Enter the candidate name') if (!company) return setError('Choose a company') setError('') const config = { candidateName: name.trim(), company, apiKey: DEFAULT_KEY, server: VX_SERVER, voiceSettings: Object.keys(voiceSettings).length ? voiceSettings : null, } setInterviewUrl(buildInterviewUrl(sessionId, config)) setWatchUrl(buildWatchUrl(sessionId)) setPhase('ready') } if (phase === 'ready') { return (

Interview ready

Send the link,
then watch.

Share the interview link with {name}. Open the watch link on your device to follow the conversation live.

{/* Interview link */}
Interview link Send this to the candidate
{interviewUrl}
{/* Watch link */}
Watch link Your observer view
{watchUrl}

The candidate opens their link and the interview starts automatically. You'll see the full transcript here as it happens.

) } return (

AI-powered mock interview

Configure &
send the link.

{/* Candidate name */}
setName(e.target.value)} onKeyDown={e => e.key === 'Enter' && handleCreate()} placeholder="e.g. Ayush" autoComplete="off" />
{/* Company picker */}
{Object.values(COMPANIES).map(c => ( { setCompany(c.id); setError('') }} /> ))}
{error &&

{error}

}

Generates a unique link for the candidate and a watch link for you.

) } function CompanyCard({ company, selected, onSelect }) { return ( ) } const s = { page: { minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '40px 20px', position: 'relative', overflowY: 'auto', overflowX: 'hidden', }, glow1: { position: 'fixed', inset: 0, background: 'radial-gradient(ellipse 60% 50% at 20% 80%, rgba(200,240,96,.05) 0%, transparent 70%)', pointerEvents: 'none', }, glow2: { position: 'fixed', inset: 0, background: 'radial-gradient(ellipse 50% 50% at 80% 20%, rgba(96,208,240,.04) 0%, transparent 70%)', pointerEvents: 'none', }, inner: { width: '100%', maxWidth: 560, display: 'flex', flexDirection: 'column', position: 'relative', zIndex: 1, }, back: { alignSelf: 'flex-start', fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--muted)', background: 'none', border: 'none', cursor: 'pointer', letterSpacing: '.08em', padding: 0, marginBottom: 28, }, pill: { display: 'inline-block', alignSelf: 'flex-start', fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '.2em', textTransform: 'uppercase', color: 'var(--accent)', border: '1px solid rgba(200,240,96,.25)', padding: '4px 10px', borderRadius: 20, marginBottom: 20, }, title: { fontSize: 'clamp(34px, 6vw, 56px)', fontWeight: 800, lineHeight: .95, letterSpacing: '-.03em', marginBottom: 16, }, subtitle: { fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--muted)', lineHeight: 1.7, marginBottom: 32, letterSpacing: '.04em', }, linkCard: { background: 'var(--surface)', border: '1px solid var(--border2)', borderRadius: 10, padding: '14px 16px', marginBottom: 14, display: 'flex', flexDirection: 'column', gap: 10, }, linkCardHeader: { display: 'flex', alignItems: 'baseline', gap: 10, }, linkCardLabel: { fontFamily: 'var(--mono)', fontSize: 9, letterSpacing: '.2em', textTransform: 'uppercase', color: 'var(--accent)', }, linkCardHint: { fontFamily: 'var(--mono)', fontSize: 9, color: 'var(--muted)', letterSpacing: '.08em', }, linkRow: { display: 'flex', alignItems: 'center', gap: 10, }, linkText: { fontFamily: 'var(--mono)', fontSize: 10, color: 'var(--muted)', flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', }, copyBtn: { fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '.1em', padding: '5px 12px', borderRadius: 6, border: '1px solid var(--border2)', background: 'transparent', color: 'var(--text)', cursor: 'pointer', flexShrink: 0, transition: 'border-color .15s, color .15s', }, copyBtnDone: { color: 'var(--accent)', borderColor: 'var(--accent)', }, fieldGroup: { display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 20, }, label: { fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '.18em', color: 'var(--muted)', textTransform: 'uppercase', }, input: { background: 'var(--surface)', border: '1px solid var(--border2)', color: 'var(--text)', fontFamily: 'var(--mono)', fontSize: 13, padding: '12px 14px', borderRadius: 8, outline: 'none', width: '100%', }, companyGrid: { display: 'flex', flexDirection: 'column', gap: 10, }, companyCard: { display: 'flex', alignItems: 'flex-start', gap: 14, padding: '14px 16px', borderRadius: 10, border: '1.5px solid', cursor: 'pointer', textAlign: 'left', transition: 'border-color .15s, background .15s', fontFamily: 'var(--sans)', width: '100%', position: 'relative', }, companyIcon: { width: 40, height: 40, borderRadius: 10, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 18, fontWeight: 800, flexShrink: 0, }, companyInfo: { display: 'flex', flexDirection: 'column', gap: 3, flex: 1, }, companyName: { fontSize: 15, fontWeight: 700, color: 'var(--text)', }, companyTag: { fontFamily: 'var(--mono)', fontSize: 10, color: 'var(--muted)', letterSpacing: '.12em', }, companyPills: { display: 'flex', flexWrap: 'wrap', gap: 4, marginTop: 6, }, qpill: { fontFamily: 'var(--mono)', fontSize: 9, letterSpacing: '.1em', color: 'var(--muted)', border: '1px solid var(--border)', padding: '2px 7px', borderRadius: 20, }, checkmark: { position: 'absolute', top: 12, right: 14, fontSize: 16, fontWeight: 700, }, error: { fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--danger)', marginBottom: 12, }, startBtn: { background: 'var(--accent)', color: '#0a0a0a', border: 'none', fontFamily: 'var(--sans)', fontSize: 14, fontWeight: 700, letterSpacing: '.06em', padding: '16px 24px', borderRadius: 8, cursor: 'pointer', marginTop: 4, marginBottom: 16, }, watchBtn: { background: 'transparent', color: 'var(--text)', border: '1.5px solid var(--border2)', fontFamily: 'var(--sans)', fontSize: 14, fontWeight: 600, letterSpacing: '.04em', padding: '14px 24px', borderRadius: 8, cursor: 'pointer', marginBottom: 20, transition: 'border-color .15s', }, fine: { fontFamily: 'var(--mono)', fontSize: 10, color: 'var(--muted)', letterSpacing: '.1em', textAlign: 'center', lineHeight: 1.6, }, }