Fix chat widget UI and allow attachment-only messages
- Allow sending messages with only attachments (no text required) - Change "Chat Ativo" header to just "Chat" - Replace Headphones icon with MessageCircle for own messages - Replace PhoneOff icon with XCircle for end chat button 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
60e98dd47c
commit
f45ee91804
2 changed files with 18 additions and 15 deletions
|
|
@ -3178,14 +3178,17 @@ export const postChatMessage = mutation({
|
|||
}
|
||||
|
||||
const trimmedBody = body.replace(/\r\n/g, "\n").trim()
|
||||
if (trimmedBody.length === 0) {
|
||||
throw new ConvexError("Digite uma mensagem para enviar no chat")
|
||||
const files = attachments ?? []
|
||||
|
||||
// Validar que há pelo menos texto ou anexo
|
||||
if (trimmedBody.length === 0 && files.length === 0) {
|
||||
throw new ConvexError("Digite uma mensagem ou anexe um arquivo")
|
||||
}
|
||||
if (trimmedBody.length > 4000) {
|
||||
throw new ConvexError("Mensagem muito longa (máx. 4000 caracteres)")
|
||||
}
|
||||
|
||||
const files = attachments ?? []
|
||||
// Validar anexos
|
||||
if (files.length > 5) {
|
||||
throw new ConvexError("Envie até 5 arquivos por mensagem")
|
||||
}
|
||||
|
|
@ -3196,13 +3199,14 @@ export const postChatMessage = mutation({
|
|||
}
|
||||
}
|
||||
|
||||
const normalizedBody = await normalizeTicketMentions(ctx, trimmedBody, { user: participant.user, role: participant.role ?? "" }, ticketDoc.tenantId)
|
||||
const plainLength = plainTextLength(normalizedBody)
|
||||
if (plainLength === 0) {
|
||||
throw new ConvexError("A mensagem está vazia após a formatação")
|
||||
}
|
||||
if (plainLength > 4000) {
|
||||
throw new ConvexError("Mensagem muito longa (máx. 4000 caracteres)")
|
||||
// Normalizar corpo apenas se houver texto
|
||||
let normalizedBody = ""
|
||||
if (trimmedBody.length > 0) {
|
||||
normalizedBody = await normalizeTicketMentions(ctx, trimmedBody, { user: participant.user, role: participant.role ?? "" }, ticketDoc.tenantId)
|
||||
const plainLength = plainTextLength(normalizedBody)
|
||||
if (plainLength > 4000) {
|
||||
throw new ConvexError("Mensagem muito longa (máx. 4000 caracteres)")
|
||||
}
|
||||
}
|
||||
|
||||
const authorSnapshot: CommentAuthorSnapshot = {
|
||||
|
|
|
|||
|
|
@ -22,10 +22,9 @@ import {
|
|||
X,
|
||||
Minimize2,
|
||||
User,
|
||||
Headphones,
|
||||
ChevronDown,
|
||||
WifiOff,
|
||||
PhoneOff,
|
||||
XCircle,
|
||||
Paperclip,
|
||||
FileText,
|
||||
Image as ImageIcon,
|
||||
|
|
@ -428,7 +427,7 @@ export function ChatWidget() {
|
|||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<p className="text-sm font-semibold text-slate-900">Chat Ativo</p>
|
||||
<p className="text-sm font-semibold text-slate-900">Chat</p>
|
||||
{/* Indicador online/offline */}
|
||||
{liveChat?.hasMachine && (
|
||||
machineOnline ? (
|
||||
|
|
@ -464,7 +463,7 @@ export function ChatWidget() {
|
|||
{isEndingChat ? (
|
||||
<Spinner className="size-3.5" />
|
||||
) : (
|
||||
<PhoneOff className="size-3.5" />
|
||||
<XCircle className="size-3.5" />
|
||||
)}
|
||||
<span className="hidden sm:inline">Encerrar</span>
|
||||
</Button>
|
||||
|
|
@ -548,7 +547,7 @@ export function ChatWidget() {
|
|||
isOwn ? "bg-black text-white" : "bg-slate-200 text-slate-600"
|
||||
)}
|
||||
>
|
||||
{isOwn ? <Headphones className="size-3.5" /> : <User className="size-3.5" />}
|
||||
{isOwn ? <MessageCircle className="size-3.5" /> : <User className="size-3.5" />}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue