mirror of
https://github.com/arkorty/B.Tech-Project-III.git
synced 2026-04-19 20:51:49 +00:00
init
This commit is contained in:
184
negot8/dashboard/components/ResolutionCard.tsx
Normal file
184
negot8/dashboard/components/ResolutionCard.tsx
Normal file
@@ -0,0 +1,184 @@
|
||||
"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;
|
||||
}
|
||||
Reference in New Issue
Block a user