"use client"; import { useEffect, useState, useCallback, useMemo } from "react"; import Link from "next/link"; import { api } from "@/lib/api"; import type { Negotiation } from "@/lib/types"; import { FEATURE_LABELS, STATUS_COLORS, STATUS_LABELS, relativeTime } from "@/lib/utils"; import Sidebar from "@/components/Sidebar"; function Icon({ name, className = "" }: { name: string; className?: string }) { return {name}; } const FEATURE_ICONS: Record = { scheduling: "calendar_month", expenses: "account_balance_wallet", freelance: "work", roommate: "home", trip: "flight_takeoff", marketplace: "store", collaborative: "groups", conflict: "gavel", generic: "hub", }; const STATUS_FILTERS = [ { key: "all", label: "All Statuses", dot: "" }, { key: "resolved", label: "Resolved", dot: "bg-emerald-400" }, { key: "escalated", label: "Escalated", dot: "bg-rose-400" }, { key: "active", label: "In Progress", dot: "bg-amber-400" }, { key: "pending", label: "Pending", dot: "bg-slate-400" }, ]; const STATUS_BADGE: Record = { resolved: "text-emerald-400 bg-emerald-500/10 border-emerald-500/20", escalated: "text-rose-400 bg-rose-500/10 border-rose-500/20", active: "text-amber-400 bg-amber-500/10 border-amber-500/20", pending: "text-slate-400 bg-white/5 border-white/10", }; const PAGE_SIZE = 8; export default function HistoryPage() { const [negotiations, setNegotiations] = useState([]); const [loading, setLoading] = useState(true); const [search, setSearch] = useState(""); const [statusFilter, setStatusFilter] = useState("all"); const [page, setPage] = useState(1); const load = useCallback(async () => { try { const res = await api.negotiations(); setNegotiations(res.negotiations); } finally { setLoading(false); } }, []); useEffect(() => { load(); }, [load]); const filtered = useMemo(() => { return negotiations.filter((n) => { const matchStatus = statusFilter === "all" || n.status === statusFilter; const matchSearch = !search || n.id.toLowerCase().includes(search.toLowerCase()) || (FEATURE_LABELS[n.feature_type] ?? n.feature_type) .toLowerCase() .includes(search.toLowerCase()); return matchStatus && matchSearch; }); }, [negotiations, statusFilter, search]); const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE)); const paginated = filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE); const getFairness = (n: Negotiation) => { const r = (n as any).result; if (r?.fairness_score != null) return Math.round(r.fairness_score * 100); return null; }; return (
{/* Top bar */}

Negotiation History

{filtered.length} record{filtered.length !== 1 ? "s" : ""} found

New Request
{/* Search + Filters */}
{ setSearch(e.target.value); setPage(1); }} placeholder="Search by ID or feature type..." className="w-full bg-white/5 border border-white/10 rounded-lg pl-10 pr-4 py-2.5 text-sm text-white placeholder-slate-600 focus:outline-none focus:border-[#B7A6FB]/40 transition-all" />
{STATUS_FILTERS.map((f) => ( ))}
{/* Table */} {loading ? (
) : paginated.length === 0 ? (

No negotiations match your filters.

) : (
{paginated.map((neg, i) => { const fairness = getFairness(neg); return ( {/* Feature */} {/* Participants */} {/* Status */} {/* Fairness */} {/* Date */} {/* Actions */} ); })}
Feature Participants Status Fairness Date Actions

{FEATURE_LABELS[neg.feature_type] ?? neg.feature_type}

#{neg.id.slice(0, 8)}

{[...Array(Math.min(neg.participant_count ?? 0, 3))].map((_, j) => (
{String.fromCharCode(65 + j)}
))}
{STATUS_LABELS[neg.status] ?? neg.status} {fairness != null ? (
{fairness}%
) : ( )}
{relativeTime(neg.created_at)}
{/* Pagination */}
Showing {Math.min((page - 1) * PAGE_SIZE + 1, filtered.length)}– {Math.min(page * PAGE_SIZE, filtered.length)} of {filtered.length} negotiations
)}
); }