"use client"; import { useState } from "react"; import type { Asset, MarketListing, MarketNegotiation } from "@/payload-types"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import { formatAmount } from "@/lib/banking/format"; import { buildChatBubbles } from "@/lib/market/chatBubbles"; import { ChatBubbleList } from "@/components/frontend/market/ChatBubbleList"; import { HistoryIcon, ChevronDownIcon } from "lucide-react"; import { cn } from "@/lib/utils"; const STATUS_LABELS: Record = { open: "Open", accepted: "Accepted", rejected: "Rejected", closed: "Closed", cancelled: "Cancelled", expired: "Expired", }; function listingOf(negotiation: MarketNegotiation): MarketListing | null { return typeof negotiation.listing === "object" && negotiation.listing ? (negotiation.listing as MarketListing) : null; } function assetName(listing: MarketListing | null): string { if (!listing) return "Unknown item"; const asset = listing.asset as Asset; return typeof asset === "object" && asset ? asset.name : `Asset #${listing.asset}`; } function counterpartyLabel(negotiation: MarketNegotiation, role: "buyer" | "seller"): string { if (role === "seller") { const listing = listingOf(negotiation); if (listing?.isAutoGenerated) { const npc = listing.npc as unknown; if (typeof npc === "object" && npc && "name" in (npc as object)) { return (npc as { name: string }).name; } return "Market vendor"; } const seller = listing?.seller as unknown; if (typeof seller === "object" && seller && "username" in (seller as object)) { return ( (seller as { username?: string; displayName?: string }).displayName || (seller as { username?: string }).username || "Seller" ); } return "Seller"; } const buyer = negotiation.buyer as unknown; if (typeof buyer === "object" && buyer && "username" in (buyer as object)) { return (buyer as { username?: string }).username ?? "Buyer"; } return "Buyer"; } function HistoryRow({ negotiation, role, currencyLabel, }: { negotiation: MarketNegotiation; role: "buyer" | "seller"; currencyLabel: string | null; }) { const [expanded, setExpanded] = useState(false); const listing = listingOf(negotiation); const fmt = (n: number) => formatAmount(n, { name: currencyLabel ?? undefined }); const buyerLabel = role === "buyer" ? "You" : counterpartyLabel(negotiation, "buyer"); const sellerLabel = role === "seller" ? "You" : counterpartyLabel(negotiation, "seller"); const counterparty = role === "buyer" ? sellerLabel : buyerLabel; const date = new Date(negotiation.updatedAt).toLocaleDateString(); const isOpen = negotiation.status === "open"; return (
{assetName(listing)} {counterparty} ยท {date}
{fmt(negotiation.amount ?? 0)} {STATUS_LABELS[negotiation.status] ?? negotiation.status}
{listing && ( )}
); } interface NegotiationHistoryDialogProps { negotiations: MarketNegotiation[]; currentUserId: number; currencyLabel: string | null; } export function NegotiationHistoryDialog({ negotiations, currentUserId, currencyLabel, }: NegotiationHistoryDialogProps) { const [open, setOpen] = useState(false); const sorted = [...negotiations].sort( (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(), ); return ( Negotiation history Your offers, counters and vendor conversations. Tap a row to expand the chat.
{sorted.length === 0 ? (

No negotiations yet.

) : ( sorted.map((negotiation) => { const buyerId = typeof negotiation.buyer === "object" && negotiation.buyer ? negotiation.buyer.id : (negotiation.buyer as number); const role: "buyer" | "seller" = buyerId === currentUserId ? "buyer" : "seller"; return ( ); }) )}
); }