diff --git a/web/src/components/transcript.tsx b/web/src/components/transcript.tsx index 38ad3246..3766ebad 100644 --- a/web/src/components/transcript.tsx +++ b/web/src/components/transcript.tsx @@ -69,10 +69,57 @@ export function Transcript({ } }, [scrollButtonRef]); + const handleDownloadTranscript = () => { + // Create CSV content + let csvContent = "Timestamp,Participant,Text\n"; + + displayTranscriptions.forEach(({ segment, participant, timestamp }) => { + const csvRow = [ + new Date(timestamp || 0).toLocaleTimeString([], { + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + hour12: false + }), + participant?.isAgent ? "Agent" : "User", + `"${segment.text.trim().replace(/"/g, '""')}"`, // Escape quotes in the text + ].join(","); + + csvContent += csvRow + "\n"; + }); + + // Create Blob + const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" }); + + // Create download link + const link = document.createElement("a"); + if (link.download !== undefined) { + const url = URL.createObjectURL(blob); + link.setAttribute("href", url); + link.setAttribute( + "download", + `transcript_${new Date().toISOString()}.csv` + ); + link.style.visibility = "hidden"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + console.log("Downloading transcript..."); + }; + return ( <> -
- Transcript +
+

+ Transcript +

+
{displayTranscriptions.length === 0 ? ( @@ -82,7 +129,7 @@ export function Transcript({ ) : (
{displayTranscriptions.map( - ({ segment, participant, publication }) => + ({ segment, participant, publication, timestamp }) => segment.text.trim() !== "" && (
- {segment.text.trim()} +
+ {segment.text.trim()} + + {new Date(timestamp || 0).toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + second: '2-digit', + })} + +
), )} diff --git a/web/src/hooks/use-agent.tsx b/web/src/hooks/use-agent.tsx index 9ffc4679..f9f5e278 100644 --- a/web/src/hooks/use-agent.tsx +++ b/web/src/hooks/use-agent.tsx @@ -18,6 +18,7 @@ interface Transcription { segment: TranscriptionSegment; participant?: Participant; publication?: TrackPublication; + timestamp?: number; // Add this line to include a timestamp } interface AgentContextType { @@ -89,7 +90,7 @@ export function AgentProvider({ children }: { children: React.ReactNode }) { ); const mergedSorted = sorted.reduce((acc, current) => { if (acc.length === 0) { - return [current]; + return [{...current, timestamp: current.segment.firstReceivedTime}]; } const last = acc[acc.length - 1]; @@ -113,10 +114,11 @@ export function AgentProvider({ children }: { children: React.ReactNode }) { id: current.segment.id, // Use the id of the latest segment firstReceivedTime: last.segment.firstReceivedTime, // Keep the original start time }, + timestamp: last.timestamp, // Keep the earliest timestamp }, ]; } else { - return [...acc, current]; + return [...acc, {...current, timestamp: current.segment.firstReceivedTime}]; } }, [] as Transcription[]); setDisplayTranscriptions(mergedSorted);