refactor: integrate current user data across components
- Replaced instances of `authStore` with `currentUser` to streamline user authentication handling. - Updated permission checks and user-related data retrieval to utilize the new `useQuery` for better performance and clarity. - Cleaned up component structures and improved formatting for consistency and readability. - Enhanced error handling and user feedback mechanisms in various components to improve user experience.
This commit is contained in:
@@ -4,7 +4,15 @@
|
||||
import type { Id } from "@sgse-app/backend/convex/_generated/dataModel";
|
||||
import UserAvatar from "./UserAvatar.svelte";
|
||||
import UserStatusBadge from "./UserStatusBadge.svelte";
|
||||
import { X, Users, UserPlus, ArrowUp, ArrowDown, Trash2, Search } from "lucide-svelte";
|
||||
import {
|
||||
X,
|
||||
Users,
|
||||
UserPlus,
|
||||
ArrowUp,
|
||||
ArrowDown,
|
||||
Trash2,
|
||||
Search,
|
||||
} from "lucide-svelte";
|
||||
|
||||
interface Props {
|
||||
conversaId: Id<"conversas">;
|
||||
@@ -37,17 +45,18 @@
|
||||
const conv = conversa();
|
||||
const usuarios = todosUsuarios();
|
||||
if (!conv || !usuarios || usuarios.length === 0) return [];
|
||||
|
||||
|
||||
const participantesInfo = conv.participantesInfo || [];
|
||||
if (!Array.isArray(participantesInfo) || participantesInfo.length === 0) return [];
|
||||
|
||||
if (!Array.isArray(participantesInfo) || participantesInfo.length === 0)
|
||||
return [];
|
||||
|
||||
return participantesInfo
|
||||
.map((p: any) => {
|
||||
try {
|
||||
// p pode ser um objeto com _id ou apenas um ID
|
||||
const participanteId = p?._id || p;
|
||||
if (!participanteId) return null;
|
||||
|
||||
|
||||
const usuario = usuarios.find((u: any) => {
|
||||
try {
|
||||
return String(u?._id) === String(participanteId);
|
||||
@@ -56,13 +65,15 @@
|
||||
}
|
||||
});
|
||||
if (!usuario) return null;
|
||||
|
||||
|
||||
// Combinar dados do usuário com dados do participante (se p for objeto)
|
||||
return {
|
||||
...usuario,
|
||||
...(typeof p === 'object' && p !== null && p !== undefined ? p : {}),
|
||||
...(typeof p === "object" && p !== null && p !== undefined
|
||||
? p
|
||||
: {}),
|
||||
// Garantir que _id existe e priorizar o do usuario
|
||||
_id: usuario._id
|
||||
_id: usuario._id,
|
||||
};
|
||||
} catch (err) {
|
||||
console.error("Erro ao processar participante:", err, p);
|
||||
@@ -84,17 +95,21 @@
|
||||
const usuarios = todosUsuarios();
|
||||
if (!usuarios || usuarios.length === 0) return [];
|
||||
const participantesIds = conversa()?.participantes || [];
|
||||
return usuarios.filter((u: any) => !participantesIds.some((pid: any) => String(pid) === String(u._id)));
|
||||
return usuarios.filter(
|
||||
(u: any) =>
|
||||
!participantesIds.some((pid: any) => String(pid) === String(u._id)),
|
||||
);
|
||||
});
|
||||
|
||||
const usuariosFiltrados = $derived(() => {
|
||||
const disponiveis = usuariosDisponiveis();
|
||||
if (!searchQuery.trim()) return disponiveis;
|
||||
const query = searchQuery.toLowerCase();
|
||||
return disponiveis.filter((u: any) =>
|
||||
(u.nome || "").toLowerCase().includes(query) ||
|
||||
(u.email || "").toLowerCase().includes(query) ||
|
||||
(u.matricula || "").toLowerCase().includes(query)
|
||||
return disponiveis.filter(
|
||||
(u: any) =>
|
||||
(u.nome || "").toLowerCase().includes(query) ||
|
||||
(u.email || "").toLowerCase().includes(query) ||
|
||||
(u.matricula || "").toLowerCase().includes(query),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -114,10 +129,13 @@
|
||||
try {
|
||||
loading = `remover-${participanteId}`;
|
||||
error = null;
|
||||
const resultado = await client.mutation(api.chat.removerParticipanteSala, {
|
||||
conversaId,
|
||||
participanteId: participanteId as any,
|
||||
});
|
||||
const resultado = await client.mutation(
|
||||
api.chat.removerParticipanteSala,
|
||||
{
|
||||
conversaId,
|
||||
participanteId: participanteId as any,
|
||||
},
|
||||
);
|
||||
|
||||
if (!resultado.sucesso) {
|
||||
error = resultado.erro || "Erro ao remover participante";
|
||||
@@ -175,10 +193,13 @@
|
||||
try {
|
||||
loading = `adicionar-${usuarioId}`;
|
||||
error = null;
|
||||
const resultado = await client.mutation(api.chat.adicionarParticipanteSala, {
|
||||
conversaId,
|
||||
participanteId: usuarioId as any,
|
||||
});
|
||||
const resultado = await client.mutation(
|
||||
api.chat.adicionarParticipanteSala,
|
||||
{
|
||||
conversaId,
|
||||
participanteId: usuarioId as any,
|
||||
},
|
||||
);
|
||||
|
||||
if (!resultado.sucesso) {
|
||||
error = resultado.erro || "Erro ao adicionar participante";
|
||||
@@ -193,16 +214,26 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<dialog class="modal modal-open" onclick={(e) => e.target === e.currentTarget && onClose()}>
|
||||
<div class="modal-box max-w-2xl max-h-[80vh] flex flex-col p-0" onclick={(e) => e.stopPropagation()}>
|
||||
<dialog
|
||||
class="modal modal-open"
|
||||
onclick={(e) => e.target === e.currentTarget && onClose()}
|
||||
>
|
||||
<div
|
||||
class="modal-box max-w-2xl max-h-[80vh] flex flex-col p-0"
|
||||
onclick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<!-- Header -->
|
||||
<div class="flex items-center justify-between px-6 py-4 border-b border-base-300">
|
||||
<div
|
||||
class="flex items-center justify-between px-6 py-4 border-b border-base-300"
|
||||
>
|
||||
<div>
|
||||
<h2 class="text-xl font-semibold flex items-center gap-2">
|
||||
<Users class="w-5 h-5 text-primary" />
|
||||
Gerenciar Sala de Reunião
|
||||
</h2>
|
||||
<p class="text-sm text-base-content/60">{conversa()?.nome || "Sem nome"}</p>
|
||||
<p class="text-sm text-base-content/60">
|
||||
{conversa()?.nome || "Sem nome"}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@@ -240,7 +271,11 @@
|
||||
{#if error}
|
||||
<div class="mx-6 mt-2 alert alert-error">
|
||||
<span>{error}</span>
|
||||
<button type="button" class="btn btn-sm btn-ghost" onclick={() => (error = null)}>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-ghost"
|
||||
onclick={() => (error = null)}
|
||||
>
|
||||
<X class="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -252,13 +287,17 @@
|
||||
<!-- Loading conversas -->
|
||||
<div class="flex items-center justify-center py-8">
|
||||
<span class="loading loading-spinner loading-lg"></span>
|
||||
<span class="ml-2 text-sm text-base-content/60">Carregando conversa...</span>
|
||||
<span class="ml-2 text-sm text-base-content/60"
|
||||
>Carregando conversa...</span
|
||||
>
|
||||
</div>
|
||||
{:else if !todosUsuariosQuery?.data}
|
||||
<!-- Loading usuários -->
|
||||
<div class="flex items-center justify-center py-8">
|
||||
<span class="loading loading-spinner loading-lg"></span>
|
||||
<span class="ml-2 text-sm text-base-content/60">Carregando usuários...</span>
|
||||
<span class="ml-2 text-sm text-base-content/60"
|
||||
>Carregando usuários...</span
|
||||
>
|
||||
</div>
|
||||
{:else if activeTab === "participantes"}
|
||||
<!-- Lista de Participantes -->
|
||||
@@ -273,27 +312,34 @@
|
||||
class="flex items-center gap-3 p-3 rounded-lg border border-base-300 hover:bg-base-200 transition-colors"
|
||||
>
|
||||
<!-- Avatar -->
|
||||
<div class="relative flex-shrink-0">
|
||||
<div class="relative shrink-0">
|
||||
<UserAvatar
|
||||
avatar={participante.avatar}
|
||||
fotoPerfilUrl={participante.fotoPerfilUrl || participante.fotoPerfil}
|
||||
fotoPerfilUrl={participante.fotoPerfilUrl ||
|
||||
participante.fotoPerfil}
|
||||
nome={participante.nome || "Usuário"}
|
||||
size="sm"
|
||||
/>
|
||||
<div class="absolute bottom-0 right-0">
|
||||
<UserStatusBadge status={participante.statusPresenca || "offline"} size="sm" />
|
||||
<UserStatusBadge
|
||||
status={participante.statusPresenca || "offline"}
|
||||
size="sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info -->
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2">
|
||||
<p class="font-medium text-base-content truncate">{participante.nome || "Usuário"}</p>
|
||||
<p class="font-medium text-base-content truncate">
|
||||
{participante.nome || "Usuário"}
|
||||
</p>
|
||||
{#if ehAdmin}
|
||||
<span class="badge badge-primary badge-sm">Admin</span>
|
||||
{/if}
|
||||
{#if ehCriador}
|
||||
<span class="badge badge-secondary badge-sm">Criador</span>
|
||||
<span class="badge badge-secondary badge-sm">Criador</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
<p class="text-sm text-base-content/60 truncate">
|
||||
@@ -313,7 +359,8 @@
|
||||
title="Rebaixar administrador"
|
||||
>
|
||||
{#if isLoading && loading?.includes("rebaixar")}
|
||||
<span class="loading loading-spinner loading-xs"></span>
|
||||
<span class="loading loading-spinner loading-xs"
|
||||
></span>
|
||||
{:else}
|
||||
<ArrowDown class="w-4 h-4" />
|
||||
{/if}
|
||||
@@ -327,7 +374,8 @@
|
||||
title="Promover a administrador"
|
||||
>
|
||||
{#if isLoading && loading?.includes("promover")}
|
||||
<span class="loading loading-spinner loading-xs"></span>
|
||||
<span class="loading loading-spinner loading-xs"
|
||||
></span>
|
||||
{:else}
|
||||
<ArrowUp class="w-4 h-4" />
|
||||
{/if}
|
||||
@@ -365,7 +413,9 @@
|
||||
class="input input-bordered w-full pl-10"
|
||||
bind:value={searchQuery}
|
||||
/>
|
||||
<Search class="w-5 h-5 absolute left-3 top-1/2 -translate-y-1/2 text-base-content/40" />
|
||||
<Search
|
||||
class="w-5 h-5 absolute left-3 top-1/2 -translate-y-1/2 text-base-content/40"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
@@ -380,7 +430,7 @@
|
||||
disabled={isLoading}
|
||||
>
|
||||
<!-- Avatar -->
|
||||
<div class="relative flex-shrink-0">
|
||||
<div class="relative shrink-0">
|
||||
<UserAvatar
|
||||
avatar={usuario.avatar}
|
||||
fotoPerfilUrl={usuario.fotoPerfilUrl || usuario.fotoPerfil}
|
||||
@@ -388,13 +438,18 @@
|
||||
size="sm"
|
||||
/>
|
||||
<div class="absolute bottom-0 right-0">
|
||||
<UserStatusBadge status={usuario.statusPresenca || "offline"} size="sm" />
|
||||
<UserStatusBadge
|
||||
status={usuario.statusPresenca || "offline"}
|
||||
size="sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info -->
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-medium text-base-content truncate">{usuario.nome || "Usuário"}</p>
|
||||
<p class="font-medium text-base-content truncate">
|
||||
{usuario.nome || "Usuário"}
|
||||
</p>
|
||||
<p class="text-sm text-base-content/60 truncate">
|
||||
{usuario.setor || usuario.email || ""}
|
||||
</p>
|
||||
@@ -410,7 +465,9 @@
|
||||
{/each}
|
||||
{:else}
|
||||
<div class="text-center py-8 text-base-content/50">
|
||||
{searchQuery.trim() ? "Nenhum usuário encontrado" : "Todos os usuários já são participantes"}
|
||||
{searchQuery.trim()
|
||||
? "Nenhum usuário encontrado"
|
||||
: "Todos os usuários já são participantes"}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -428,4 +485,3 @@
|
||||
<button type="button" onclick={onClose}>fechar</button>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user