E2E-Frontend-Data-Eyond / src /app /components /interview /InterviewResultView.tsx
ishaq101's picture
feat:interview (#1)
fe828ac
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>
);
}