Spaces:
Sleeping
Sleeping
| import { useState } from "react"; | |
| import { CheckCircle2, ChevronDown, ChevronRight } from "lucide-react"; | |
| import type { InterviewResult, QAPair } from "../../../services/interviewApi"; | |
| interface Props { | |
| result: InterviewResult; | |
| } | |
| export default function InterviewResultView({ result }: Props) { | |
| const [openSections, setOpenSections] = useState<Set<number>>(new Set([0])); | |
| const toggleSection = (i: number) => { | |
| setOpenSections((prev) => { | |
| const next = new Set(prev); | |
| if (next.has(i)) next.delete(i); | |
| else next.add(i); | |
| return next; | |
| }); | |
| }; | |
| return ( | |
| <div className="mx-4 my-4 rounded-2xl border border-emerald-200 bg-emerald-50/60 overflow-hidden text-sm"> | |
| {/* Header */} | |
| <div className="flex items-center gap-2 px-4 py-3 bg-emerald-100/80 border-b border-emerald-200"> | |
| <CheckCircle2 className="w-4 h-4 text-emerald-600 flex-shrink-0" /> | |
| <span className="font-semibold text-emerald-800">Hasil Interview</span> | |
| </div> | |
| <div className="px-4 py-4 space-y-5"> | |
| {/* Summary */} | |
| {result.summary && ( | |
| <div> | |
| <p className="text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Ringkasan</p> | |
| <p className="text-slate-700 leading-relaxed">{result.summary}</p> | |
| </div> | |
| )} | |
| {/* Goals */} | |
| {result.goals?.length > 0 && ( | |
| <div> | |
| <p className="text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Tujuan</p> | |
| <ul className="space-y-1"> | |
| {result.goals.map((g, i) => ( | |
| <li key={i} className="flex gap-2 text-slate-700"> | |
| <span className="text-emerald-500 flex-shrink-0 mt-0.5">•</span> | |
| <span>{g}</span> | |
| </li> | |
| ))} | |
| </ul> | |
| </div> | |
| )} | |
| {/* Section Results */} | |
| {result.section_results?.length > 0 && ( | |
| <div> | |
| <p className="text-xs font-semibold text-slate-500 uppercase tracking-wide mb-2">Sesi Pertanyaan</p> | |
| <div className="space-y-2"> | |
| {result.section_results.map((section, i) => ( | |
| <div key={i} className="rounded-xl border border-slate-200 bg-white overflow-hidden"> | |
| <button | |
| onClick={() => toggleSection(i)} | |
| className="w-full flex items-center justify-between px-3 py-2.5 text-left hover:bg-slate-50 transition" | |
| > | |
| <span className="font-medium text-slate-700">{section.section_title}</span> | |
| {openSections.has(i) ? ( | |
| <ChevronDown className="w-3.5 h-3.5 text-slate-400 flex-shrink-0" /> | |
| ) : ( | |
| <ChevronRight className="w-3.5 h-3.5 text-slate-400 flex-shrink-0" /> | |
| )} | |
| </button> | |
| {openSections.has(i) && ( | |
| <div className="px-3 pb-3 space-y-3 border-t border-slate-100 pt-2"> | |
| {section.section_summary && ( | |
| <p className="text-xs text-slate-500 italic">{section.section_summary}</p> | |
| )} | |
| {section.qa_pairs?.map((qa, j) => ( | |
| <QAItem key={j} qa={qa} depth={0} /> | |
| ))} | |
| </div> | |
| )} | |
| </div> | |
| ))} | |
| </div> | |
| </div> | |
| )} | |
| {/* Key Insights */} | |
| {result.key_insights?.length > 0 && ( | |
| <div> | |
| <p className="text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Key Insights</p> | |
| <ul className="space-y-1"> | |
| {result.key_insights.map((insight, i) => ( | |
| <li key={i} className="flex gap-2 text-slate-700"> | |
| <span className="text-blue-400 flex-shrink-0 mt-0.5">•</span> | |
| <span>{insight}</span> | |
| </li> | |
| ))} | |
| </ul> | |
| </div> | |
| )} | |
| {/* Unresolved Items */} | |
| {result.unresolved_items?.length > 0 && ( | |
| <div> | |
| <p className="text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">Belum Terjawab</p> | |
| <ul className="space-y-1"> | |
| {result.unresolved_items.map((item, i) => ( | |
| <li key={i} className="flex gap-2 text-amber-700"> | |
| <span className="text-amber-400 flex-shrink-0 mt-0.5">•</span> | |
| <span>{item}</span> | |
| </li> | |
| ))} | |
| </ul> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function QAItem({ qa, depth }: { qa: QAPair; depth: number }) { | |
| return ( | |
| <div className={depth > 0 ? "ml-4 pl-3 border-l-2 border-slate-100" : ""}> | |
| <p className="text-xs text-slate-500 mb-0.5">T: {qa.question_text}</p> | |
| <p className="text-slate-700">J: {qa.answer_cleaned}</p> | |
| {qa.follow_ups?.map((f, i) => ( | |
| <QAItem key={i} qa={f} depth={depth + 1} /> | |
| ))} | |
| </div> | |
| ); | |
| } | |