import { useState, useRef, useEffect } from "react"; import { startNegotiation, sendResponse, acceptOffer } from "./utils/api"; function EQGauge({ label, value, max = 10 }) { const pct = Math.round((value / max) * 100); const color = pct >= 70 ? "#00b894" : pct >= 40 ? "#fdcb6e" : "#e17055"; return (
{label}
{value}/{max}
); } function MomentBadge({ rating }) { const colors = { strong: "#00b894", neutral: "#fdcb6e", weak: "#e17055" }; return {rating}; } function CoachingPanel({ tip, warning, candidateTactics, momentRating }) { if (!tip && !warning) return null; return (
Real-Time Coach{momentRating && }
{candidateTactics && candidateTactics.length > 0 && (
Your tactics: {candidateTactics.map((t, i) => {t})}
)} {tip &&
Try next: {tip}
} {warning && warning.length > 0 &&
Avoid: {warning}
}
); } function ScoreCircle({ score, label, size = 80 }) { const r = (size - 10) / 2; const circ = 2 * Math.PI * r; const offset = circ - (score / 100) * circ; const color = score >= 75 ? "#00b894" : score >= 50 ? "#fdcb6e" : "#e17055"; return (
100 ? "2rem" : "1.1rem", fontWeight: 700, color: "#fff" }}>{score}
{label}
); } function ReportView({ report, onReset }) { const r = report; return (

Performance Report

{r.verdict}
{r.letterGrade &&
Grade: {r.letterGrade}
}
Target
{"$"}{(r.targetSalary||0).toLocaleString()}
Final Offer
{"$"}{(r.finalSalary||0).toLocaleString()}
{r.percentOfTarget}% of target
{r.marketContext &&
Market Range
{"$"}{(r.marketContext.marketLow||0).toLocaleString()} - {"$"}{(r.marketContext.marketHigh||0).toLocaleString()}
{r.marketContext.candidatePosition}
}

{r.summary}

{r.negotiationStyle &&

Negotiation Style: {r.negotiationStyle.primary}

{r.negotiationStyle.description}

} {r.emotionalIntelligence && (

Emotional Intelligence

{r.emotionalIntelligence.analysis}

)} {r.communicationScore && (

Communication

{r.communicationScore.analysis}

)} {r.powerDynamics && (

Power Dynamics

You: {r.powerDynamics.candidatePower}/10
Manager: {r.powerDynamics.managerPower}/10

{r.powerDynamics.assessment}

{r.powerDynamics.shiftMoments?.map((m,i)=>
{m}
)}
)} {r.bestMoments?.length > 0 && (

Best Moments

{r.bestMoments.map((m,i)=>
Round {m.round}
"{m.quote}"
{m.why}
)}
)} {r.worstMoments?.length > 0 && (

Weakest Moments

{r.worstMoments.map((m,i)=>
Round {m.round}
"{m.quote}"
{m.why}
)}
)} {r.tacticsUsed?.length > 0 && (

Tactics Analysis

{r.tacticsUsed.map((t,i)=>
{t.name}
{t.effectiveness}
"{t.example}"
)}
)} {r.missedOpportunities?.length > 0 && (

Missed Opportunities

{r.missedOpportunities.map((m,i)=>
Situation: {m.situation}
Better approach: {m.betterApproach}
Impact: {m.impact}
)}
)} {r.marketContext &&

Market Context

{r.marketContext.analysis}

}

Strengths

    {r.strengths?.map((s,i)=>
  • {s}
  • )}

Areas to Improve

    {r.improvements?.map((s,i)=>
  • {s}
  • )}
{r.personalizedTips?.length > 0 && (

Personalized Pro Tips

{r.personalizedTips.map((t,i)=>
{t.category}
{t.tip}
)}
)} {r.nextSessionFocus &&

Next Session Focus

{r.nextSessionFocus}

}
); } export default function App() { const [phase, setPhase] = useState("setup"); const [config, setConfig] = useState({ role:"", company:"", currentSalary:"", targetSalary:"", difficulty:"medium", scenarioType:"salary" }); const [sessionId, setSessionId] = useState(null); const [messages, setMessages] = useState([]); const [currentOffer, setCurrentOffer] = useState(0); const [response, setResponse] = useState(""); const [loading, setLoading] = useState(false); const [report, setReport] = useState(null); const [round, setRound] = useState(1); const [tactic, setTactic] = useState(""); const [tacticExplanation, setTacticExplanation] = useState(""); const [error, setError] = useState(""); const [coaching, setCoaching] = useState(null); const [eqScores, setEqScores] = useState(null); const [scenarioLabel, setScenarioLabel] = useState(""); const chatRef = useRef(null); const inputRef = useRef(null); useEffect(() => { if (chatRef.current) chatRef.current.scrollTop = chatRef.current.scrollHeight; }, [messages, coaching]); useEffect(() => { if (phase === "negotiation" && !loading && inputRef.current) inputRef.current.focus(); }, [phase, loading, messages]); const handleStart = async () => { if (!config.role || !config.targetSalary) { setError("Role and target salary are required"); return; } setLoading(true); setError(""); try { const data = await startNegotiation({ ...config, targetSalary: Number(config.targetSalary), currentSalary: Number(config.currentSalary) || undefined }); setSessionId(data.sessionId); setCurrentOffer(data.initialOffer); setScenarioLabel(data.scenarioLabel || "Salary Negotiation"); setMessages([{ role: "Hiring Manager", text: data.openingStatement + " Our initial offer is " + "$" + (data.initialOffer||0).toLocaleString() + ".", name: data.hiringManagerName }]); setPhase("negotiation"); } catch (err) { setError(err.message); } finally { setLoading(false); } }; const handleRespond = async () => { if (!response.trim()) return; setMessages(prev => [...prev, { role: "You", text: response }]); const myResponse = response; setResponse(""); setLoading(true); setCoaching(null); try { const data = await sendResponse(sessionId, myResponse); setCurrentOffer(data.currentOffer); setMessages(prev => [...prev, { role: "Hiring Manager", text: data.response }]); setRound(data.round); if (data.tactic) setTactic(data.tactic); if (data.tacticExplanation) setTacticExplanation(data.tacticExplanation); if (data.emotionalIntelligence) setEqScores(data.emotionalIntelligence); setCoaching({ tip: data.coachingTip, warning: data.coachingWarning, candidateTactics: data.candidateTactics, momentRating: data.momentRating }); } catch (err) { setError(err.message); } finally { setLoading(false); } }; const handleAccept = async () => { setLoading(true); try { const data = await acceptOffer(sessionId); setReport(data); setPhase("report"); } catch (err) { setError(err.message); } finally { setLoading(false); } }; const resetAll = () => { setPhase("setup"); setMessages([]); setReport(null); setRound(1); setCoaching(null); setEqScores(null); setTactic(""); setTacticExplanation(""); setError(""); }; if (phase === "report" && report) return ; if (phase === "negotiation") { return (

Negotiation Simulator

{scenarioLabel}
Round {round} | {config.difficulty} difficulty
{"$"}{(currentOffer||0).toLocaleString()}
Target: {"$"}{Number(config.targetSalary).toLocaleString()}
{Math.round((currentOffer / Number(config.targetSalary)) * 100)}% of target
{tactic &&
{tactic}{tacticExplanation && {tacticExplanation}}
}
{eqScores &&
Empathy{eqScores.empathy}
Assertive{eqScores.assertiveness}
Composure{eqScores.composure}
Rapport{eqScores.rapport}
}
{messages.map((m,i) =>
{m.role}{m.name ? " ("+m.name+")" : ""}
{m.text}
)} {loading &&
Thinking...
}
{coaching && } {error &&

{error}

}