import { useState, useEffect } from "react"; import { ChatHeader } from "@/components/ChatHeader"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Upload, Download, Trash2, FileAudio, Copy, Search, ChevronLeft, ChevronRight } from "lucide-react"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Pagination, PaginationContent, PaginationItem, } from "@/components/ui/pagination"; import { useToast } from "@/hooks/use-toast"; import { transcriptionService, TranscriptionRecord } from "@/services/transcription"; const SUPPORTED_FORMATS = ['flac', 'm4a', 'mp3', 'mp4', 'mpeg', 'mpga', 'oga', 'ogg', 'wav', 'webm']; export const TranscriptionView = () => { const [isTranscribing, setIsTranscribing] = useState(false); const [lastTranscriptionResult, setLastTranscriptionResult] = useState(null); const [selectedFile, setSelectedFile] = useState(null); const [transcriptionHistory, setTranscriptionHistory] = useState([]); const [isLoadingTranscriptions, setIsLoadingTranscriptions] = useState(false); const [transcriptionSearchQuery, setTranscriptionSearchQuery] = useState(""); const [currentPage, setCurrentPage] = useState(1); const [perPage, setPerPage] = useState(10); const { toast } = useToast(); // Carrega transcrições do banco de dados const loadTranscriptions = async (page: number = currentPage, limit: number = perPage) => { setIsLoadingTranscriptions(true); try { const fetchedTranscriptions = await transcriptionService.getTranscriptions(undefined, page, limit); // Garante que sempre seja um array if (Array.isArray(fetchedTranscriptions)) { setTranscriptionHistory(fetchedTranscriptions); } else { console.warn('Resposta da API não é um array:', fetchedTranscriptions); setTranscriptionHistory([]); } } catch (error: any) { console.error('Erro ao carregar transcrições:', error); toast({ title: "Erro ao carregar histórico", description: error.message || "Não foi possível carregar o histórico de transcrições.", variant: "destructive", }); setTranscriptionHistory([]); } finally { setIsLoadingTranscriptions(false); } }; // Carrega transcrições ao montar e quando a paginação mudar useEffect(() => { loadTranscriptions(); }, [currentPage, perPage]); const handleFileSelect = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; // Valida o arquivo usando o serviço const validation = transcriptionService.validateAudioFile(file); if (!validation.valid) { toast({ title: "Arquivo inválido", description: validation.error, variant: "destructive", }); return; } setSelectedFile(file); handleTranscription(file); }; const handleTranscription = async (file: File) => { setIsTranscribing(true); try { // Chama o serviço de transcrição const response = await transcriptionService.transcribeAudio({ audioFile: file, }); // Verifica se a transcrição foi bem-sucedida if (response.success) { // Cria objeto da transcrição recém-gerada para exibição imediata const newTranscription: TranscriptionRecord = { id: response.transcription_id, user_email: '', estabelecimento_id: 0, audio_file_name: file.name, audio_duration_seconds: 0, transcription_text: response.message, model: 'whisper-1', audio_url: response.audio_url, cost_usd: '0', created_at: new Date().toISOString(), }; // Salva a última transcrição para exibição setLastTranscriptionResult(newTranscription); toast({ title: "Transcrição concluída", description: "Seu áudio foi transcrito com sucesso!", }); // Recarrega a lista de transcrições (sem aguardar para não bloquear a UI) loadTranscriptions(1, perPage); setCurrentPage(1); } else { throw new Error(response.message || 'Erro ao transcrever áudio'); } } catch (error: any) { console.error('Erro na transcrição:', error); toast({ title: "Erro na transcrição", description: error.message || "Não foi possível transcrever o áudio. Tente novamente.", variant: "destructive", }); } finally { setIsTranscribing(false); } }; const handleDeleteTranscription = () => { setLastTranscriptionResult(null); setSelectedFile(null); }; const handleDeleteTranscriptionFromHistory = async (transcriptionId: string) => { try { const result = await transcriptionService.deleteTranscription(transcriptionId); if (result.success) { toast({ title: "Transcrição removida", description: "A transcrição foi removida com sucesso.", }); // Se a transcrição deletada for a última gerada, limpa o preview if (lastTranscriptionResult && lastTranscriptionResult.id === transcriptionId) { setLastTranscriptionResult(null); } // Recarrega a lista de transcrições await loadTranscriptions(); } else { throw new Error(result.message || 'Erro ao deletar transcrição'); } } catch (error: any) { console.error('Erro ao deletar transcrição:', error); toast({ title: "Erro ao remover", description: error.message || "Não foi possível remover a transcrição.", variant: "destructive", }); } }; const handleCopyTranscription = (text: string) => { navigator.clipboard.writeText(text); toast({ title: "Texto copiado", description: "A transcrição foi copiada para a área de transferência", }); }; const handleDownloadTranscription = (transcription: TranscriptionRecord) => { const blob = new Blob([transcription.transcription_text], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `transcricao_${transcription.audio_file_name}.txt`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); toast({ title: "Download iniciado", description: "O arquivo de transcrição está sendo baixado.", }); }; const handlePageChange = (page: number) => { setCurrentPage(page); }; const handlePerPageChange = (value: string) => { setPerPage(parseInt(value)); setCurrentPage(1); }; const filteredTranscriptions = Array.isArray(transcriptionHistory) ? transcriptionHistory.filter(item => item.audio_file_name.toLowerCase().includes(transcriptionSearchQuery.toLowerCase()) || item.transcription_text.toLowerCase().includes(transcriptionSearchQuery.toLowerCase()) ) : []; return (
Transcrição Histórico

Converter Áudio em Texto

Envie um arquivo de áudio para transcrição (máx. 25MB)

Formatos: {SUPPORTED_FORMATS.join(', ')}

`.${f}`).join(',')} onChange={handleFileSelect} /> {isTranscribing && (

Transcrevendo áudio...

)}
{lastTranscriptionResult && (

{lastTranscriptionResult.audio_file_name}

Transcrito {new Date(lastTranscriptionResult.created_at).toLocaleTimeString('pt-BR')}

{lastTranscriptionResult.transcription_text}

)} {/* Search and Filters */}
setTranscriptionSearchQuery(e.target.value)} placeholder="Buscar por nome ou conteúdo..." className="pl-9" />
{/* Loading State */} {isLoadingTranscriptions ? (

Carregando transcrições...

) : ( <> {filteredTranscriptions.length === 0 ? (

{transcriptionSearchQuery ? 'Nenhuma transcrição encontrada' : 'Nenhuma transcrição no histórico'}

) : ( <>
{filteredTranscriptions.map((item) => (

{item.audio_file_name}

{new Date(item.created_at).toLocaleDateString('pt-BR')} às{' '} {new Date(item.created_at).toLocaleTimeString('pt-BR')}

{item.transcription_text}

))}
{/* Pagination */} {!transcriptionSearchQuery && transcriptionHistory.length >= perPage && (
Página {currentPage}
)} )} )}
); };