diff --git a/src/components/areas/AreasView.tsx b/src/components/areas/AreasView.tsx index 40ff800..7e33cf3 100644 --- a/src/components/areas/AreasView.tsx +++ b/src/components/areas/AreasView.tsx @@ -40,6 +40,7 @@ export function AreasView() { const [loadingList, setLoadingList] = useState(true); const totalPages = Math.max(1, totalPaginas); + const isFiltering = filterNome.trim().length > 0; useEffect(() => { let cancelled = false; @@ -262,7 +263,7 @@ export function AreasView() {
- {!loadingList && areasList.length === 0 && totalRegistros === 0 ? ( + {!loadingList && totalRegistros === 0 && !isFiltering ? ( @@ -297,6 +298,12 @@ export function AreasView() { Carregando... + ) : totalRegistros === 0 ? ( + + + Nenhum resultado para o filtro {filterNome.trim() ? `"${filterNome.trim()}"` : "atual"}. + + ) : ( areasList.map((item) => ( diff --git a/src/components/audio/AudioView.tsx b/src/components/audio/AudioView.tsx index 15315c7..4d9a905 100644 --- a/src/components/audio/AudioView.tsx +++ b/src/components/audio/AudioView.tsx @@ -14,6 +14,7 @@ import { SelectValue, } from "@/components/ui/select"; import { useToast } from "@/hooks/use-toast"; +import { audioGenerationService } from "@/services/audioGeneration"; const SUPPORTED_FORMATS = ['flac', 'm4a', 'mp3', 'mp4', 'mpeg', 'mpga', 'oga', 'ogg', 'wav', 'webm']; const MAX_FILE_SIZE = 25 * 1024 * 1024; // 25 MB @@ -186,19 +187,23 @@ export const AudioView = () => { }, 2000); }; - const handleDownloadAudio = (audio: GeneratedAudio) => { - // In real implementation, download the actual audio file - const a = document.createElement('a'); - a.href = audio.audioUrl; - a.download = `audio_${audio.voiceLabel}_${new Date(audio.timestamp).getTime()}.mp3`; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - - toast({ - title: "Download iniciado", - description: "O arquivo de áudio está sendo baixado.", - }); + const handleDownloadAudio = async (audio: GeneratedAudio) => { + const filename = `audio_${audio.voiceLabel}_${new Date(audio.timestamp).getTime()}.mp3`; + try { + await audioGenerationService.downloadAudioFile(audio.audioUrl, filename); + toast({ + title: "Download iniciado", + description: "O arquivo de áudio está sendo baixado.", + }); + } catch (error: unknown) { + const message = + error && typeof error === "object" && "message" in error ? String((error as { message: string }).message) : "Não foi possível baixar o áudio."; + toast({ + title: "Erro ao baixar", + description: message, + variant: "destructive", + }); + } }; const handleDeleteAudio = (audioId: string) => { @@ -482,10 +487,11 @@ export const AudioView = () => {
diff --git a/src/components/audio/GenerationView.tsx b/src/components/audio/GenerationView.tsx index 8444f7f..793bf48 100644 --- a/src/components/audio/GenerationView.tsx +++ b/src/components/audio/GenerationView.tsx @@ -134,18 +134,23 @@ export const GenerationView = () => { } }; - const handleDownloadAudio = (audio: AudioRecord) => { - const a = document.createElement('a'); - a.href = audio.audio_url; - a.download = `audio_${audio.voice}_${new Date(audio.created_at).getTime()}.mp3`; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - - toast({ - title: "Download iniciado", - description: "O arquivo de áudio está sendo baixado.", - }); + const handleDownloadAudio = async (audio: AudioRecord) => { + const filename = `audio_${audio.voice}_${new Date(audio.created_at).getTime()}.mp3`; + try { + await audioGenerationService.downloadAudioFile(audio.audio_url, filename); + toast({ + title: "Download iniciado", + description: "O arquivo de áudio está sendo baixado.", + }); + } catch (error: unknown) { + const message = + error && typeof error === "object" && "message" in error ? String((error as { message: string }).message) : "Não foi possível baixar o áudio."; + toast({ + title: "Erro ao baixar", + description: message, + variant: "destructive", + }); + } }; const handleDeleteAudio = async (audioId: string) => { @@ -290,10 +295,11 @@ export const GenerationView = () => {
diff --git a/src/components/chat/ChatMessage.tsx b/src/components/chat/ChatMessage.tsx index ce829c4..c7a4007 100644 --- a/src/components/chat/ChatMessage.tsx +++ b/src/components/chat/ChatMessage.tsx @@ -1,4 +1,5 @@ import { Bot, User, Copy, File } from "lucide-react"; +import ReactMarkdown from "react-markdown"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { useState } from "react"; @@ -53,7 +54,7 @@ export const ChatMessage = ({ role, content, model, attachments }: ChatMessagePr
)} -
+
{/* Attachments */} {attachments && attachments.length > 0 && (
@@ -73,15 +74,19 @@ export const ChatMessage = ({ role, content, model, attachments }: ChatMessagePr )}
-

- {content} -

+ {isAssistant ? ( +
+ {content} +
+ ) : ( +

{content}

+ )}
{showActions && ( diff --git a/src/components/parecer-juridico/ParecerJuridicoDetailView.tsx b/src/components/parecer-juridico/ParecerJuridicoDetailView.tsx index 28ca26a..8474070 100644 --- a/src/components/parecer-juridico/ParecerJuridicoDetailView.tsx +++ b/src/components/parecer-juridico/ParecerJuridicoDetailView.tsx @@ -133,8 +133,9 @@ export function ParecerJuridicoDetailView() { new Date(a.created_at.replace(" ", "T")).getTime() - new Date(b.created_at.replace(" ", "T")).getTime() ); + const nonEmptyMessages = sorted.filter((m) => (m.content ?? "").trim().length > 0); setMessages( - sorted.map((m) => ({ + nonEmptyMessages.map((m) => ({ id: m.id, role: m.role, content: m.content, diff --git a/src/components/parecer-juridico/ParecerJuridicoFormView.tsx b/src/components/parecer-juridico/ParecerJuridicoFormView.tsx index c366f11..90a325c 100644 --- a/src/components/parecer-juridico/ParecerJuridicoFormView.tsx +++ b/src/components/parecer-juridico/ParecerJuridicoFormView.tsx @@ -155,18 +155,32 @@ export function ParecerJuridicoFormView() {
- + setTituloParecer(e.target.value)} placeholder="Ex.: Parecer sobre contrato de prestação de serviços" className="w-full" + required + aria-required="true" />
- + setPromptId(v === "none" ? "" : v)} @@ -221,29 +235,45 @@ export function ParecerJuridicoFormView() {
- +