diff options
| author | Ilan Bigio <ilan@openai.com> | 2024-12-16 13:06:08 -0800 |
|---|---|---|
| committer | Ilan Bigio <ilan@openai.com> | 2024-12-19 16:08:22 -0500 |
| commit | 20009aed53d8864c9204d43a17895168a777d2cc (patch) | |
| tree | 754dded819869bc34a8a2a02c66ea72dac1ccd24 /webapp/components/transcript.tsx | |
Initial commit
Diffstat (limited to 'webapp/components/transcript.tsx')
| -rw-r--r-- | webapp/components/transcript.tsx | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/webapp/components/transcript.tsx b/webapp/components/transcript.tsx new file mode 100644 index 0000000..bc2ecbd --- /dev/null +++ b/webapp/components/transcript.tsx @@ -0,0 +1,104 @@ +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; |
