refactor: improve Svelte components and enhance user experience

- Updated various Svelte components to improve code readability and maintainability.
- Standardized button classes across components for a consistent user interface.
- Enhanced error handling and user feedback in modals and forms.
- Cleaned up unnecessary imports and optimized component structure for better performance.
This commit is contained in:
2025-11-12 16:36:29 -03:00
parent 94f4b23a39
commit 11eef4aa2a
39 changed files with 15729 additions and 15486 deletions

View File

@@ -1,424 +1,406 @@
<script lang="ts">
import { goto } from "$app/navigation";
import { useQuery, useConvexClient } from "convex-svelte";
import { api } from "@sgse-app/backend/convex/_generated/api";
import AprovarAusencias from "$lib/components/AprovarAusencias.svelte";
import type { Id } from "@sgse-app/backend/convex/_generated/dataModel";
import { goto } from '$app/navigation';
import { useQuery, useConvexClient } from 'convex-svelte';
import { api } from '@sgse-app/backend/convex/_generated/api';
import AprovarAusencias from '$lib/components/AprovarAusencias.svelte';
import type { Id } from '@sgse-app/backend/convex/_generated/dataModel';
const client = useConvexClient();
const currentUser = useQuery(api.auth.getCurrentUser, {});
const client = useConvexClient();
const currentUser = useQuery(api.auth.getCurrentUser, {});
// Buscar TODAS as solicitações de ausências
const todasAusenciasQuery = useQuery(api.ausencias.listarTodas, {});
// Buscar TODAS as solicitações de ausências
const todasAusenciasQuery = useQuery(api.ausencias.listarTodas, {});
let filtroStatus = $state<string>("todos");
let solicitacaoSelecionada = $state<Id<"solicitacoesAusencias"> | null>(null);
let filtroStatus = $state<string>('todos');
let solicitacaoSelecionada = $state<Id<'solicitacoesAusencias'> | null>(null);
const ausencias = $derived(todasAusenciasQuery?.data || []);
const ausencias = $derived(todasAusenciasQuery?.data || []);
// Filtrar solicitações
const ausenciasFiltradas = $derived(
ausencias.filter((a) => {
// Filtro de status
if (filtroStatus !== "todos" && a.status !== filtroStatus) return false;
return true;
}),
);
// Filtrar solicitações
const ausenciasFiltradas = $derived(
ausencias.filter((a) => {
// Filtro de status
if (filtroStatus !== 'todos' && a.status !== filtroStatus) return false;
return true;
})
);
// Estatísticas gerais
const stats = $derived({
total: ausencias.length,
aguardando: ausencias.filter((a) => a.status === "aguardando_aprovacao")
.length,
aprovadas: ausencias.filter((a) => a.status === "aprovado").length,
reprovadas: ausencias.filter((a) => a.status === "reprovado").length,
});
// Estatísticas gerais
const stats = $derived({
total: ausencias.length,
aguardando: ausencias.filter((a) => a.status === 'aguardando_aprovacao').length,
aprovadas: ausencias.filter((a) => a.status === 'aprovado').length,
reprovadas: ausencias.filter((a) => a.status === 'reprovado').length
});
function getStatusBadge(status: string) {
const badges: Record<string, string> = {
aguardando_aprovacao: "badge-warning",
aprovado: "badge-success",
reprovado: "badge-error",
};
return badges[status] || "badge-neutral";
}
function getStatusBadge(status: string) {
const badges: Record<string, string> = {
aguardando_aprovacao: 'badge-warning',
aprovado: 'badge-success',
reprovado: 'badge-error'
};
return badges[status] || 'badge-neutral';
}
function getStatusTexto(status: string) {
const textos: Record<string, string> = {
aguardando_aprovacao: "Aguardando",
aprovado: "Aprovado",
reprovado: "Reprovado",
};
return textos[status] || status;
}
function getStatusTexto(status: string) {
const textos: Record<string, string> = {
aguardando_aprovacao: 'Aguardando',
aprovado: 'Aprovado',
reprovado: 'Reprovado'
};
return textos[status] || status;
}
function calcularDias(dataInicio: string, dataFim: string): number {
const inicio = new Date(dataInicio);
const fim = new Date(dataFim);
const diff = fim.getTime() - inicio.getTime();
return Math.ceil(diff / (1000 * 60 * 60 * 24)) + 1;
}
function calcularDias(dataInicio: string, dataFim: string): number {
const inicio = new Date(dataInicio);
const fim = new Date(dataFim);
const diff = fim.getTime() - inicio.getTime();
return Math.ceil(diff / (1000 * 60 * 60 * 24)) + 1;
}
async function selecionarSolicitacao(
solicitacaoId: Id<"solicitacoesAusencias">,
) {
solicitacaoSelecionada = solicitacaoId;
}
async function selecionarSolicitacao(solicitacaoId: Id<'solicitacoesAusencias'>) {
solicitacaoSelecionada = solicitacaoId;
}
async function recarregar() {
solicitacaoSelecionada = null;
}
async function recarregar() {
solicitacaoSelecionada = null;
}
</script>
<main class="container mx-auto px-4 py-6 max-w-7xl">
<!-- Breadcrumb -->
<div class="text-sm breadcrumbs mb-4">
<ul>
<li>
<a href="/secretaria-executiva" class="text-primary hover:underline"
>Secretaria Executiva</a
>
</li>
<li>Gestão de Ausências</li>
</ul>
</div>
<main class="container mx-auto max-w-7xl px-4 py-6">
<!-- Breadcrumb -->
<div class="breadcrumbs mb-4 text-sm">
<ul>
<li>
<a href="/secretaria-executiva" class="text-primary hover:underline">Secretaria Executiva</a
>
</li>
<li>Gestão de Ausências</li>
</ul>
</div>
<!-- Header -->
<div class="mb-6">
<div class="flex items-center justify-between">
<div class="flex items-center gap-4">
<div class="p-3 bg-orange-500/20 rounded-xl">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8 text-orange-600"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div>
<h1 class="text-3xl font-bold text-primary">Gestão de Ausências</h1>
<p class="text-base-content/70">
Visão geral de todas as solicitações de ausências
</p>
</div>
</div>
<button
class="btn btn-ghost gap-2"
onclick={() => goto("/secretaria-executiva")}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 19l-7-7m0 0l7-7m-7 7h18"
/>
</svg>
Voltar
</button>
</div>
</div>
<!-- Header -->
<div class="mb-6">
<div class="flex items-center justify-between">
<div class="flex items-center gap-4">
<div class="rounded-xl bg-orange-500/20 p-3">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8 text-orange-600"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div>
<h1 class="text-primary text-3xl font-bold">Gestão de Ausências</h1>
<p class="text-base-content/70">Visão geral de todas as solicitações de ausências</p>
</div>
</div>
<button class="btn gap-2" onclick={() => goto('/secretaria-executiva')}>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 19l-7-7m0 0l7-7m-7 7h18"
/>
</svg>
Voltar
</button>
</div>
</div>
<!-- Estatísticas -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
<div class="stat bg-base-100 shadow-lg rounded-box border border-base-300">
<div class="stat-figure text-orange-500">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
/>
</svg>
</div>
<div class="stat-title">Total</div>
<div class="stat-value text-orange-500">{stats.total}</div>
<div class="stat-desc">Solicitações</div>
</div>
<!-- Estatísticas -->
<div class="mb-6 grid grid-cols-1 gap-4 md:grid-cols-4">
<div class="stat bg-base-100 rounded-box border-base-300 border shadow-lg">
<div class="stat-figure text-orange-500">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
/>
</svg>
</div>
<div class="stat-title">Total</div>
<div class="stat-value text-orange-500">{stats.total}</div>
<div class="stat-desc">Solicitações</div>
</div>
<div
class="stat bg-base-100 shadow-lg rounded-box border border-warning/30"
>
<div class="stat-figure text-warning">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="stat-title">Pendentes</div>
<div class="stat-value text-warning">{stats.aguardando}</div>
<div class="stat-desc">Aguardando</div>
</div>
<div class="stat bg-base-100 rounded-box border-warning/30 border shadow-lg">
<div class="stat-figure text-warning">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="stat-title">Pendentes</div>
<div class="stat-value text-warning">{stats.aguardando}</div>
<div class="stat-desc">Aguardando</div>
</div>
<div
class="stat bg-base-100 shadow-lg rounded-box border border-success/30"
>
<div class="stat-figure text-success">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="stat-title">Aprovadas</div>
<div class="stat-value text-success">{stats.aprovadas}</div>
<div class="stat-desc">Deferidas</div>
</div>
<div class="stat bg-base-100 rounded-box border-success/30 border shadow-lg">
<div class="stat-figure text-success">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="stat-title">Aprovadas</div>
<div class="stat-value text-success">{stats.aprovadas}</div>
<div class="stat-desc">Deferidas</div>
</div>
<div class="stat bg-base-100 shadow-lg rounded-box border border-error/30">
<div class="stat-figure text-error">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="stat-title">Reprovadas</div>
<div class="stat-value text-error">{stats.reprovadas}</div>
<div class="stat-desc">Indeferidas</div>
</div>
</div>
<div class="stat bg-base-100 rounded-box border-error/30 border shadow-lg">
<div class="stat-figure text-error">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<div class="stat-title">Reprovadas</div>
<div class="stat-value text-error">{stats.reprovadas}</div>
<div class="stat-desc">Indeferidas</div>
</div>
</div>
<!-- Filtros -->
<div class="card bg-base-100 shadow-lg mb-6">
<div class="card-body">
<h2 class="card-title text-lg mb-4">Filtros</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="form-control">
<label class="label" for="filtro-status">
<span class="label-text">Status</span>
</label>
<select
id="filtro-status"
class="select select-bordered"
bind:value={filtroStatus}
>
<option value="todos">Todos</option>
<option value="aguardando_aprovacao">Aguardando Aprovação</option>
<option value="aprovado">Aprovado</option>
<option value="reprovado">Reprovado</option>
</select>
</div>
</div>
</div>
</div>
<!-- Filtros -->
<div class="card bg-base-100 mb-6 shadow-lg">
<div class="card-body">
<h2 class="card-title mb-4 text-lg">Filtros</h2>
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
<div class="form-control">
<label class="label" for="filtro-status">
<span class="label-text">Status</span>
</label>
<select id="filtro-status" class="select select-bordered" bind:value={filtroStatus}>
<option value="todos">Todos</option>
<option value="aguardando_aprovacao">Aguardando Aprovação</option>
<option value="aprovado">Aprovado</option>
<option value="reprovado">Reprovado</option>
</select>
</div>
</div>
</div>
</div>
<!-- Lista de Solicitações -->
<div class="card bg-base-100 shadow-lg">
<div class="card-body">
<h2 class="card-title text-lg mb-4">
Todas as Solicitações ({ausenciasFiltradas.length})
</h2>
<!-- Lista de Solicitações -->
<div class="card bg-base-100 shadow-lg">
<div class="card-body">
<h2 class="card-title mb-4 text-lg">
Todas as Solicitações ({ausenciasFiltradas.length})
</h2>
{#if ausenciasFiltradas.length === 0}
<div class="alert">
<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>Nenhuma solicitação encontrada com os filtros aplicados.</span>
</div>
{:else}
<div class="overflow-x-auto">
<table class="table table-zebra">
<thead>
<tr>
<th>Funcionário</th>
<th>Time</th>
<th>Período</th>
<th>Dias</th>
<th>Motivo</th>
<th>Status</th>
<th>Solicitado em</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
{#each ausenciasFiltradas as ausencia}
<tr>
<td class="font-semibold">
{ausencia.funcionario?.nome || "N/A"}
</td>
<td>
{#if ausencia.time}
<div
class="badge badge-sm font-semibold"
style="background-color: {ausencia.time
.cor}20; border-color: {ausencia.time
.cor}; color: {ausencia.time.cor}"
>
{ausencia.time.nome}
</div>
{:else}
<span class="text-base-content/50">Sem time</span>
{/if}
</td>
<td>
{new Date(ausencia.dataInicio).toLocaleDateString("pt-BR")} até{" "}
{new Date(ausencia.dataFim).toLocaleDateString("pt-BR")}
</td>
<td class="font-bold">
{calcularDias(ausencia.dataInicio, ausencia.dataFim)} dias
</td>
<td class="max-w-xs truncate" title={ausencia.motivo}>
{ausencia.motivo}
</td>
<td>
<div class={`badge ${getStatusBadge(ausencia.status)}`}>
{getStatusTexto(ausencia.status)}
</div>
</td>
<td class="text-xs">
{new Date(ausencia.criadoEm).toLocaleDateString("pt-BR")}
</td>
<td>
{#if ausencia.status === "aguardando_aprovacao"}
<button
type="button"
class="btn btn-primary btn-sm gap-2"
onclick={() => selecionarSolicitacao(ausencia._id)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
/>
</svg>
Ver Detalhes
</button>
{:else}
<button
type="button"
class="btn btn-ghost btn-sm gap-2"
onclick={() => selecionarSolicitacao(ausencia._id)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
/>
</svg>
Ver Detalhes
</button>
{/if}
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{/if}
</div>
</div>
{#if ausenciasFiltradas.length === 0}
<div class="alert">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="stroke-info h-6 w-6 shrink-0"
>
<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>Nenhuma solicitação encontrada com os filtros aplicados.</span>
</div>
{:else}
<div class="overflow-x-auto">
<table class="table-zebra table">
<thead>
<tr>
<th>Funcionário</th>
<th>Time</th>
<th>Período</th>
<th>Dias</th>
<th>Motivo</th>
<th>Status</th>
<th>Solicitado em</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
{#each ausenciasFiltradas as ausencia}
<tr>
<td class="font-semibold">
{ausencia.funcionario?.nome || 'N/A'}
</td>
<td>
{#if ausencia.time}
<div
class="badge badge-sm font-semibold"
style="background-color: {ausencia.time.cor}20; border-color: {ausencia.time
.cor}; color: {ausencia.time.cor}"
>
{ausencia.time.nome}
</div>
{:else}
<span class="text-base-content/50">Sem time</span>
{/if}
</td>
<td>
{new Date(ausencia.dataInicio).toLocaleDateString('pt-BR')} até{' '}
{new Date(ausencia.dataFim).toLocaleDateString('pt-BR')}
</td>
<td class="font-bold">
{calcularDias(ausencia.dataInicio, ausencia.dataFim)} dias
</td>
<td class="max-w-xs truncate" title={ausencia.motivo}>
{ausencia.motivo}
</td>
<td>
<div class={`badge ${getStatusBadge(ausencia.status)}`}>
{getStatusTexto(ausencia.status)}
</div>
</td>
<td class="text-xs">
{new Date(ausencia.criadoEm).toLocaleDateString('pt-BR')}
</td>
<td>
{#if ausencia.status === 'aguardando_aprovacao'}
<button
type="button"
class="btn btn-primary btn-sm gap-2"
onclick={() => selecionarSolicitacao(ausencia._id)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
/>
</svg>
Ver Detalhes
</button>
{:else}
<button
type="button"
class="btn btn-sm gap-2"
onclick={() => selecionarSolicitacao(ausencia._id)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
/>
</svg>
Ver Detalhes
</button>
{/if}
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{/if}
</div>
</div>
</main>
<!-- Modal de Aprovação -->
{#if solicitacaoSelecionada && currentUser.data}
{#await client.query( api.ausencias.obterDetalhes, { solicitacaoId: solicitacaoSelecionada }, ) then detalhes}
{#if detalhes}
<dialog class="modal modal-open">
<div class="modal-box max-w-4xl">
<AprovarAusencias
solicitacao={detalhes}
gestorId={currentUser.data._id}
onSucesso={recarregar}
onCancelar={() => (solicitacaoSelecionada = null)}
/>
</div>
<form method="dialog" class="modal-backdrop">
<button
type="button"
onclick={() => (solicitacaoSelecionada = null)}
aria-label="Fechar modal">Fechar</button
>
</form>
</dialog>
{/if}
{/await}
{#await client.query( api.ausencias.obterDetalhes, { solicitacaoId: solicitacaoSelecionada } ) then detalhes}
{#if detalhes}
<dialog class="modal modal-open">
<div class="modal-box max-w-4xl">
<AprovarAusencias
solicitacao={detalhes}
gestorId={currentUser.data._id}
onSucesso={recarregar}
onCancelar={() => (solicitacaoSelecionada = null)}
/>
</div>
<form method="dialog" class="modal-backdrop">
<button
type="button"
onclick={() => (solicitacaoSelecionada = null)}
aria-label="Fechar modal">Fechar</button
>
</form>
</dialog>
{/if}
{/await}
{/if}