webapp/components/transcript.tsx (95 lines of code) (raw):

import React, { useEffect, useRef } from "react"; import { Card, CardContent } from "@/components/ui/card"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Bot, Phone, MessageSquare, Wrench } from "lucide-react"; import { Item } from "@/components/types"; type TranscriptProps = { items: Item[]; }; const Transcript: React.FC<TranscriptProps> = ({ items }) => { const scrollRef = useRef<HTMLDivElement>(null); useEffect(() => { scrollRef.current?.scrollIntoView({ behavior: "smooth" }); }, [items]); // Show messages, function calls, and function call outputs in the transcript const transcriptItems = items.filter( (it) => it.type === "message" || it.type === "function_call" || it.type === "function_call_output" ); return ( <Card className="h-full flex flex-col overflow-hidden"> <CardContent className="flex-1 h-full min-h-0 overflow-hidden flex flex-col p-0"> {transcriptItems.length === 0 && ( <div className="flex flex-1 h-full items-center justify-center mt-36"> <div className="flex flex-col items-center gap-3 justify-center h-full"> <div className="h-[140px] w-[140px] rounded-full bg-secondary/20 flex items-center justify-center"> <MessageSquare className="h-16 w-16 text-foreground/10 bg-transparent" /> </div> <div className="text-center space-y-1"> <p className="text-sm font-medium text-foreground/60"> No messages yet </p> <p className="text-sm text-muted-foreground"> Start a call to see the transcript </p> </div> </div> </div> )} <ScrollArea className="h-full"> <div className="flex flex-col gap-6 p-6"> {transcriptItems.map((msg, i) => { const isUser = msg.role === "user"; const isTool = msg.role === "tool"; // Default to assistant if not user or tool const Icon = isUser ? Phone : isTool ? Wrench : Bot; // Combine all text parts into a single string for display const displayText = msg.content ? msg.content.map((c) => c.text).join("") : ""; return ( <div key={i} className="flex items-start gap-3"> <div className={`shrink-0 w-8 h-8 rounded-full flex items-center justify-center border ${ isUser ? "bg-background border-border" : isTool ? "bg-secondary border-secondary" : "bg-secondary border-secondary" }`} > <Icon className="h-4 w-4" /> </div> <div className="flex-1 min-w-0"> <div className="flex items-center gap-2 mb-1.5"> <span className={`text-sm font-medium ${ isUser ? "text-muted-foreground" : "text-foreground" }`} > {isUser ? "Caller" : isTool ? "Tool Response" : "Assistant"} </span> <span className="text-xs text-muted-foreground"> {msg.timestamp} </span> </div> <p className="text-sm text-muted-foreground leading-relaxed break-words"> {displayText} </p> </div> </div> ); })} <div ref={scrollRef} /> </div> </ScrollArea> </CardContent> </Card> ); }; export default Transcript;