refactor: enhance chat components with type safety and response functionality

- Updated type definitions in ChatWindow and MessageList components for better type safety.
- Improved MessageInput to handle message responses, including a preview feature for replying to messages.
- Enhanced the chat message handling logic to support message references and improve user interaction.
- Refactored notification utility functions to support push notifications and rate limiting for email sending.
- Updated backend schema to accommodate new features related to message responses and notifications.
This commit is contained in:
2025-11-04 20:36:01 -03:00
parent 15374276d5
commit 12db52a8a7
23 changed files with 3195 additions and 503 deletions

View File

@@ -18,6 +18,7 @@
let uploadingFile = $state(false);
let digitacaoTimeout: ReturnType<typeof setTimeout> | null = null;
let showEmojiPicker = $state(false);
let mensagemRespondendo: { id: Id<"mensagens">; conteudo: string; remetente: string } | null = $state(null);
// Emojis mais usados
const emojis = [
@@ -62,6 +63,7 @@
conversaId,
conteudo: texto,
tipo: "texto",
respostaPara: mensagemRespondendo?.id,
});
try {
@@ -70,11 +72,13 @@
conversaId,
conteudo: texto,
tipo: "texto",
respostaPara: mensagemRespondendo?.id,
});
console.log("✅ [MessageInput] Mensagem enviada com sucesso! ID:", result);
mensagem = "";
mensagemRespondendo = null;
if (textarea) {
textarea.style.height = "auto";
}
@@ -86,6 +90,34 @@
}
}
function cancelarResposta() {
mensagemRespondendo = null;
}
// Escutar evento de resposta
onMount(() => {
const handler = (e: Event) => {
const customEvent = e as CustomEvent<{ mensagemId: Id<"mensagens"> }>;
// Buscar informações da mensagem para exibir preview
client.query(api.chat.obterMensagens, { conversaId, limit: 100 }).then((mensagens) => {
const msg = mensagens.find((m: any) => m._id === customEvent.detail.mensagemId);
if (msg) {
mensagemRespondendo = {
id: msg._id,
conteudo: msg.conteudo.substring(0, 100),
remetente: msg.remetente?.nome || "Usuário",
};
textarea?.focus();
}
});
};
window.addEventListener("responderMensagem", handler);
return () => {
window.removeEventListener("responderMensagem", handler);
};
});
function handleKeyDown(e: KeyboardEvent) {
// Enter sem Shift = enviar
if (e.key === "Enter" && !e.shiftKey) {
@@ -154,6 +186,24 @@
</script>
<div class="p-4">
<!-- Preview da mensagem respondendo -->
{#if mensagemRespondendo}
<div class="mb-2 p-2 bg-base-200 rounded-lg flex items-center justify-between">
<div class="flex-1">
<p class="text-xs font-medium text-base-content/70">Respondendo a {mensagemRespondendo.remetente}</p>
<p class="text-xs text-base-content/50 truncate">{mensagemRespondendo.conteudo}</p>
</div>
<button
type="button"
class="btn btn-xs btn-ghost"
onclick={cancelarResposta}
title="Cancelar resposta"
>
</button>
</div>
{/if}
<div class="flex items-end gap-2">
<!-- Botão de anexar arquivo MODERNO -->
<label