Fix usuarios page #6

Merged
killer-cf merged 28 commits from fix-usuarios-page into master 2025-11-04 17:42:21 +00:00
77 changed files with 14170 additions and 7460 deletions
Showing only changes of commit 90eee27ba7 - Show all commits

View File

@@ -1,383 +1,383 @@
<script lang="ts"> <script lang="ts">
import { useQuery, useConvexClient } from "convex-svelte"; import { useQuery, useConvexClient } from "convex-svelte";
import { api } from "@sgse-app/backend/convex/_generated/api"; import { api } from "@sgse-app/backend/convex/_generated/api";
import type { Id } from "@sgse-app/backend/convex/_generated/dataModel"; import type { Id } from "@sgse-app/backend/convex/_generated/dataModel";
let { onClose }: { onClose: () => void } = $props(); let { onClose }: { onClose: () => void } = $props();
const client = useConvexClient(); const client = useConvexClient();
const alertasQuery = useQuery(api.monitoramento.listarAlertas, {}); const alertasQuery = useQuery(api.monitoramento.listarAlertas, {});
const alertas = $derived.by(() => { const alertas = $derived.by(() => {
if (!alertasQuery) return []; if (!alertasQuery) return [];
// O useQuery pode retornar o array diretamente ou em .data // O useQuery pode retornar o array diretamente ou em .data
if (Array.isArray(alertasQuery)) return alertasQuery; if (Array.isArray(alertasQuery)) return alertasQuery;
return alertasQuery.data ?? []; return alertasQuery.data ?? [];
}); });
// Estado para novo alerta // Estado para novo alerta
let editingAlertId = $state<Id<"alertConfigurations"> | null>(null); let editingAlertId = $state<Id<"alertConfigurations"> | null>(null);
let metricName = $state("cpuUsage"); let metricName = $state("cpuUsage");
let threshold = $state(80); let threshold = $state(80);
let operator = $state<">" | "<" | ">=" | "<=" | "==">(">"); let operator = $state<">" | "<" | ">=" | "<=" | "==">(">");
let enabled = $state(true); let enabled = $state(true);
let notifyByEmail = $state(false); let notifyByEmail = $state(false);
let notifyByChat = $state(true); let notifyByChat = $state(true);
let saving = $state(false); let saving = $state(false);
let showForm = $state(false); let showForm = $state(false);
const metricOptions = [ const metricOptions = [
{ value: "cpuUsage", label: "Uso de CPU (%)" }, { value: "cpuUsage", label: "Uso de CPU (%)" },
{ value: "memoryUsage", label: "Uso de Memória (%)" }, { value: "memoryUsage", label: "Uso de Memória (%)" },
{ value: "networkLatency", label: "Latência de Rede (ms)" }, { value: "networkLatency", label: "Latência de Rede (ms)" },
{ value: "storageUsed", label: "Armazenamento Usado (%)" }, { value: "storageUsed", label: "Armazenamento Usado (%)" },
{ value: "usuariosOnline", label: "Usuários Online" }, { value: "usuariosOnline", label: "Usuários Online" },
{ value: "mensagensPorMinuto", label: "Mensagens por Minuto" }, { value: "mensagensPorMinuto", label: "Mensagens por Minuto" },
{ value: "tempoRespostaMedio", label: "Tempo de Resposta (ms)" }, { value: "tempoRespostaMedio", label: "Tempo de Resposta (ms)" },
{ value: "errosCount", label: "Contagem de Erros" }, { value: "errosCount", label: "Contagem de Erros" },
]; ];
const operatorOptions = [ const operatorOptions = [
{ value: ">", label: "Maior que (>)" }, { value: ">", label: "Maior que (>)" },
{ value: ">=", label: "Maior ou igual (≥)" }, { value: ">=", label: "Maior ou igual (≥)" },
{ value: "<", label: "Menor que (<)" }, { value: "<", label: "Menor que (<)" },
{ value: "<=", label: "Menor ou igual (≤)" }, { value: "<=", label: "Menor ou igual (≤)" },
{ value: "==", label: "Igual a (=)" }, { value: "==", label: "Igual a (=)" },
]; ];
function resetForm() { function resetForm() {
editingAlertId = null; editingAlertId = null;
metricName = "cpuUsage"; metricName = "cpuUsage";
threshold = 80; threshold = 80;
operator = ">"; operator = ">";
enabled = true; enabled = true;
notifyByEmail = false; notifyByEmail = false;
notifyByChat = true; notifyByChat = true;
showForm = false; showForm = false;
} }
function editAlert(alert: any) { function editAlert(alert: any) {
editingAlertId = alert._id; editingAlertId = alert._id;
metricName = alert.metricName; metricName = alert.metricName;
threshold = alert.threshold; threshold = alert.threshold;
operator = alert.operator; operator = alert.operator;
enabled = alert.enabled; enabled = alert.enabled;
notifyByEmail = alert.notifyByEmail; notifyByEmail = alert.notifyByEmail;
notifyByChat = alert.notifyByChat; notifyByChat = alert.notifyByChat;
showForm = true; showForm = true;
} }
async function saveAlert() { async function saveAlert() {
saving = true; saving = true;
try { try {
await client.mutation(api.monitoramento.configurarAlerta, { await client.mutation(api.monitoramento.configurarAlerta, {
alertId: editingAlertId || undefined, alertId: editingAlertId || undefined,
metricName, metricName,
threshold, threshold,
operator, operator,
enabled, enabled,
notifyByEmail, notifyByEmail,
notifyByChat, notifyByChat,
}); });
resetForm(); resetForm();
} catch (error) { } catch (error) {
console.error("Erro ao salvar alerta:", error); console.error("Erro ao salvar alerta:", error);
alert("Erro ao salvar alerta. Tente novamente."); alert("Erro ao salvar alerta. Tente novamente.");
} finally { } finally {
saving = false; saving = false;
} }
} }
async function deleteAlert(alertId: Id<"alertConfigurations">) { async function deleteAlert(alertId: Id<"alertConfigurations">) {
if (!confirm("Tem certeza que deseja deletar este alerta?")) return; if (!confirm("Tem certeza que deseja deletar este alerta?")) return;
try { try {
await client.mutation(api.monitoramento.deletarAlerta, { alertId }); await client.mutation(api.monitoramento.deletarAlerta, { alertId });
} catch (error) { } catch (error) {
console.error("Erro ao deletar alerta:", error); console.error("Erro ao deletar alerta:", error);
alert("Erro ao deletar alerta. Tente novamente."); alert("Erro ao deletar alerta. Tente novamente.");
} }
} }
function getMetricLabel(metricName: string): string { function getMetricLabel(metricName: string): string {
return metricOptions.find(m => m.value === metricName)?.label || metricName; return metricOptions.find(m => m.value === metricName)?.label || metricName;
} }
function getOperatorLabel(op: string): string { function getOperatorLabel(op: string): string {
return operatorOptions.find(o => o.value === op)?.label || op; return operatorOptions.find(o => o.value === op)?.label || op;
} }
</script> </script>
<dialog class="modal modal-open"> <dialog class="modal modal-open">
<div class="modal-box max-w-4xl bg-gradient-to-br from-base-100 to-base-200"> <div class="modal-box max-w-4xl bg-gradient-to-br from-base-100 to-base-200">
<button <button
type="button" type="button"
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2" class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
onclick={onClose} onclick={onClose}
> >
</button> </button>
<h3 class="font-bold text-3xl text-primary mb-2">⚙️ Configuração de Alertas</h3> <h3 class="font-bold text-3xl text-primary mb-2">⚙️ Configuração de Alertas</h3>
<p class="text-base-content/60 mb-6">Configure alertas personalizados para monitoramento do sistema</p> <p class="text-base-content/60 mb-6">Configure alertas personalizados para monitoramento do sistema</p>
<!-- Botão Novo Alerta --> <!-- Botão Novo Alerta -->
{#if !showForm} {#if !showForm}
<button <button
type="button" type="button"
class="btn btn-primary mb-6" class="btn btn-primary mb-6"
onclick={() => showForm = true} onclick={() => showForm = true}
> >
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <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="M12 4v16m8-8H4" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg> </svg>
Novo Alerta Novo Alerta
</button> </button>
{/if} {/if}
<!-- Formulário de Alerta --> <!-- Formulário de Alerta -->
{#if showForm} {#if showForm}
<div class="card bg-base-100 shadow-xl mb-6 border-2 border-primary/20"> <div class="card bg-base-100 shadow-xl mb-6 border-2 border-primary/20">
<div class="card-body"> <div class="card-body">
<h4 class="card-title text-xl"> <h4 class="card-title text-xl">
{editingAlertId ? "Editar Alerta" : "Novo Alerta"} {editingAlertId ? "Editar Alerta" : "Novo Alerta"}
</h4> </h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4"> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
<!-- Métrica --> <!-- Métrica -->
<div class="form-control"> <div class="form-control">
<label class="label" for="metric"> <label class="label" for="metric">
<span class="label-text font-semibold">Métrica</span> <span class="label-text font-semibold">Métrica</span>
</label> </label>
<select <select
id="metric" id="metric"
class="select select-bordered select-primary" class="select select-bordered select-primary"
bind:value={metricName} bind:value={metricName}
> >
{#each metricOptions as option} {#each metricOptions as option}
<option value={option.value}>{option.label}</option> <option value={option.value}>{option.label}</option>
{/each} {/each}
</select> </select>
</div> </div>
<!-- Operador --> <!-- Operador -->
<div class="form-control"> <div class="form-control">
<label class="label" for="operator"> <label class="label" for="operator">
<span class="label-text font-semibold">Condição</span> <span class="label-text font-semibold">Condição</span>
</label> </label>
<select <select
id="operator" id="operator"
class="select select-bordered select-primary" class="select select-bordered select-primary"
bind:value={operator} bind:value={operator}
> >
{#each operatorOptions as option} {#each operatorOptions as option}
<option value={option.value}>{option.label}</option> <option value={option.value}>{option.label}</option>
{/each} {/each}
</select> </select>
</div> </div>
<!-- Threshold --> <!-- Threshold -->
<div class="form-control"> <div class="form-control">
<label class="label" for="threshold"> <label class="label" for="threshold">
<span class="label-text font-semibold">Valor Limite</span> <span class="label-text font-semibold">Valor Limite</span>
</label> </label>
<input <input
id="threshold" id="threshold"
type="number" type="number"
class="input input-bordered input-primary" class="input input-bordered input-primary"
bind:value={threshold} bind:value={threshold}
min="0" min="0"
step="1" step="1"
/> />
</div> </div>
<!-- Ativo --> <!-- Ativo -->
<div class="form-control"> <div class="form-control">
<label class="label cursor-pointer justify-start gap-4"> <label class="label cursor-pointer justify-start gap-4">
<span class="label-text font-semibold">Alerta Ativo</span> <span class="label-text font-semibold">Alerta Ativo</span>
<input <input
type="checkbox" type="checkbox"
class="toggle toggle-primary" class="toggle toggle-primary"
bind:checked={enabled} bind:checked={enabled}
/> />
</label> </label>
</div> </div>
</div> </div>
<!-- Notificações --> <!-- Notificações -->
<div class="divider">Método de Notificação</div> <div class="divider">Método de Notificação</div>
<div class="flex gap-6"> <div class="flex gap-6">
<label class="label cursor-pointer gap-3"> <label class="label cursor-pointer gap-3">
<input <input
type="checkbox" type="checkbox"
class="checkbox checkbox-primary" class="checkbox checkbox-primary"
bind:checked={notifyByChat} bind:checked={notifyByChat}
/> />
<span class="label-text"> <span class="label-text">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" />
</svg> </svg>
Notificar por Chat Notificar por Chat
</span> </span>
</label> </label>
<label class="label cursor-pointer gap-3"> <label class="label cursor-pointer gap-3">
<input <input
type="checkbox" type="checkbox"
class="checkbox checkbox-secondary" class="checkbox checkbox-secondary"
bind:checked={notifyByEmail} bind:checked={notifyByEmail}
/> />
<span class="label-text"> <span class="label-text">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg> </svg>
Notificar por E-mail Notificar por E-mail
</span> </span>
</label> </label>
</div> </div>
<!-- Preview --> <!-- Preview -->
<div class="alert alert-info mt-4"> <div class="alert alert-info mt-4">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current 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> <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> </svg>
<div> <div>
<h4 class="font-bold">Preview do Alerta:</h4> <h4 class="font-bold">Preview do Alerta:</h4>
<p class="text-sm"> <p class="text-sm">
Alertar quando <strong>{getMetricLabel(metricName)}</strong> for Alertar quando <strong>{getMetricLabel(metricName)}</strong> for
<strong>{getOperatorLabel(operator)}</strong> a <strong>{threshold}</strong> <strong>{getOperatorLabel(operator)}</strong> a <strong>{threshold}</strong>
</p> </p>
</div> </div>
</div> </div>
<!-- Botões --> <!-- Botões -->
<div class="card-actions justify-end mt-4"> <div class="card-actions justify-end mt-4">
<button <button
type="button" type="button"
class="btn btn-ghost" class="btn btn-ghost"
onclick={resetForm} onclick={resetForm}
disabled={saving} disabled={saving}
> >
Cancelar Cancelar
</button> </button>
<button <button
type="button" type="button"
class="btn btn-primary" class="btn btn-primary"
onclick={saveAlert} onclick={saveAlert}
disabled={saving || (!notifyByChat && !notifyByEmail)} disabled={saving || (!notifyByChat && !notifyByEmail)}
> >
{#if saving} {#if saving}
<span class="loading loading-spinner"></span> <span class="loading loading-spinner"></span>
Salvando... Salvando...
{:else} {:else}
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <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="M5 13l4 4L19 7" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg> </svg>
Salvar Alerta Salvar Alerta
{/if} {/if}
</button> </button>
</div> </div>
</div> </div>
</div> </div>
{/if} {/if}
<!-- Lista de Alertas --> <!-- Lista de Alertas -->
<div class="divider">Alertas Configurados</div> <div class="divider">Alertas Configurados</div>
{#if alertas.length > 0} {#if alertas.length > 0}
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="table table-zebra"> <table class="table table-zebra">
<thead> <thead>
<tr> <tr>
<th>Métrica</th> <th>Métrica</th>
<th>Condição</th> <th>Condição</th>
<th>Status</th> <th>Status</th>
<th>Notificações</th> <th>Notificações</th>
<th>Ações</th> <th>Ações</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each alertas as alerta} {#each alertas as alerta}
<tr class={!alerta.enabled ? "opacity-50" : ""}> <tr class={!alerta.enabled ? "opacity-50" : ""}>
<td> <td>
<div class="font-semibold">{getMetricLabel(alerta.metricName)}</div> <div class="font-semibold">{getMetricLabel(alerta.metricName)}</div>
</td> </td>
<td> <td>
<div class="badge badge-outline"> <div class="badge badge-outline">
{getOperatorLabel(alerta.operator)} {alerta.threshold} {getOperatorLabel(alerta.operator)} {alerta.threshold}
</div> </div>
</td> </td>
<td> <td>
{#if alerta.enabled} {#if alerta.enabled}
<div class="badge badge-success gap-2"> <div class="badge badge-success gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" 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" /> <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> </svg>
Ativo Ativo
</div> </div>
{:else} {:else}
<div class="badge badge-ghost gap-2"> <div class="badge badge-ghost gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" 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" /> <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> </svg>
Inativo Inativo
</div> </div>
{/if} {/if}
</td> </td>
<td> <td>
<div class="flex gap-1"> <div class="flex gap-1">
{#if alerta.notifyByChat} {#if alerta.notifyByChat}
<div class="badge badge-primary badge-sm">Chat</div> <div class="badge badge-primary badge-sm">Chat</div>
{/if} {/if}
{#if alerta.notifyByEmail} {#if alerta.notifyByEmail}
<div class="badge badge-secondary badge-sm">Email</div> <div class="badge badge-secondary badge-sm">Email</div>
{/if} {/if}
</div> </div>
</td> </td>
<td> <td>
<div class="flex gap-2"> <div class="flex gap-2">
<button <button
type="button" type="button"
class="btn btn-ghost btn-xs" class="btn btn-ghost btn-xs"
onclick={() => editAlert(alerta)} onclick={() => editAlert(alerta)}
> >
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <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="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
</svg> </svg>
</button> </button>
<button <button
type="button" type="button"
class="btn btn-ghost btn-xs text-error" class="btn btn-ghost btn-xs text-error"
onclick={() => deleteAlert(alerta._id)} onclick={() => deleteAlert(alerta._id)}
> >
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <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="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg> </svg>
</button> </button>
</div> </div>
</td> </td>
</tr> </tr>
{/each} {/each}
</tbody> </tbody>
</table> </table>
</div> </div>
{:else} {:else}
<div class="alert"> <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"> <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> <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> </svg>
<span>Nenhum alerta configurado. Clique em "Novo Alerta" para criar um.</span> <span>Nenhum alerta configurado. Clique em "Novo Alerta" para criar um.</span>
</div> </div>
{/if} {/if}
<div class="modal-action"> <div class="modal-action">
<button type="button" class="btn btn-lg" onclick={onClose}>Fechar</button> <button type="button" class="btn btn-lg" onclick={onClose}>Fechar</button>
</div> </div>
</div> </div>
<!-- svelte-ignore a11y_click_events_have_key_events --> <!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_noninteractive_element_interactions --> <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
<form method="dialog" class="modal-backdrop" onclick={onClose}> <form method="dialog" class="modal-backdrop" onclick={onClose}>
<button type="button">close</button> <button type="button">close</button>
</form> </form>
</dialog> </dialog>