From 51f8828f700dd3b800f23305a406cb4a9827713d Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 19:04:15 +0000 Subject: [PATCH] feat: Alinhar mensagens e permitir anexos --- src/components/chat/ChatInput.tsx | 88 ++++++++++++++++++++++++----- src/components/chat/ChatMessage.tsx | 85 +++++++++++++++++++--------- src/components/chat/ChatView.tsx | 13 ++++- 3 files changed, 144 insertions(+), 42 deletions(-) diff --git a/src/components/chat/ChatInput.tsx b/src/components/chat/ChatInput.tsx index db7c37b..b0783f6 100644 --- a/src/components/chat/ChatInput.tsx +++ b/src/components/chat/ChatInput.tsx @@ -1,19 +1,24 @@ -import { Send, Paperclip, Mic } from "lucide-react"; +import { Send, Paperclip, X } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; -import { useState } from "react"; +import { useState, useRef } from "react"; +import { useToast } from "@/hooks/use-toast"; interface ChatInputProps { - onSendMessage: (message: string) => void; + onSendMessage: (message: string, files?: File[]) => void; } export const ChatInput = ({ onSendMessage }: ChatInputProps) => { const [message, setMessage] = useState(""); + const [attachedFiles, setAttachedFiles] = useState([]); + const fileInputRef = useRef(null); + const { toast } = useToast(); const handleSend = () => { - if (message.trim()) { - onSendMessage(message); + if (message.trim() || attachedFiles.length > 0) { + onSendMessage(message, attachedFiles); setMessage(""); + setAttachedFiles([]); } }; @@ -24,9 +29,61 @@ export const ChatInput = ({ onSendMessage }: ChatInputProps) => { } }; + const handleFileSelect = (e: React.ChangeEvent) => { + const files = Array.from(e.target.files || []); + + // Validate file size (max 10MB per file) + const validFiles = files.filter((file) => { + if (file.size > 10 * 1024 * 1024) { + toast({ + title: "Arquivo muito grande", + description: `${file.name} excede o limite de 10MB`, + variant: "destructive", + }); + return false; + } + return true; + }); + + setAttachedFiles([...attachedFiles, ...validFiles]); + if (fileInputRef.current) { + fileInputRef.current.value = ""; + } + }; + + const removeFile = (index: number) => { + setAttachedFiles(attachedFiles.filter((_, i) => i !== index)); + }; + return (
+ {/* Attached Files Preview */} + {attachedFiles.length > 0 && ( +
+ {attachedFiles.map((file, index) => ( +
+ + {file.name} + + ({(file.size / 1024).toFixed(1)} KB) + + +
+ ))} +
+ )} +