feat: enhance absence management with calendar integration and error handling

- Added functionality to check for date overlaps with existing absence requests in the absence calendar.
- Implemented a modal to display error messages when users attempt to create overlapping absence requests.
- Updated the calendar component to visually indicate blocked days due to existing approved or pending absence requests.
- Improved user feedback by providing alerts for unavailable periods and enhancing the overall user experience in absence management.
This commit is contained in:
2025-11-04 15:09:15 -03:00
parent a93d55f02b
commit c1e0998a5f
4 changed files with 552 additions and 15 deletions

View File

@@ -6,6 +6,7 @@
import WizardSolicitacaoFerias from "$lib/components/ferias/WizardSolicitacaoFerias.svelte";
import WizardSolicitacaoAusencia from "$lib/components/ausencias/WizardSolicitacaoAusencia.svelte";
import AprovarAusencias from "$lib/components/AprovarAusencias.svelte";
import CalendarioAusencias from "$lib/components/ausencias/CalendarioAusencias.svelte";
import { generateAvatarGallery, type Avatar } from "$lib/utils/avatars";
import type { Id } from "@sgse-app/backend/convex/_generated/dataModel";
import { page } from "$app/stores";
@@ -151,6 +152,15 @@
})
);
// Formatar ausências para o calendário
const ausenciasParaCalendario = $derived(
minhasAusencias.map((a) => ({
dataInicio: a.dataInicio,
dataFim: a.dataFim,
status: a.status as "aguardando_aprovacao" | "aprovado" | "reprovado",
}))
);
// Estatísticas das minhas férias
const statsMinhasFerias = $derived({
total: minhasSolicitacoes.length,
@@ -1375,6 +1385,46 @@
</div>
</div>
<!-- Calendário de Ausências -->
<div class="card bg-base-100 shadow-lg">
<div class="card-body">
<h2 class="card-title text-lg mb-4">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 text-orange-500"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
Calendário de Ausências
</h2>
<p class="text-sm text-base-content/70 mb-4">
Visualize todas as suas solicitações de ausência no calendário
</p>
{#if ausenciasParaCalendario.length > 0}
<CalendarioAusencias
ausenciasExistentes={ausenciasParaCalendario}
readonly={true}
modoVisualizacao="month"
/>
{:else}
<div class="alert alert-info">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-info shrink-0 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<span>Você ainda não possui solicitações de ausência. Clique em "Solicitar Ausência" para criar uma nova.</span>
</div>
{/if}
</div>
</div>
<!-- Filtros e Botão Nova Solicitação -->
<div class="card bg-base-100 shadow-lg">
<div class="card-body">
@@ -2128,8 +2178,17 @@
<div class="max-h-[80vh] overflow-y-auto">
<WizardSolicitacaoAusencia
funcionarioId={funcionarioIdDisponivel}
onSucesso={() => {
onSucesso={async () => {
mostrarWizardAusencia = false;
// As queries do Convex são reativas e devem atualizar automaticamente
// Mas garantimos que o componente será re-renderizado
// Forçar recarregamento das queries mudando temporariamente o filtro
const filtroAnterior = filtroStatusAusencias;
if (filtroAnterior !== "todos") {
filtroStatusAusencias = "todos";
await new Promise(resolve => setTimeout(resolve, 200));
}
filtroStatusAusencias = filtroAnterior;
}}
onCancelar={() => (mostrarWizardAusencia = false)}
/>