import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { apiClient } from "../lib/apiClient"; import { Inbox as InboxIcon, Search, Send, Sparkles, CheckCircle2, AlertCircle, Clock, Mail, Calendar, User, Building, ChevronRight, Paperclip, Smile, RefreshCw } from "lucide-react"; import { useState } from "react"; import DOMPurify from "dompurify"; import StatusBadge from "../components/StatusBadge"; import RichTextEditor from "../components/RichTextEditor"; import toast from "react-hot-toast"; const CATEGORIES = [ { key: "ALL", label: "All Messages" }, { key: "INTERESTED", label: "Interested" }, { key: "MEETING_BOOKED", label: "Meeting Booked" }, { key: "REPLIED", label: "Replied" }, { key: "NOT_INTERESTED", label: "Not Interested" }, ]; export default function Inbox() { const queryClient = useQueryClient(); const [selectedCategory, setSelectedCategory] = useState("ALL"); const [selectedMessageId, setSelectedMessageId] = useState("msg_001"); const [replyBody, setReplyBody] = useState(""); const { data: messages = [], isLoading, refetch } = useQuery({ queryKey: ["inbox-messages", selectedCategory], queryFn: async () => { const res = await apiClient.get("/inbox", { params: selectedCategory !== "ALL" ? { category: selectedCategory } : {}, }); return res.data; }, }); const selectedMessage = (Array.isArray(messages) ? messages : []).find((m: any) => m.id === selectedMessageId) || (Array.isArray(messages) ? messages[0] : null); const updateCategoryMutation = useMutation({ mutationFn: async ({ messageId, category }: { messageId: string; category: string }) => { const res = await apiClient.post(`/inbox/${messageId}/category`, { category }); return res.data; }, onSuccess: () => { toast.success("Lead categorization updated"); refetch(); }, }); const sendReplyMutation = useMutation({ mutationFn: async ({ messageId, body }: { messageId: string; body: string }) => { const res = await apiClient.post(`/inbox/${messageId}/reply`, { reply_body: body }); return res.data; }, onSuccess: () => { toast.success("Reply dispatched to lead!"); setReplyBody(""); refetch(); }, onError: () => { toast.error("Failed to send reply"); } }); return (
{/* Top Controls */}

Unified Master Inbox AI Sentiment Active

{/* 2-Pane Inbox Workspace */}
{/* Left Pane: Message List */}
{/* Categories Filter Tabs */}
{CATEGORIES.map((cat) => ( ))}
{/* Messages Scroll Area */}
{messages.map((msg: any) => { const isSelected = msg.id === selectedMessage?.id; return (
setSelectedMessageId(msg.id)} className={`p-4 transition-colors cursor-pointer ${ isSelected ? "bg-indigo-950/30 border-l-2 border-indigo-500" : "hover:bg-zinc-900/40" }`} >
{msg.from_name || msg.from_email} {new Date(msg.created_at || Date.now()).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}

{msg.subject}

{msg.preview_body || msg.body?.replace(/<[^>]*>?/gm, "")}

{msg.company_name}
); })} {messages.length === 0 && (
No replies found for this category filter.
)}
{/* Right Pane: Thread View & Response Composer */} {selectedMessage ? (
{/* Thread Header */}
{selectedMessage.from_name ? selectedMessage.from_name[0] : "L"}

{selectedMessage.subject}

{selectedMessage.from_name} <{selectedMessage.from_email}> • {selectedMessage.company_name}
{/* Categorization Dropdown */}
AI Intent:
{/* Conversation Messages */}
{/* Outbound Sent Message */}
Outbound Step #1 (Sent by Sequence) Yesterday
Hi {selectedMessage.from_name?.split(" ")[0] || "there"},

Wanted to see how your team is managing deliverability and scale this quarter?

Best regards,
Alex
{/* Inbound Prospect Reply */}
{selectedMessage.from_name} (Prospect Reply) Today
{/* Reply Composer Bottom Section */}
) : (
Select a message thread from the left pane to view conversation.
)}
); }