refactor: improve UI and functionality in employee registration and audit pages

- Enhanced the employee registration form by adding a dependents management section, allowing users to input details such as relationship, name, CPF, and birth date.
- Updated the layout and styling of the audit page, including improved statistics display and user feedback elements.
- Refined the handling of user actions in the audit logs, providing clearer labels and better organization of information.
- Improved the overall user experience by ensuring consistent design patterns and responsive elements across the registration and audit interfaces.
This commit is contained in:
2025-11-04 06:31:28 -03:00
parent d5c01aabab
commit f7cc758d33
3 changed files with 1848 additions and 1708 deletions

View File

@@ -702,71 +702,51 @@
</div> </div>
{/if} {/if}
<!-- Filtros --> <!-- Filtros -->
<div class="card bg-base-100 shadow-xl mb-6"> <div class="card bg-base-100 shadow-xl mb-6">
<div class="card-body"> <div class="card-body">
<h2 class="card-title mb-4">Filtros</h2> <h2 class="card-title mb-4">Filtros</h2>
<div class="grid grid-cols-1 md:grid-cols-4 gap-4"> <div class="grid grid-cols-1 md:grid-cols-5 gap-4 items-end">
<div class="form-control"> <div class="form-control">
<label class="label"> <label class="label cursor-pointer flex flex-col gap-2" for="filtro-tipo">
<span class="label-text">Tipo</span> <span class="label-text">Tipo</span>
</label> <select id="filtro-tipo" class="select select-bordered" bind:value={filtroTipo}>
<select
bind:value={filtroTipo}
class="select select-bordered"
>
<option value="todos">Todos</option> <option value="todos">Todos</option>
<option value="atestado_medico">Atestado Médico</option> <option value="atestado_medico">Atestado Médico</option>
<option value="declaracao_comparecimento">Declaração</option> <option value="declaracao_comparecimento">Declaração</option>
<option value="maternidade">Licença Maternidade</option> <option value="maternidade">Licença Maternidade</option>
<option value="paternidade">Licença Paternidade</option> <option value="paternidade">Licença Paternidade</option>
</select> </select>
</div> </label>
</div>
<div class="form-control"> <div class="form-control">
<label class="label"> <label class="label cursor-pointer flex flex-col gap-2" for="filtro-funcionario">
<span class="label-text">Funcionário</span> <span class="label-text">Funcionário</span>
</label> <input id="filtro-funcionario" class="input input-bordered" type="text" bind:value={filtroFuncionario} placeholder="Nome do colaborador" />
<input </label>
type="text" </div>
bind:value={filtroFuncionario}
placeholder="Buscar por nome..."
class="input input-bordered"
/>
</div>
<div class="form-control"> <div class="form-control">
<label class="label"> <label class="label cursor-pointer flex flex-col gap-2" for="filtro-data-inicio">
<span class="label-text">Data Início</span> <span class="label-text">Data Início</span>
</label> <input id="filtro-data-inicio" class="input input-bordered" type="date" bind:value={filtroDataInicio} />
<input </label>
type="date" </div>
bind:value={filtroDataInicio}
class="input input-bordered"
/>
</div>
<div class="form-control"> <div class="form-control">
<label class="label"> <label class="label cursor-pointer flex flex-col gap-2" for="filtro-data-fim">
<span class="label-text">Data Fim</span> <span class="label-text">Data Fim</span>
</label> <input id="filtro-data-fim" class="input input-bordered" type="date" bind:value={filtroDataFim} />
<div class="flex gap-2"> </label>
<input </div>
type="date"
bind:value={filtroDataFim} <div class="flex gap-2 justify-end">
class="input input-bordered flex-1" <button class="btn btn-outline" onclick={limparFiltros}>Limpar</button>
/>
<button
class="btn btn-outline"
onclick={limparFiltros}
>
Limpar
</button>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- Calendário Interativo --> <!-- Calendário Interativo -->
{#if eventosQuery?.data} {#if eventosQuery?.data}
@@ -1136,8 +1116,8 @@
: "Declaração"} : "Declaração"}
</span> </span>
</td> </td>
<td>{formatarData(atestado.dataInicio)}</td> <td class="whitespace-nowrap font-mono text-xs">{formatarData(atestado.dataInicio)}</td>
<td>{formatarData(atestado.dataFim)}</td> <td class="whitespace-nowrap font-mono text-xs">{formatarData(atestado.dataFim)}</td>
<td>{atestado.dias}</td> <td>{atestado.dias}</td>
<td> <td>
<span <span
@@ -1203,8 +1183,8 @@
{licenca.ehProrrogacao ? " (Prorrogação)" : ""} {licenca.ehProrrogacao ? " (Prorrogação)" : ""}
</span> </span>
</td> </td>
<td>{formatarData(licenca.dataInicio)}</td> <td class="whitespace-nowrap font-mono text-xs">{formatarData(licenca.dataInicio)}</td>
<td>{formatarData(licenca.dataFim)}</td> <td class="whitespace-nowrap font-mono text-xs">{formatarData(licenca.dataFim)}</td>
<td>{licenca.dias}</td> <td>{licenca.dias}</td>
<td> <td>
<span <span
@@ -1279,9 +1259,9 @@
/> />
<div class="form-control"> <div class="form-control">
<label class="label"> <div class="label">
<span class="label-text font-medium">Data Início <span class="text-error">*</span></span> <span class="label-text font-medium">Data Início <span class="text-error">*</span></span>
</label> </div>
<input <input
type="date" type="date"
bind:value={atestadoMedico.dataInicio} bind:value={atestadoMedico.dataInicio}
@@ -1291,9 +1271,9 @@
</div> </div>
<div class="form-control"> <div class="form-control">
<label class="label"> <div class="label">
<span class="label-text font-medium">Data Fim <span class="text-error">*</span></span> <span class="label-text font-medium">Data Fim <span class="text-error">*</span></span>
</label> </div>
<input <input
type="date" type="date"
bind:value={atestadoMedico.dataFim} bind:value={atestadoMedico.dataFim}
@@ -1303,9 +1283,9 @@
</div> </div>
<div class="form-control"> <div class="form-control">
<label class="label"> <div class="label">
<span class="label-text font-medium">CID <span class="text-error">*</span></span> <span class="label-text font-medium">CID <span class="text-error">*</span></span>
</label> </div>
<input <input
type="text" type="text"
bind:value={atestadoMedico.cid} bind:value={atestadoMedico.cid}
@@ -1333,9 +1313,9 @@
</div> </div>
<div class="form-control md:col-span-2"> <div class="form-control md:col-span-2">
<label class="label"> <div class="label">
<span class="label-text font-medium">Observações</span> <span class="label-text font-medium">Observações</span>
</label> </div>
<textarea <textarea
bind:value={atestadoMedico.observacoes} bind:value={atestadoMedico.observacoes}
class="textarea textarea-bordered h-24" class="textarea textarea-bordered h-24"
@@ -1379,9 +1359,9 @@
/> />
<div class="form-control"> <div class="form-control">
<label class="label"> <div class="label">
<span class="label-text font-medium">Data Início <span class="text-error">*</span></span> <span class="label-text font-medium">Data Início <span class="text-error">*</span></span>
</label> </div>
<input <input
type="date" type="date"
bind:value={declaracao.dataInicio} bind:value={declaracao.dataInicio}
@@ -1391,9 +1371,9 @@
</div> </div>
<div class="form-control"> <div class="form-control">
<label class="label"> <div class="label">
<span class="label-text font-medium">Data Fim <span class="text-error">*</span></span> <span class="label-text font-medium">Data Fim <span class="text-error">*</span></span>
</label> </div>
<input <input
type="date" type="date"
bind:value={declaracao.dataFim} bind:value={declaracao.dataFim}
@@ -1417,9 +1397,9 @@
</div> </div>
<div class="form-control md:col-span-2"> <div class="form-control md:col-span-2">
<label class="label"> <div class="label">
<span class="label-text font-medium">Observações</span> <span class="label-text font-medium">Observações</span>
</label> </div>
<textarea <textarea
bind:value={declaracao.observacoes} bind:value={declaracao.observacoes}
class="textarea textarea-bordered h-24" class="textarea textarea-bordered h-24"
@@ -1463,9 +1443,9 @@
/> />
<div class="form-control"> <div class="form-control">
<label class="label"> <div class="label">
<span class="label-text font-medium">Data Início <span class="text-error">*</span></span> <span class="label-text font-medium">Data Início <span class="text-error">*</span></span>
</label> </div>
<input <input
type="date" type="date"
bind:value={licencaMaternidade.dataInicio} bind:value={licencaMaternidade.dataInicio}
@@ -1475,18 +1455,18 @@
</div> </div>
<div class="form-control"> <div class="form-control">
<label class="label"> <div class="label">
<span class="label-text font-medium">Data Fim <span class="text-error">*</span></span> <span class="label-text font-medium">Data Fim <span class="text-error">*</span></span>
</label> </div>
<input <input
type="date" type="date"
bind:value={licencaMaternidade.dataFim} bind:value={licencaMaternidade.dataFim}
class="input input-bordered" class="input input-bordered"
required required
/> />
<label class="label"> <div class="label">
<span class="label-text-alt">Calculado automaticamente (120 dias)</span> <span class="label-text-alt">Calculado automaticamente (120 dias)</span>
</label> </div>
</div> </div>
<div class="form-control md:col-span-2"> <div class="form-control md:col-span-2">
@@ -1502,9 +1482,9 @@
{#if licencaMaternidade.ehProrrogacao} {#if licencaMaternidade.ehProrrogacao}
<div class="form-control md:col-span-2"> <div class="form-control md:col-span-2">
<label class="label"> <div class="label">
<span class="label-text font-medium">Licença Original <span class="text-error">*</span></span> <span class="label-text font-medium">Licença Original <span class="text-error">*</span></span>
</label> </div>
<select <select
bind:value={licencaMaternidade.licencaOriginalId} bind:value={licencaMaternidade.licencaOriginalId}
class="select select-bordered" class="select select-bordered"
@@ -1539,9 +1519,9 @@
</div> </div>
<div class="form-control md:col-span-2"> <div class="form-control md:col-span-2">
<label class="label"> <div class="label">
<span class="label-text font-medium">Observações</span> <span class="label-text font-medium">Observações</span>
</label> </div>
<textarea <textarea
bind:value={licencaMaternidade.observacoes} bind:value={licencaMaternidade.observacoes}
class="textarea textarea-bordered h-24" class="textarea textarea-bordered h-24"
@@ -1585,9 +1565,9 @@
/> />
<div class="form-control"> <div class="form-control">
<label class="label"> <div class="label">
<span class="label-text font-medium">Data Início <span class="text-error">*</span></span> <span class="label-text font-medium">Data Início <span class="text-error">*</span></span>
</label> </div>
<input <input
type="date" type="date"
bind:value={licencaPaternidade.dataInicio} bind:value={licencaPaternidade.dataInicio}
@@ -1597,18 +1577,18 @@
</div> </div>
<div class="form-control"> <div class="form-control">
<label class="label"> <div class="label">
<span class="label-text font-medium">Data Fim <span class="text-error">*</span></span> <span class="label-text font-medium">Data Fim <span class="text-error">*</span></span>
</label> </div>
<input <input
type="date" type="date"
bind:value={licencaPaternidade.dataFim} bind:value={licencaPaternidade.dataFim}
class="input input-bordered" class="input input-bordered"
required required
/> />
<label class="label"> <div class="label">
<span class="label-text-alt">Calculado automaticamente (20 dias)</span> <span class="label-text-alt">Calculado automaticamente (20 dias)</span>
</label> </div>
</div> </div>
<div class="form-control md:col-span-2"> <div class="form-control md:col-span-2">
@@ -1628,9 +1608,9 @@
</div> </div>
<div class="form-control md:col-span-2"> <div class="form-control md:col-span-2">
<label class="label"> <div class="label">
<span class="label-text font-medium">Observações</span> <span class="label-text font-medium">Observações</span>
</label> </div>
<textarea <textarea
bind:value={licencaPaternidade.observacoes} bind:value={licencaPaternidade.observacoes}
class="textarea textarea-bordered h-24" class="textarea textarea-bordered h-24"

View File

@@ -15,7 +15,8 @@
month: '2-digit', month: '2-digit',
year: 'numeric', year: 'numeric',
hour: '2-digit', hour: '2-digit',
minute: '2-digit' minute: '2-digit',
second: '2-digit'
}); });
} }
@@ -30,55 +31,128 @@
}; };
return colors[acao] || "badge-neutral"; return colors[acao] || "badge-neutral";
} }
function getAcaoLabel(acao: string) {
const labels: Record<string, string> = {
criar: "Criar",
editar: "Editar",
excluir: "Excluir",
bloquear: "Bloquear",
desbloquear: "Desbloquear",
resetar_senha: "Resetar Senha"
};
return labels[acao] || acao;
}
// Estatísticas
const totalAtividades = $derived(atividades?.data?.length || 0);
const totalLogins = $derived(logins?.data?.length || 0);
const loginsSucesso = $derived(logins?.data?.filter(l => l.sucesso).length || 0);
const loginsFalha = $derived(logins?.data?.filter(l => !l.sucesso).length || 0);
</script> </script>
<div class="container mx-auto px-4 py-6 max-w-7xl"> <main class="container mx-auto px-4 py-6 max-w-7xl">
<!-- Breadcrumb -->
<div class="text-sm breadcrumbs mb-4">
<ul>
<li><a href="/ti" class="text-primary hover:underline">TI</a></li>
<li>Auditoria e Logs</li>
</ul>
</div>
<!-- Header --> <!-- Header -->
<div class="flex items-center justify-between mb-6"> <div class="mb-6">
<div class="flex items-center gap-4"> <div class="flex items-center gap-4 mb-2">
<div class="p-3 bg-accent/10 rounded-xl"> <div class="p-3 bg-blue-500/20 rounded-xl">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-accent" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-blue-600" 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" /> <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> </svg>
</div> </div>
<div> <div>
<h1 class="text-3xl font-bold text-base-content">Auditoria e Logs</h1> <h1 class="text-3xl font-bold text-primary">Auditoria e Logs</h1>
<p class="text-base-content/60 mt-1">Histórico completo de atividades e acessos</p> <p class="text-base-content/70">Monitoramento completo de atividades e acessos do sistema</p>
</div> </div>
</div> </div>
</div> </div>
<!-- Cards de Estatísticas -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<div class="stat bg-base-100 shadow-lg rounded-lg">
<div class="stat-figure text-primary">
<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 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
</div>
<div class="stat-title text-xs">Atividades</div>
<div class="stat-value text-2xl">{totalAtividades}</div>
<div class="stat-desc">Registros exibidos</div>
</div>
<div class="stat bg-base-100 shadow-lg rounded-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="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1" />
</svg>
</div>
<div class="stat-title text-xs">Logins Totais</div>
<div class="stat-value text-2xl">{totalLogins}</div>
<div class="stat-desc">Tentativas de acesso</div>
</div>
<div class="stat bg-base-100 shadow-lg rounded-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 text-xs">Logins Bem-sucedidos</div>
<div class="stat-value text-2xl text-success">{loginsSucesso}</div>
<div class="stat-desc">{totalLogins > 0 ? Math.round((loginsSucesso / totalLogins) * 100) : 0}% de sucesso</div>
</div>
<div class="stat bg-base-100 shadow-lg rounded-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 text-xs">Logins Falhados</div>
<div class="stat-value text-2xl text-error">{loginsFalha}</div>
<div class="stat-desc">{totalLogins > 0 ? Math.round((loginsFalha / totalLogins) * 100) : 0}% de falhas</div>
</div>
</div>
<!-- Tabs --> <!-- Tabs -->
<div class="tabs tabs-boxed mb-6 bg-base-100 shadow-lg p-2"> <div class="tabs tabs-boxed mb-6 bg-base-100 shadow-lg p-1">
<button <button
class="tab {abaAtiva === 'atividades' ? 'tab-active' : ''}" class="tab flex items-center gap-2 {abaAtiva === 'atividades' ? 'tab-active' : ''}"
onclick={() => abaAtiva = "atividades"} onclick={() => abaAtiva = "atividades"}
> >
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" 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="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4" />
</svg> </svg>
Atividades no Sistema <span class="font-medium">Atividades no Sistema</span>
</button> </button>
<button <button
class="tab {abaAtiva === 'logins' ? 'tab-active' : ''}" class="tab flex items-center gap-2 {abaAtiva === 'logins' ? 'tab-active' : ''}"
onclick={() => abaAtiva = "logins"} onclick={() => abaAtiva = "logins"}
> >
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" 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="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1" />
</svg> </svg>
Histórico de Logins <span class="font-medium">Histórico de Logins</span>
</button> </button>
</div> </div>
<!-- Controles --> <!-- Controles -->
<div class="card bg-base-100 shadow-xl mb-6"> <div class="card bg-base-100 shadow-xl mb-6">
<div class="card-body"> <div class="card-body py-4">
<div class="flex flex-wrap items-center justify-between gap-4"> <div class="flex flex-wrap items-center justify-between gap-4">
<div class="form-control"> <div class="form-control">
<label class="label"> <label class="label py-1">
<span class="label-text">Quantidade de registros</span> <span class="label-text font-medium">Quantidade de registros</span>
</label> </label>
<select bind:value={limite} class="select select-bordered"> <select bind:value={limite} class="select select-bordered select-sm w-full max-w-xs">
<option value={20}>20 registros</option> <option value={20}>20 registros</option>
<option value={50}>50 registros</option> <option value={50}>50 registros</option>
<option value={100}>100 registros</option> <option value={100}>100 registros</option>
@@ -87,14 +161,14 @@
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<button class="btn btn-outline btn-primary"> <button class="btn btn-outline btn-primary btn-sm gap-2">
<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-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg> </svg>
Exportar CSV Exportar CSV
</button> </button>
<button class="btn btn-outline btn-secondary"> <button class="btn btn-outline btn-secondary btn-sm gap-2">
<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-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
</svg> </svg>
Filtros Avançados Filtros Avançados
@@ -108,45 +182,79 @@
{#if abaAtiva === "atividades"} {#if abaAtiva === "atividades"}
<div class="card bg-base-100 shadow-xl"> <div class="card bg-base-100 shadow-xl">
<div class="card-body"> <div class="card-body">
<h2 class="card-title mb-4">Atividades Recentes</h2> <div class="flex items-center justify-between mb-4">
<h2 class="card-title text-xl">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
Atividades Recentes
</h2>
{#if atividades?.data}
<div class="badge badge-outline badge-lg">{atividades.data.length} registro{atividades.data.length !== 1 ? 's' : ''}</div>
{/if}
</div>
{#if !atividades?.data} {#if !atividades?.data}
<div class="flex justify-center py-10"> <div class="flex flex-col items-center justify-center py-16">
<span class="loading loading-spinner loading-lg text-primary"></span> <span class="loading loading-spinner loading-lg text-primary mb-4"></span>
<p class="text-base-content/60">Carregando atividades...</p>
</div> </div>
{:else if atividades.data.length === 0} {:else if atividades.data.length === 0}
<div class="text-center py-10 text-base-content/60"> <div class="flex flex-col items-center justify-center py-16 text-base-content/60">
Nenhuma atividade registrada <svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 mb-4 opacity-50" 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>
<p class="text-lg font-medium">Nenhuma atividade registrada</p>
<p class="text-sm mt-1">As atividades do sistema aparecerão aqui</p>
</div> </div>
{:else} {:else}
<div class="overflow-x-auto"> <div class="overflow-x-auto rounded-lg">
<table class="table table-sm"> <table class="table table-zebra">
<thead> <thead class="bg-base-200">
<tr> <tr>
<th>Data/Hora</th> <th class="font-semibold">Data/Hora</th>
<th>Usuário</th> <th class="font-semibold">Usuário</th>
<th>Ação</th> <th class="font-semibold">Ação</th>
<th>Recurso</th> <th class="font-semibold">Recurso</th>
<th>Detalhes</th> <th class="font-semibold">Detalhes</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each atividades.data as atividade} {#each atividades.data as atividade}
<tr class="hover"> <tr class="hover transition-colors">
<td class="font-mono text-xs">{formatarData(atividade.timestamp)}</td>
<td> <td>
<div class="font-medium">{atividade.usuarioNome || "Sistema"}</div> <div class="flex items-center gap-2">
<div class="text-xs opacity-60">{atividade.usuarioMatricula || "-"}</div> <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-base-content/40" 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>
<span class="font-mono text-xs">{formatarData(atividade.timestamp)}</span>
</div>
</td> </td>
<td> <td>
<span class="badge {getAcaoColor(atividade.acao)} badge-sm"> <div class="flex flex-col">
{atividade.acao} <div class="font-semibold text-sm">{atividade.usuarioNome || "Sistema"}</div>
{#if atividade.usuarioMatricula}
<div class="text-xs text-base-content/50 font-mono">{atividade.usuarioMatricula}</div>
{/if}
</div>
</td>
<td>
<span class="badge {getAcaoColor(atividade.acao)} badge-sm gap-1">
{getAcaoLabel(atividade.acao)}
</span> </span>
</td> </td>
<td class="font-medium">{atividade.recurso}</td>
<td> <td>
<div class="text-xs max-w-md truncate" title={atividade.detalhes}> <span class="font-medium text-sm">{atividade.recurso}</span>
{atividade.detalhes || "-"} </td>
<td>
<div class="max-w-md">
{#if atividade.detalhes}
<div class="text-xs text-base-content/70 truncate" title={atividade.detalhes}>
{atividade.detalhes}
</div>
{:else}
<span class="text-base-content/40 text-xs">-</span>
{/if}
</div> </div>
</td> </td>
</tr> </tr>
@@ -160,49 +268,98 @@
{:else} {:else}
<div class="card bg-base-100 shadow-xl"> <div class="card bg-base-100 shadow-xl">
<div class="card-body"> <div class="card-body">
<h2 class="card-title mb-4">Histórico de Logins</h2> <div class="flex items-center justify-between mb-4">
<h2 class="card-title text-xl">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1" />
</svg>
Histórico de Logins
</h2>
{#if logins?.data}
<div class="badge badge-outline badge-lg">{logins.data.length} registro{logins.data.length !== 1 ? 's' : ''}</div>
{/if}
</div>
{#if !logins?.data} {#if !logins?.data}
<div class="flex justify-center py-10"> <div class="flex flex-col items-center justify-center py-16">
<span class="loading loading-spinner loading-lg text-primary"></span> <span class="loading loading-spinner loading-lg text-primary mb-4"></span>
<p class="text-base-content/60">Carregando logins...</p>
</div> </div>
{:else if logins.data.length === 0} {:else if logins.data.length === 0}
<div class="text-center py-10 text-base-content/60"> <div class="flex flex-col items-center justify-center py-16 text-base-content/60">
Nenhum login registrado <svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 mb-4 opacity-50" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1" />
</svg>
<p class="text-lg font-medium">Nenhum login registrado</p>
<p class="text-sm mt-1">Os acessos ao sistema aparecerão aqui</p>
</div> </div>
{:else} {:else}
<div class="overflow-x-auto"> <div class="overflow-x-auto rounded-lg">
<table class="table table-sm"> <table class="table table-zebra">
<thead> <thead class="bg-base-200">
<tr> <tr>
<th>Data/Hora</th> <th class="font-semibold">Data/Hora</th>
<th>Usuário/Email</th> <th class="font-semibold">Usuário/Email</th>
<th>Status</th> <th class="font-semibold">Status</th>
<th>IP</th> <th class="font-semibold">IP</th>
<th>Dispositivo</th> <th class="font-semibold">Dispositivo</th>
<th>Navegador</th> <th class="font-semibold">Navegador</th>
<th>Sistema</th> <th class="font-semibold">Sistema</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each logins.data as login} {#each logins.data as login}
<tr class="hover"> <tr class="hover transition-colors">
<td class="font-mono text-xs">{formatarData(login.timestamp)}</td>
<td class="text-sm">{login.matriculaOuEmail}</td>
<td> <td>
{#if login.sucesso} <div class="flex items-center gap-2">
<span class="badge badge-success badge-sm">Sucesso</span> <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-base-content/40" fill="none" viewBox="0 0 24 24" stroke="currentColor">
{:else} <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" />
<span class="badge badge-error badge-sm">Falhou</span> </svg>
{#if login.motivoFalha} <span class="font-mono text-xs">{formatarData(login.timestamp)}</span>
<div class="text-xs text-error mt-1">{login.motivoFalha}</div> </div>
{/if} </td>
{/if} <td>
<div class="flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-base-content/40" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
<span class="text-sm font-medium">{login.matriculaOuEmail}</span>
</div>
</td>
<td>
<div class="flex flex-col gap-1">
{#if login.sucesso}
<span class="badge badge-success badge-sm gap-1">
<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="M5 13l4 4L19 7" />
</svg>
Sucesso
</span>
{:else}
<span class="badge badge-error badge-sm gap-1">
<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="M6 18L18 6M6 6l12 12" />
</svg>
Falhou
</span>
{#if login.motivoFalha}
<div class="text-xs text-error mt-1 font-medium">{login.motivoFalha}</div>
{/if}
{/if}
</div>
</td>
<td>
<span class="font-mono text-xs bg-base-200 px-2 py-1 rounded">{login.ipAddress || "-"}</span>
</td>
<td>
<div class="text-xs text-base-content/70">{login.device || "-"}</div>
</td>
<td>
<div class="text-xs text-base-content/70">{login.browser || "-"}</div>
</td>
<td>
<div class="text-xs text-base-content/70">{login.sistema || "-"}</div>
</td> </td>
<td class="font-mono text-xs">{login.ipAddress || "-"}</td>
<td class="text-xs">{login.device || "-"}</td>
<td class="text-xs">{login.browser || "-"}</td>
<td class="text-xs">{login.sistema || "-"}</td>
</tr> </tr>
{/each} {/each}
</tbody> </tbody>
@@ -214,11 +371,14 @@
{/if} {/if}
<!-- Informação --> <!-- Informação -->
<div class="alert alert-info mt-6"> <div class="alert alert-info shadow-lg mt-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"> <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>
<span>Os logs são armazenados permanentemente e não podem ser alterados ou excluídos.</span> <div>
<h3 class="font-bold">Informação Importante</h3>
<div class="text-sm">Os logs são armazenados permanentemente e não podem ser alterados ou excluídos.</div>
</div>
</div> </div>
</div> </main>