fix: update dependencies and improve chat component structure

- Updated `lucide-svelte` dependency to version 0.552.0 across multiple files for consistency.
- Refactored chat components to enhance structure and readability, including adjustments to the Sidebar, ChatList, and MessageInput components.
- Improved notification handling in chat components to ensure better user experience and responsiveness.
- Added type safety enhancements in various components to ensure better integration with backend data models.
This commit is contained in:
2025-11-05 11:52:01 -03:00
parent 1774b135b3
commit 6cb7414dcc
15 changed files with 377 additions and 408 deletions

View File

@@ -9,6 +9,20 @@
conversaId: Id<"conversas">;
}
type ParticipanteInfo = {
_id: Id<"usuarios">;
nome: string;
email?: string;
fotoPerfilUrl?: string;
avatar?: string;
};
type ConversaComParticipantes = {
_id: Id<"conversas">;
tipo: "individual" | "grupo" | "sala_reuniao";
participantesInfo?: ParticipanteInfo[];
};
let { conversaId }: Props = $props();
const client = useConvexClient();
@@ -43,25 +57,25 @@
}
// Obter conversa atual
const conversa = $derived(() => {
const conversa = $derived((): ConversaComParticipantes | null => {
if (!conversas?.data) return null;
return conversas.data.find((c: any) => c._id === conversaId);
return (conversas.data as ConversaComParticipantes[]).find((c) => c._id === conversaId) || null;
});
// Obter participantes para menções (apenas grupos e salas)
const participantesParaMencoes = $derived(() => {
const participantesParaMencoes = $derived((): ParticipanteInfo[] => {
const c = conversa();
if (!c || (c.tipo !== "grupo" && c.tipo !== "sala_reuniao")) return [];
return c.participantesInfo || [];
});
// Filtrar participantes para dropdown de menções
const participantesFiltrados = $derived(() => {
const participantesFiltrados = $derived((): ParticipanteInfo[] => {
if (!mentionQuery.trim()) return participantesParaMencoes().slice(0, 5);
const query = mentionQuery.toLowerCase();
return participantesParaMencoes().filter((p: any) =>
return participantesParaMencoes().filter((p) =>
p.nome?.toLowerCase().includes(query) ||
p.email?.toLowerCase().includes(query)
(p.email && p.email.toLowerCase().includes(query))
).slice(0, 5);
});
@@ -102,7 +116,7 @@
}, 1000);
}
function inserirMencao(participante: any) {
function inserirMencao(participante: ParticipanteInfo) {
const nome = participante.nome.split(' ')[0]; // Usar primeiro nome
const antes = mensagem.substring(0, mentionStartPos);
const depois = mensagem.substring(textarea.selectionStart || mensagem.length);
@@ -128,7 +142,7 @@
let match;
while ((match = mentionRegex.exec(texto)) !== null) {
const nomeMencionado = match[1];
const participante = participantesParaMencoes().find((p: any) =>
const participante = participantesParaMencoes().find((p) =>
p.nome.split(' ')[0].toLowerCase() === nomeMencionado.toLowerCase()
);
if (participante) {
@@ -175,13 +189,19 @@
mensagemRespondendo = null;
}
type MensagemComRemetente = {
_id: Id<"mensagens">;
conteudo: string;
remetente?: { nome: string } | 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);
const msg = (mensagens as MensagemComRemetente[]).find((m) => m._id === customEvent.detail.mensagemId);
if (msg) {
mensagemRespondendo = {
id: msg._id,
@@ -254,11 +274,11 @@
const { storageId } = await result.json();
// 3. Enviar mensagem com o arquivo
const tipo = file.type.startsWith("image/") ? "imagem" : "arquivo";
const tipo: "imagem" | "arquivo" = file.type.startsWith("image/") ? "imagem" : "arquivo";
await client.mutation(api.chat.enviarMensagem, {
conversaId,
conteudo: tipo === "imagem" ? "" : file.name,
tipo: tipo as any,
tipo,
arquivoId: storageId,
arquivoNome: file.name,
arquivoTamanho: file.size,