refactor: clean up Svelte components and improve code readability
- Refactored multiple Svelte components to enhance code clarity and maintainability. - Standardized formatting and indentation across various files for consistency. - Improved error handling messages in the AprovarAusencias component for better user feedback. - Updated class names in the UI components to align with the new design system. - Removed unnecessary whitespace and comments to streamline the codebase.
This commit is contained in:
@@ -6,7 +6,17 @@
|
||||
import { ptBR } from "date-fns/locale";
|
||||
import { onMount } from "svelte";
|
||||
import { authStore } from "$lib/stores/auth.svelte";
|
||||
import { Bell, Mail, AtSign, Users, Calendar, Clock, BellOff, Trash2, X } from "lucide-svelte";
|
||||
import {
|
||||
Bell,
|
||||
Mail,
|
||||
AtSign,
|
||||
Users,
|
||||
Calendar,
|
||||
Clock,
|
||||
BellOff,
|
||||
Trash2,
|
||||
X,
|
||||
} from "lucide-svelte";
|
||||
|
||||
// Queries e Client
|
||||
const client = useConvexClient();
|
||||
@@ -18,31 +28,46 @@
|
||||
});
|
||||
|
||||
let modalOpen = $state(false);
|
||||
let notificacoesFerias = $state<Array<{ _id: string; mensagem: string; tipo: string; _creationTime: number }>>([]);
|
||||
let notificacoesAusencias = $state<Array<{ _id: string; mensagem: string; tipo: string; _creationTime: number }>>([]);
|
||||
let notificacoesFerias = $state<
|
||||
Array<{
|
||||
_id: string;
|
||||
mensagem: string;
|
||||
tipo: string;
|
||||
_creationTime: number;
|
||||
}>
|
||||
>([]);
|
||||
let notificacoesAusencias = $state<
|
||||
Array<{
|
||||
_id: string;
|
||||
mensagem: string;
|
||||
tipo: string;
|
||||
_creationTime: number;
|
||||
}>
|
||||
>([]);
|
||||
let limpandoNotificacoes = $state(false);
|
||||
|
||||
// Helpers para obter valores das queries
|
||||
const count = $derived(
|
||||
(typeof countQuery === "number" ? countQuery : countQuery?.data) ?? 0
|
||||
(typeof countQuery === "number" ? countQuery : countQuery?.data) ?? 0,
|
||||
);
|
||||
const todasNotificacoes = $derived(
|
||||
(Array.isArray(todasNotificacoesQuery)
|
||||
? todasNotificacoesQuery
|
||||
: todasNotificacoesQuery?.data) ?? []
|
||||
: todasNotificacoesQuery?.data) ?? [],
|
||||
);
|
||||
|
||||
|
||||
// Separar notificações lidas e não lidas
|
||||
const notificacoesNaoLidas = $derived(
|
||||
todasNotificacoes.filter((n) => !n.lida)
|
||||
);
|
||||
const notificacoesLidas = $derived(
|
||||
todasNotificacoes.filter((n) => n.lida)
|
||||
todasNotificacoes.filter((n) => !n.lida),
|
||||
);
|
||||
const notificacoesLidas = $derived(todasNotificacoes.filter((n) => n.lida));
|
||||
|
||||
// Atualizar contador no store
|
||||
$effect(() => {
|
||||
const totalNotificacoes = count + (notificacoesFerias?.length || 0) + (notificacoesAusencias?.length || 0);
|
||||
const totalNotificacoes =
|
||||
count +
|
||||
(notificacoesFerias?.length || 0) +
|
||||
(notificacoesAusencias?.length || 0);
|
||||
notificacoesCount.set(totalNotificacoes);
|
||||
});
|
||||
|
||||
@@ -56,7 +81,7 @@
|
||||
api.ferias.obterNotificacoesNaoLidas,
|
||||
{
|
||||
usuarioId: usuarioStore.usuario._id,
|
||||
}
|
||||
},
|
||||
);
|
||||
notificacoesFerias = notifsFerias || [];
|
||||
}
|
||||
@@ -76,14 +101,20 @@
|
||||
api.ausencias.obterNotificacoesNaoLidas,
|
||||
{
|
||||
usuarioId: usuarioStore.usuario._id,
|
||||
}
|
||||
},
|
||||
);
|
||||
notificacoesAusencias = notifsAusencias || [];
|
||||
} catch (queryError: unknown) {
|
||||
// Silenciar erro se a função não estiver disponível ainda (Convex não sincronizado)
|
||||
const errorMessage = queryError instanceof Error ? queryError.message : String(queryError);
|
||||
const errorMessage =
|
||||
queryError instanceof Error
|
||||
? queryError.message
|
||||
: String(queryError);
|
||||
if (!errorMessage.includes("Could not find public function")) {
|
||||
console.error("Erro ao buscar notificações de ausências:", queryError);
|
||||
console.error(
|
||||
"Erro ao buscar notificações de ausências:",
|
||||
queryError,
|
||||
);
|
||||
}
|
||||
notificacoesAusencias = [];
|
||||
}
|
||||
@@ -201,7 +232,10 @@
|
||||
|
||||
function handleClickOutside(event: MouseEvent) {
|
||||
const target = event.target as HTMLElement;
|
||||
if (!target.closest(".notification-popup") && !target.closest(".notification-bell")) {
|
||||
if (
|
||||
!target.closest(".notification-popup") &&
|
||||
!target.closest(".notification-bell")
|
||||
) {
|
||||
modalOpen = false;
|
||||
}
|
||||
}
|
||||
@@ -233,7 +267,7 @@
|
||||
>
|
||||
<!-- Efeito de brilho no hover -->
|
||||
<div
|
||||
class="absolute inset-0 bg-gradient-to-br from-white/0 to-white/20 opacity-0 group-hover:opacity-100 transition-opacity duration-300"
|
||||
class="absolute inset-0 bg-linear-to-br from-white/0 to-white/20 opacity-0 group-hover:opacity-100 transition-opacity duration-300"
|
||||
></div>
|
||||
|
||||
<!-- Anel de pulso sutil -->
|
||||
@@ -271,52 +305,59 @@
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<!-- Popup Flutuante de Notificações -->
|
||||
{#if modalOpen}
|
||||
<div class="notification-popup fixed right-4 top-24 z-[100] w-[calc(100vw-2rem)] max-w-2xl max-h-[calc(100vh-7rem)] flex flex-col bg-base-100 rounded-2xl shadow-2xl border border-base-300 overflow-hidden backdrop-blur-sm" style="animation: slideDown 0.2s ease-out;">
|
||||
<!-- Header -->
|
||||
<div class="flex items-center justify-between px-6 py-4 border-b border-base-300 bg-gradient-to-r from-primary/5 to-primary/10">
|
||||
<h3 class="text-2xl font-bold text-primary">Notificações</h3>
|
||||
<div class="flex items-center gap-2">
|
||||
{#if notificacoesNaoLidas.length > 0}
|
||||
<!-- Popup Flutuante de Notificações -->
|
||||
{#if modalOpen}
|
||||
<div
|
||||
class="notification-popup fixed right-4 top-24 z-[100] w-[calc(100vw-2rem)] max-w-2xl max-h-[calc(100vh-7rem)] flex flex-col bg-base-100 rounded-2xl shadow-2xl border border-base-300 overflow-hidden backdrop-blur-sm"
|
||||
style="animation: slideDown 0.2s ease-out;"
|
||||
>
|
||||
<!-- Header -->
|
||||
<div
|
||||
class="flex items-center justify-between px-6 py-4 border-b border-base-300 bg-linear-to-r from-primary/5 to-primary/10"
|
||||
>
|
||||
<h3 class="text-2xl font-bold text-primary">Notificações</h3>
|
||||
<div class="flex items-center gap-2">
|
||||
{#if notificacoesNaoLidas.length > 0}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-ghost"
|
||||
onclick={handleLimparNotificacoesNaoLidas}
|
||||
disabled={limpandoNotificacoes}
|
||||
>
|
||||
<Trash2 class="w-4 h-4" />
|
||||
Limpar não lidas
|
||||
</button>
|
||||
{/if}
|
||||
{#if todasNotificacoes.length > 0}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-error btn-outline"
|
||||
onclick={handleLimparTodasNotificacoes}
|
||||
disabled={limpandoNotificacoes}
|
||||
>
|
||||
<Trash2 class="w-4 h-4" />
|
||||
Limpar todas
|
||||
</button>
|
||||
{/if}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-ghost"
|
||||
onclick={handleLimparNotificacoesNaoLidas}
|
||||
disabled={limpandoNotificacoes}
|
||||
class="btn btn-sm btn-circle btn-ghost"
|
||||
onclick={closeModal}
|
||||
>
|
||||
<Trash2 class="w-4 h-4" />
|
||||
Limpar não lidas
|
||||
<X class="w-5 h-5" />
|
||||
</button>
|
||||
{/if}
|
||||
{#if todasNotificacoes.length > 0}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-error btn-outline"
|
||||
onclick={handleLimparTodasNotificacoes}
|
||||
disabled={limpandoNotificacoes}
|
||||
>
|
||||
<Trash2 class="w-4 h-4" />
|
||||
Limpar todas
|
||||
</button>
|
||||
{/if}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-circle btn-ghost"
|
||||
onclick={closeModal}
|
||||
>
|
||||
<X class="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lista de notificações -->
|
||||
<div class="flex-1 overflow-y-auto px-2 py-4">
|
||||
<!-- Lista de notificações -->
|
||||
<div class="flex-1 overflow-y-auto px-2 py-4">
|
||||
{#if todasNotificacoes.length > 0 || notificacoesFerias.length > 0 || notificacoesAusencias.length > 0}
|
||||
<!-- Notificações não lidas -->
|
||||
{#if notificacoesNaoLidas.length > 0}
|
||||
<div class="mb-4">
|
||||
<h4 class="text-sm font-semibold text-primary mb-2 px-2">Não lidas</h4>
|
||||
<h4 class="text-sm font-semibold text-primary mb-2 px-2">
|
||||
Não lidas
|
||||
</h4>
|
||||
{#each notificacoesNaoLidas as notificacao (notificacao._id)}
|
||||
<button
|
||||
type="button"
|
||||
@@ -329,7 +370,10 @@
|
||||
{#if notificacao.tipo === "nova_mensagem"}
|
||||
<Mail class="w-5 h-5 text-primary" strokeWidth={1.5} />
|
||||
{:else if notificacao.tipo === "mencao"}
|
||||
<AtSign class="w-5 h-5 text-warning" strokeWidth={1.5} />
|
||||
<AtSign
|
||||
class="w-5 h-5 text-warning"
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
{:else}
|
||||
<Users class="w-5 h-5 text-info" strokeWidth={1.5} />
|
||||
{/if}
|
||||
@@ -341,21 +385,27 @@
|
||||
<p class="text-sm font-semibold text-primary">
|
||||
{notificacao.remetente.nome}
|
||||
</p>
|
||||
<p class="text-xs text-base-content/70 mt-1 line-clamp-2">
|
||||
<p
|
||||
class="text-xs text-base-content/70 mt-1 line-clamp-2"
|
||||
>
|
||||
{notificacao.descricao}
|
||||
</p>
|
||||
{:else if notificacao.tipo === "mencao" && notificacao.remetente}
|
||||
<p class="text-sm font-semibold text-warning">
|
||||
{notificacao.remetente.nome} mencionou você
|
||||
</p>
|
||||
<p class="text-xs text-base-content/70 mt-1 line-clamp-2">
|
||||
<p
|
||||
class="text-xs text-base-content/70 mt-1 line-clamp-2"
|
||||
>
|
||||
{notificacao.descricao}
|
||||
</p>
|
||||
{:else}
|
||||
<p class="text-sm font-semibold text-base-content">
|
||||
{notificacao.titulo}
|
||||
</p>
|
||||
<p class="text-xs text-base-content/70 mt-1 line-clamp-2">
|
||||
<p
|
||||
class="text-xs text-base-content/70 mt-1 line-clamp-2"
|
||||
>
|
||||
{notificacao.descricao}
|
||||
</p>
|
||||
{/if}
|
||||
@@ -377,7 +427,9 @@
|
||||
<!-- Notificações lidas -->
|
||||
{#if notificacoesLidas.length > 0}
|
||||
<div class="mb-4">
|
||||
<h4 class="text-sm font-semibold text-base-content/60 mb-2 px-2">Lidas</h4>
|
||||
<h4 class="text-sm font-semibold text-base-content/60 mb-2 px-2">
|
||||
Lidas
|
||||
</h4>
|
||||
{#each notificacoesLidas as notificacao (notificacao._id)}
|
||||
<button
|
||||
type="button"
|
||||
@@ -388,9 +440,15 @@
|
||||
<!-- Ícone -->
|
||||
<div class="flex-shrink-0 mt-1">
|
||||
{#if notificacao.tipo === "nova_mensagem"}
|
||||
<Mail class="w-5 h-5 text-primary/60" strokeWidth={1.5} />
|
||||
<Mail
|
||||
class="w-5 h-5 text-primary/60"
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
{:else if notificacao.tipo === "mencao"}
|
||||
<AtSign class="w-5 h-5 text-warning/60" strokeWidth={1.5} />
|
||||
<AtSign
|
||||
class="w-5 h-5 text-warning/60"
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
{:else}
|
||||
<Users class="w-5 h-5 text-info/60" strokeWidth={1.5} />
|
||||
{/if}
|
||||
@@ -402,21 +460,27 @@
|
||||
<p class="text-sm font-medium text-primary/70">
|
||||
{notificacao.remetente.nome}
|
||||
</p>
|
||||
<p class="text-xs text-base-content/60 mt-1 line-clamp-2">
|
||||
<p
|
||||
class="text-xs text-base-content/60 mt-1 line-clamp-2"
|
||||
>
|
||||
{notificacao.descricao}
|
||||
</p>
|
||||
{:else if notificacao.tipo === "mencao" && notificacao.remetente}
|
||||
<p class="text-sm font-medium text-warning/70">
|
||||
{notificacao.remetente.nome} mencionou você
|
||||
</p>
|
||||
<p class="text-xs text-base-content/60 mt-1 line-clamp-2">
|
||||
<p
|
||||
class="text-xs text-base-content/60 mt-1 line-clamp-2"
|
||||
>
|
||||
{notificacao.descricao}
|
||||
</p>
|
||||
{:else}
|
||||
<p class="text-sm font-medium text-base-content/70">
|
||||
{notificacao.titulo}
|
||||
</p>
|
||||
<p class="text-xs text-base-content/60 mt-1 line-clamp-2">
|
||||
<p
|
||||
class="text-xs text-base-content/60 mt-1 line-clamp-2"
|
||||
>
|
||||
{notificacao.descricao}
|
||||
</p>
|
||||
{/if}
|
||||
@@ -433,7 +497,9 @@
|
||||
<!-- Notificações de Férias -->
|
||||
{#if notificacoesFerias.length > 0}
|
||||
<div class="mb-4">
|
||||
<h4 class="text-sm font-semibold text-purple-600 mb-2 px-2">Férias</h4>
|
||||
<h4 class="text-sm font-semibold text-purple-600 mb-2 px-2">
|
||||
Férias
|
||||
</h4>
|
||||
{#each notificacoesFerias as notificacao (notificacao._id)}
|
||||
<button
|
||||
type="button"
|
||||
@@ -443,7 +509,10 @@
|
||||
<div class="flex items-start gap-3">
|
||||
<!-- Ícone -->
|
||||
<div class="flex-shrink-0 mt-1">
|
||||
<Calendar class="w-5 h-5 text-purple-600" strokeWidth={2} />
|
||||
<Calendar
|
||||
class="w-5 h-5 text-purple-600"
|
||||
strokeWidth={2}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Conteúdo -->
|
||||
@@ -469,12 +538,15 @@
|
||||
<!-- Notificações de Ausências -->
|
||||
{#if notificacoesAusencias.length > 0}
|
||||
<div class="mb-4">
|
||||
<h4 class="text-sm font-semibold text-orange-600 mb-2 px-2">Ausências</h4>
|
||||
<h4 class="text-sm font-semibold text-orange-600 mb-2 px-2">
|
||||
Ausências
|
||||
</h4>
|
||||
{#each notificacoesAusencias as notificacao (notificacao._id)}
|
||||
<button
|
||||
type="button"
|
||||
class="w-full text-left px-4 py-3 hover:bg-base-200 rounded-lg transition-colors mb-2 border-l-4 border-orange-600"
|
||||
onclick={() => handleClickNotificacaoAusencias(notificacao._id)}
|
||||
onclick={() =>
|
||||
handleClickNotificacaoAusencias(notificacao._id)}
|
||||
>
|
||||
<div class="flex items-start gap-3">
|
||||
<!-- Ícone -->
|
||||
@@ -504,30 +576,37 @@
|
||||
{:else}
|
||||
<!-- Sem notificações -->
|
||||
<div class="px-4 py-12 text-center text-base-content/50">
|
||||
<BellOff class="w-16 h-16 mx-auto mb-4 opacity-50" strokeWidth={1.5} />
|
||||
<BellOff
|
||||
class="w-16 h-16 mx-auto mb-4 opacity-50"
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
<p class="text-base font-medium">Nenhuma notificação</p>
|
||||
<p class="text-sm mt-1">Você está em dia!</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Footer com estatísticas -->
|
||||
{#if todasNotificacoes.length > 0 || notificacoesFerias.length > 0 || notificacoesAusencias.length > 0}
|
||||
<div class="px-6 py-4 border-t border-base-300 bg-base-200/50">
|
||||
<div class="flex items-center justify-between text-xs text-base-content/60">
|
||||
<span>
|
||||
Total: {todasNotificacoes.length + notificacoesFerias.length + notificacoesAusencias.length} notificações
|
||||
</span>
|
||||
{#if notificacoesNaoLidas.length > 0}
|
||||
<span class="text-primary font-semibold">
|
||||
{notificacoesNaoLidas.length} não lidas
|
||||
<!-- Footer com estatísticas -->
|
||||
{#if todasNotificacoes.length > 0 || notificacoesFerias.length > 0 || notificacoesAusencias.length > 0}
|
||||
<div class="px-6 py-4 border-t border-base-300 bg-base-200/50">
|
||||
<div
|
||||
class="flex items-center justify-between text-xs text-base-content/60"
|
||||
>
|
||||
<span>
|
||||
Total: {todasNotificacoes.length +
|
||||
notificacoesFerias.length +
|
||||
notificacoesAusencias.length} notificações
|
||||
</span>
|
||||
{/if}
|
||||
{#if notificacoesNaoLidas.length > 0}
|
||||
<span class="text-primary font-semibold">
|
||||
{notificacoesNaoLidas.length} não lidas
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -582,4 +661,3 @@
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user