customer-support-agent/components/LeftSidebar.tsx (178 lines of code) (raw):

"use client"; import React, { useState, useEffect } from "react"; import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; import { User, DollarSign, Info, Wrench, Zap, Building2, Scale, ChartBarBig, CircleHelp, } from "lucide-react"; interface ThinkingContent { id: string; content: string; user_mood?: string; matched_categories?: string[]; debug?: { context_used: boolean; }; } const getDebugPillColor = (value: boolean): string => { return value ? "bg-green-100 text-green-800 border-green-300" // Success : "bg-yellow-100 text-yellow-800 border-yellow-300"; // Not Used/Not Relevant }; const getMoodColor = (mood: string): string => { const colors: { [key: string]: string } = { positive: "bg-green-100 text-green-800", negative: "bg-red-100 text-red-800", curious: "bg-blue-100 text-blue-800", frustrated: "bg-orange-100 text-orange-800", confused: "bg-yellow-100 text-yellow-800", neutral: "bg-gray-100 text-gray-800", }; return colors[mood?.toLowerCase()] || "bg-gray-100 text-gray-800"; }; const MAX_THINKING_HISTORY = 15; const LeftSidebar: React.FC = () => { const [thinkingContents, setThinkingContents] = useState<ThinkingContent[]>( [], ); useEffect(() => { const handleUpdateSidebar = (event: CustomEvent<ThinkingContent>) => { if (event.detail && event.detail.id) { console.log("🔍 DEBUG: Sidebar Event:", event.detail); setThinkingContents((prev) => { const exists = prev.some((item) => item.id === event.detail.id); if (!exists) { console.log( "📝 New thinking entry: ", event.detail.content.slice(0, 50) + "...", ); // Shows first 50 chars // Add a timestamp! const enhancedEntry = { ...event.detail, timestamp: new Date().toISOString(), }; const newHistory = [enhancedEntry, ...prev].slice( 0, MAX_THINKING_HISTORY, ); // Always keep latest 20 return newHistory; } return prev; }); } else { console.warn("Missing 'id' in sidebar event detail:", event.detail); } }; window.addEventListener( "updateSidebar", handleUpdateSidebar as EventListener, ); return () => window.removeEventListener( "updateSidebar", handleUpdateSidebar as EventListener, ); }, []); return ( <aside className="w-[380px] pl-4 overflow-hidden pb-4"> <Card className="h-full overflow-hidden"> <CardHeader> <CardTitle className="text-sm font-medium leading-none"> Assistant Thinking </CardTitle> </CardHeader> <CardContent className="overflow-y-auto h-[calc(100%-45px)]"> {thinkingContents.length === 0 ? ( <div className="text-sm text-muted-foreground"> The assistant inner dialogue will appear here for you to debug it </div> ) : ( thinkingContents.map((content) => ( <Card key={content.id} className="mb-4 animate-fade-in-up" style={{ animationDuration: "600ms", animationFillMode: "backwards", animationTimingFunction: "cubic-bezier(0.2, 0.8, 0.2, 1)", // This adds bounce }} > <CardContent className="py-4"> <div className="text-sm text-muted-foreground"> {content.content} </div> {content.user_mood && content.debug && ( <div className="flex items-center space-x-2 mt-4 text-xs"> {/* Mood */} <span className={`px-2 py-1 rounded-full ${getMoodColor(content.user_mood)}`} > {content.user_mood.charAt(0).toUpperCase() + content.user_mood.slice(1)} </span> <span className={`px-2 py-1 rounded-full ${getDebugPillColor(content.debug.context_used)}`} > Context: {content.debug.context_used ? "✅" : "❌"} </span> </div> )} {content.matched_categories && content.matched_categories.length > 0 && ( <div className="mt-2"> {content.matched_categories.map((category) => ( <div key={category} className="inline-flex items-center mr-2 mt-2 text-muted-foreground text-xs py-0" > {category === "account" && ( <User className="w-3 h-3 mr-1" /> )} {category === "billing" && ( <DollarSign className="w-3 h-3 mr-1" /> )} {category === "feature" && ( <Zap className="w-3 h-3 mr-1" /> )} {category === "internal" && ( <Building2 className="w-3 h-3 mr-1" /> )} {category === "legal" && ( <Scale className="w-3 h-3 mr-1" /> )} {category === "other" && ( <CircleHelp className="w-3 h-3 mr-1" /> )} {category === "technical" && ( <Wrench className="w-3 h-3 mr-1" /> )} {category === "usage" && ( <ChartBarBig className="w-3 h-3 mr-1" /> )} {category .split("_") .map( (word) => word.charAt(0).toUpperCase() + word.slice(1), ) .join(" ")} </div> ))} </div> )} </CardContent> </Card> )) )} </CardContent> </Card> </aside> ); }; export default LeftSidebar;