import Link from "next/link" import { notFound } from "next/navigation" import { fetchQuery } from "convex/nextjs" import { ArrowLeft, ExternalLink, MessageSquare } from "lucide-react" import { api } from "@/convex/_generated/api" import { Badge } from "@/components/ui/badge" import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card" type PageProps = { params: Promise<{ id: string }> } function formatTimestamp(value?: number) { if (!value) { return "—" } return new Date(value).toLocaleString("en-US", { month: "short", day: "numeric", year: "numeric", hour: "2-digit", minute: "2-digit", }) } function formatDuration(value?: number) { if (!value) { return "—" } const totalSeconds = Math.round(value / 1000) const minutes = Math.floor(totalSeconds / 60) const seconds = totalSeconds % 60 return `${minutes}:${String(seconds).padStart(2, "0")}` } export default async function AdminConversationDetailPage({ params, }: PageProps) { const { id } = await params const detail = await fetchQuery(api.crm.getAdminConversationDetail, { conversationId: id, }) if (!detail) { notFound() } return (
Unified thread for Rocky-owned conversation management.
Channel
Status
Contact
{detail.contact?.name || "Unlinked"}
Started
{formatTimestamp(detail.conversation.startedAt)}
Last Activity
{formatTimestamp(detail.conversation.lastMessageAt)}
GHL Conversation ID
{detail.conversation.ghlConversationId || "—"}
Summary
{detail.conversation.summaryText}
{recording.transcriptionText}
) : null}{lead.type}
{lead.message || lead.intent || "—"}
No recordings or linked leads for this conversation yet.
) : null}No messages have been mirrored into this conversation yet.
) : ( detail.messages.map((message: any) => ({message.body}