1+ import React , { useState } from 'react' ;
2+ import { Download , Copy , FileText , FileJson , Share2 } from 'lucide-react' ;
3+ import { TranscriptResponse } from '../types' ;
4+
5+ interface ExportOptionsProps {
6+ transcript : TranscriptResponse ;
7+ }
8+
9+ const ExportOptions : React . FC < ExportOptionsProps > = ( { transcript } ) => {
10+ const [ copied , setCopied ] = useState ( false ) ;
11+ const [ exportFormat , setExportFormat ] = useState < 'txt' | 'docx' | 'json' > ( 'txt' ) ;
12+
13+ const formatTranscriptAsText = ( ) => {
14+ let result = '' ;
15+ let currentSpeaker = '' ;
16+ let currentText = '' ;
17+
18+ transcript . words . forEach ( ( word , index ) => {
19+ if ( word . type === 'word' ) {
20+ if ( currentSpeaker === '' ) {
21+ // First word
22+ currentSpeaker = word . speaker_id ;
23+ currentText = word . text ;
24+ } else if ( word . speaker_id !== currentSpeaker ) {
25+ // Speaker changed
26+ result += `${ currentSpeaker . replace ( 'speaker_' , 'Speaker ' ) } : ${ currentText . trim ( ) } \n\n` ;
27+ currentSpeaker = word . speaker_id ;
28+ currentText = word . text ;
29+ } else {
30+ // Same speaker continues
31+ currentText += word . text ;
32+ }
33+ } else if ( word . type === 'spacing' ) {
34+ currentText += ' ' ;
35+ }
36+
37+ // Handle last word
38+ if ( index === transcript . words . length - 1 && currentSpeaker ) {
39+ result += `${ currentSpeaker . replace ( 'speaker_' , 'Speaker ' ) } : ${ currentText . trim ( ) } \n` ;
40+ }
41+ } ) ;
42+
43+ return result ;
44+ } ;
45+
46+ const copyToClipboard = ( ) => {
47+ const text = formatTranscriptAsText ( ) ;
48+ navigator . clipboard . writeText ( text ) ;
49+ setCopied ( true ) ;
50+ setTimeout ( ( ) => setCopied ( false ) , 2000 ) ;
51+ } ;
52+
53+ const downloadTranscript = ( ) => {
54+ let content : string ;
55+ let mimeType : string ;
56+ let fileExtension : string ;
57+
58+ if ( exportFormat === 'json' ) {
59+ content = JSON . stringify ( transcript , null , 2 ) ;
60+ mimeType = 'application/json' ;
61+ fileExtension = 'json' ;
62+ } else {
63+ // Default to txt
64+ content = formatTranscriptAsText ( ) ;
65+ mimeType = 'text/plain' ;
66+ fileExtension = 'txt' ;
67+ }
68+
69+ const blob = new Blob ( [ content ] , { type : mimeType } ) ;
70+ const url = URL . createObjectURL ( blob ) ;
71+ const a = document . createElement ( 'a' ) ;
72+ a . href = url ;
73+ a . download = `transcript.${ fileExtension } ` ;
74+ document . body . appendChild ( a ) ;
75+ a . click ( ) ;
76+ document . body . removeChild ( a ) ;
77+ URL . revokeObjectURL ( url ) ;
78+ } ;
79+
80+ const shareTranscript = async ( ) => {
81+ if ( navigator . share ) {
82+ try {
83+ await navigator . share ( {
84+ title : 'Audio Transcript' ,
85+ text : formatTranscriptAsText ( ) ,
86+ } ) ;
87+ } catch ( err ) {
88+ console . error ( 'Error sharing:' , err ) ;
89+ }
90+ } else {
91+ copyToClipboard ( ) ;
92+ }
93+ } ;
94+
95+ return (
96+ < div className = "bg-gray-800 rounded-xl p-4 border border-gray-700 mb-8" >
97+ < h3 className = "text-lg font-medium text-gray-200 mb-3" > Export Options</ h3 >
98+
99+ < div className = "flex flex-wrap gap-3 mb-4" >
100+ < button
101+ onClick = { ( ) => setExportFormat ( 'txt' ) }
102+ className = { `px-3 py-2 rounded-md flex items-center text-sm ${
103+ exportFormat === 'txt'
104+ ? 'bg-blue-600 text-white'
105+ : 'bg-gray-700 text-gray-300 hover:bg-gray-600'
106+ } transition-colors`}
107+ >
108+ < FileText className = "h-4 w-4 mr-2" />
109+ Text
110+ </ button >
111+
112+ < button
113+ onClick = { ( ) => setExportFormat ( 'json' ) }
114+ className = { `px-3 py-2 rounded-md flex items-center text-sm ${
115+ exportFormat === 'json'
116+ ? 'bg-blue-600 text-white'
117+ : 'bg-gray-700 text-gray-300 hover:bg-gray-600'
118+ } transition-colors`}
119+ >
120+ < FileJson className = "h-4 w-4 mr-2" />
121+ JSON
122+ </ button >
123+ </ div >
124+
125+ < div className = "flex flex-wrap gap-3" >
126+ < button
127+ onClick = { downloadTranscript }
128+ className = "px-4 py-2 bg-gradient-to-r from-green-600 to-emerald-500 rounded-md text-white flex items-center hover:from-green-700 hover:to-emerald-600 transition-colors"
129+ >
130+ < Download className = "h-4 w-4 mr-2" />
131+ Download
132+ </ button >
133+
134+ < button
135+ onClick = { copyToClipboard }
136+ className = { `px-4 py-2 bg-gray-700 rounded-md text-white flex items-center hover:bg-gray-600 transition-colors ${
137+ copied ? 'bg-green-600 hover:bg-green-700' : ''
138+ } `}
139+ >
140+ < Copy className = "h-4 w-4 mr-2" />
141+ { copied ? 'Copied!' : 'Copy' }
142+ </ button >
143+
144+ < button
145+ onClick = { shareTranscript }
146+ className = "px-4 py-2 bg-gray-700 rounded-md text-white flex items-center hover:bg-gray-600 transition-colors"
147+ >
148+ < Share2 className = "h-4 w-4 mr-2" />
149+ Share
150+ </ button >
151+ </ div >
152+ </ div >
153+ ) ;
154+ } ;
155+
156+ export default ExportOptions ;
0 commit comments