Files
B.Tech-Project-III/negot8/dashboard/components/ResolutionCard.tsx
2026-04-05 00:43:23 +05:30

185 lines
7.9 KiB
TypeScript

"use client";
import { Negotiation } from "@/lib/types";
import { FEATURE_LABELS } from "@/lib/utils";
function Icon({ name, className = "" }: { name: string; className?: string }) {
return <span className={`material-symbols-outlined ${className}`}>{name}</span>;
}
interface Props {
negotiation: Negotiation;
}
export default function ResolutionCard({ negotiation }: Props) {
const resolution = negotiation.resolution as Record<string, unknown> | null;
const status = negotiation.status;
const analytics = negotiation.analytics;
if (!resolution && status !== "resolved" && status !== "escalated") {
return (
<div className="text-xs text-slate-600 py-4 text-center font-mono">
Resolution not yet available
</div>
);
}
const final = (resolution?.final_proposal ?? {}) as Record<string, unknown>;
const details = (final.details ?? {}) as Record<string, unknown>;
const roundsTaken = resolution?.rounds_taken as number | undefined;
const summaryText = String(final.summary ?? resolution?.summary ?? "");
const forPartyA = final.for_party_a ? String(final.for_party_a) : null;
const forPartyB = final.for_party_b ? String(final.for_party_b) : null;
const upiLink = (details.upi_link ?? details.upilink)
? String(details.upi_link ?? details.upilink)
: null;
const isResolved = status === "resolved";
return (
<div className="space-y-5">
{/* Hero card — matches Stitch resolution screen */}
<div
className={`relative rounded-xl border overflow-hidden ${
isResolved
? "border-emerald-500/30 bg-emerald-900/5"
: "border-amber-500/30 bg-amber-900/5"
}`}
>
{/* Top gradient line */}
<div
className={`absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent ${
isResolved ? "via-emerald-400" : "via-amber-400"
} to-transparent opacity-60`}
/>
<div className="p-5">
<div className="flex items-center gap-3 mb-3">
<div
className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full border text-[10px] font-bold uppercase tracking-wider ${
isResolved
? "bg-emerald-500/10 border-emerald-500/20 text-emerald-400"
: "bg-amber-500/10 border-amber-500/20 text-amber-400"
}`}
>
<Icon name={isResolved ? "check_circle" : "warning"} className="text-sm" />
{isResolved ? "Resolved" : "Escalated"}
</div>
<span className="text-[10px] text-slate-600 font-mono">
{FEATURE_LABELS[negotiation.feature_type]}
{roundsTaken ? ` · ${roundsTaken} round${roundsTaken > 1 ? "s" : ""}` : ""}
</span>
</div>
{summaryText && (
<p className="text-sm text-slate-300 leading-relaxed font-light">{summaryText}</p>
)}
</div>
</div>
{/* Stats row */}
{analytics && (
<div className="grid grid-cols-3 gap-3">
<MetricBox label="Fairness" value={`${analytics.fairness_score?.toFixed(0)}%`} highlight />
<MetricBox label="Total Rounds" value={String(roundsTaken ?? "—")} />
<MetricBox
label="Concessions"
value={`${analytics.total_concessions_a + analytics.total_concessions_b}`}
/>
</div>
)}
{/* Per-party outcomes */}
{(forPartyA || forPartyB) && (
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{forPartyA && (
<div className="bg-[#B7A6FB]/5 border border-[#B7A6FB]/20 rounded-lg p-3 hover:border-[#B7A6FB]/40 transition-colors">
<div className="text-[10px] font-mono text-[#B7A6FB] mb-2 uppercase tracking-wider">Agent A</div>
<p className="text-xs text-slate-300 leading-relaxed">{forPartyA}</p>
</div>
)}
{forPartyB && (
<div className="bg-cyan-900/10 border border-cyan-500/20 rounded-lg p-3 hover:border-cyan-500/40 transition-colors">
<div className="text-[10px] font-mono text-cyan-400 mb-2 uppercase tracking-wider">Agent B</div>
<p className="text-xs text-slate-300 leading-relaxed">{forPartyB}</p>
</div>
)}
</div>
)}
{/* Action buttons */}
<div className="grid grid-cols-2 gap-3">
{upiLink && (
<a
href={upiLink}
target="_blank"
rel="noopener noreferrer"
className="group relative flex items-center gap-3 p-4 rounded-xl border border-[#222249] bg-[#101023] hover:border-[#B7A6FB]/40 transition-all overflow-hidden text-left"
>
<div className="p-2 rounded-lg bg-indigo-500/20 text-indigo-300 group-hover:bg-indigo-500/30 transition-colors">
<Icon name="credit_card" className="text-lg" />
</div>
<div>
<div className="text-white text-sm font-bold">Pay via UPI</div>
<div className="text-slate-500 text-[10px]">Instant settlement</div>
</div>
<Icon name="arrow_forward" className="ml-auto text-[#B7A6FB] text-base opacity-0 group-hover:opacity-100 transition-opacity" />
</a>
)}
<button className="group relative flex items-center gap-3 p-4 rounded-xl border border-[#222249] bg-[#101023] hover:border-[#B7A6FB]/40 transition-all overflow-hidden text-left">
<div className="p-2 rounded-lg bg-sky-500/20 text-sky-300 group-hover:bg-sky-500/30 transition-colors">
<Icon name="chat" className="text-lg" />
</div>
<div>
<div className="text-white text-sm font-bold">Telegram</div>
<div className="text-slate-500 text-[10px]">Open channel</div>
</div>
<Icon name="arrow_forward" className="ml-auto text-[#B7A6FB] text-base opacity-0 group-hover:opacity-100 transition-opacity" />
</button>
<button className="group relative flex items-center gap-3 p-4 rounded-xl border border-[#222249] bg-[#101023] hover:border-[#B7A6FB]/40 transition-all overflow-hidden text-left">
<div className="p-2 rounded-lg bg-orange-500/20 text-orange-300 group-hover:bg-orange-500/30 transition-colors">
<Icon name="picture_as_pdf" className="text-lg" />
</div>
<div>
<div className="text-white text-sm font-bold">Download PDF</div>
<div className="text-slate-500 text-[10px]">Full transcript</div>
</div>
<Icon name="download" className="ml-auto text-[#B7A6FB] text-base opacity-0 group-hover:opacity-100 transition-opacity" />
</button>
<button className="group relative flex items-center gap-3 p-4 rounded-xl border border-[#222249] bg-[#101023] hover:border-[#B7A6FB]/40 transition-all overflow-hidden text-left">
<div className="p-2 rounded-lg bg-pink-500/20 text-pink-300 group-hover:bg-pink-500/30 transition-colors">
<Icon name="graphic_eq" className="text-lg" />
</div>
<div>
<div className="text-white text-sm font-bold">Voice Summary</div>
<div className="text-slate-500 text-[10px]">AI generated audio</div>
</div>
<Icon name="play_arrow" className="ml-auto text-[#B7A6FB] text-base opacity-0 group-hover:opacity-100 transition-opacity" />
</button>
</div>
</div>
);
}
function MetricBox({
label,
value,
highlight = false,
}: {
label: string;
value: string;
highlight?: boolean;
}) {
return (
<div className="flex flex-col gap-1 p-3 rounded-lg bg-white/5 border border-white/10 hover:border-[#B7A6FB]/30 transition-colors">
<span className="text-slate-500 text-[10px] font-mono">{label}</span>
<span className={`text-xl font-light tabular-nums ${highlight ? "text-[#B7A6FB]" : "text-white"}`}>
{value}
</span>
</div>
);
}
interface Props {
negotiation: Negotiation;
}