feat: replace SVG icons with Lucide components across various Svelte components for improved consistency and maintainability

This commit is contained in:
2025-12-04 14:30:31 -03:00
parent a3d9e782af
commit 88f25dc6ab
21 changed files with 457 additions and 2921 deletions

View File

@@ -1,5 +1,20 @@
<script lang="ts">
import { resolve } from '$app/paths';
import {
Settings,
Headphones,
ShieldCheck,
Mail,
Users,
Bell,
Monitor,
FileText,
UserPlus,
Clock,
Video,
Building,
Info
} from 'lucide-svelte';
type HighlightVariant = 'solid' | 'outline';
type FeatureIcon =
| 'control'
@@ -45,13 +60,6 @@
highlightBadges?: Array<{ label: string; variant: HighlightVariant }>;
};
type IconPath = {
d: string;
strokeLinecap?: 'butt' | 'round' | 'square';
strokeLinejoin?: 'miter' | 'round' | 'bevel';
strokeWidth?: number;
};
const paletteStyles: Record<
PaletteKey,
{
@@ -129,7 +137,8 @@
}
};
const iconPaths: Record<FeatureIcon, IconPath[]> = {
// Removido: iconPaths substituído por iconComponents com Lucide
const iconPaths_OLD: Record<FeatureIcon, IconPath[]> = {
control: [
{
d: 'M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4',
@@ -457,22 +466,11 @@
<div
class={`relative flex h-14 w-14 shrink-0 items-center justify-center rounded-2xl ${paletteStyles[card.palette].iconBg} ${paletteStyles[card.palette].iconRing}`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
<svelte:component
this={iconComponents[card.icon]}
class={`h-7 w-7 ${paletteStyles[card.palette].iconColor}`}
>
{#each iconPaths[card.icon] as path (path.d)}
<path
d={path.d}
stroke-linecap={path.strokeLinecap ?? 'round'}
stroke-linejoin={path.strokeLinejoin ?? 'round'}
stroke-width={path.strokeWidth ?? 2}
/>
{/each}
</svg>
strokeWidth={2}
/>
</div>
<div class="relative flex-1">
<h2 class="text-base-content text-xl font-semibold">
@@ -487,22 +485,11 @@
<div
class={`relative flex h-14 w-14 shrink-0 items-center justify-center rounded-2xl ${paletteStyles[card.palette].iconBg} ${paletteStyles[card.palette].iconRing}`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
<svelte:component
this={iconComponents[card.icon]}
class={`h-7 w-7 ${paletteStyles[card.palette].iconColor}`}
>
{#each iconPaths[card.icon] as path (path.d)}
<path
d={path.d}
stroke-linecap={path.strokeLinecap ?? 'round'}
stroke-linejoin={path.strokeLinejoin ?? 'round'}
stroke-width={path.strokeWidth ?? 2}
/>
{/each}
</svg>
strokeWidth={2}
/>
</div>
<div class="relative flex-1">
<h2 class="text-base-content text-xl font-semibold">
@@ -522,19 +509,7 @@
<div
class="bg-warning/25 text-warning flex h-12 w-12 items-center justify-center rounded-full"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="h-6 w-6 stroke-current"
>
<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"
/>
</svg>
<Info class="h-6 w-6 stroke-current" strokeWidth={2} />
</div>
<div>
<h3 class="text-base-content text-lg font-bold">Área Restrita</h3>

View File

@@ -8,6 +8,25 @@
import autoTable from 'jspdf-autotable';
import Papa from 'papaparse';
import logoGovPE from '$lib/assets/logo_governo_PE.png';
import {
FileText,
Clipboard,
LogIn,
CheckCircle,
XCircle,
Download,
Filter,
ArrowLeft,
Search,
Calendar,
User,
X,
Clock,
Inbox,
MapPin,
Info,
Mail
} from 'lucide-svelte';
let abaAtiva = $state<'atividades' | 'logins'>('atividades');
let limite = $state(50);
@@ -441,20 +460,7 @@
<div class="mb-6">
<div class="mb-2 flex items-center gap-4">
<div class="rounded-xl bg-blue-500/20 p-3">
<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"
/>
</svg>
<FileText class="h-8 w-8 text-blue-600" strokeWidth={2} />
</div>
<div>
<h1 class="text-primary text-3xl font-bold">Auditoria e Logs</h1>
@@ -469,20 +475,7 @@
<div class="mb-6 grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
<div class="stat bg-base-100 rounded-lg shadow-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>
<Clipboard class="h-8 w-8" strokeWidth={2} />
</div>
<div class="stat-title text-xs">Atividades</div>
<div class="stat-value text-2xl">{totalAtividades}</div>
@@ -491,20 +484,7 @@
<div class="stat bg-base-100 rounded-lg 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="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>
<LogIn class="h-8 w-8" strokeWidth={2} />
</div>
<div class="stat-title text-xs">Logins Totais</div>
<div class="stat-value text-2xl">{totalLogins}</div>
@@ -513,20 +493,7 @@
<div class="stat bg-base-100 rounded-lg 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>
<CheckCircle class="h-8 w-8" strokeWidth={2} />
</div>
<div class="stat-title text-xs">Logins Bem-sucedidos</div>
<div class="stat-value text-success text-2xl">{loginsSucesso}</div>
@@ -537,20 +504,7 @@
<div class="stat bg-base-100 rounded-lg 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>
<XCircle class="h-8 w-8" strokeWidth={2} />
</div>
<div class="stat-title text-xs">Logins Falhados</div>
<div class="stat-value text-error text-2xl">{loginsFalha}</div>
@@ -566,40 +520,14 @@
class="tab flex items-center gap-2 {abaAtiva === 'atividades' ? 'tab-active' : ''}"
onclick={() => (abaAtiva = 'atividades')}
>
<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 2m-6 9l2 2 4-4"
/>
</svg>
<Clipboard class="h-5 w-5" strokeWidth={2} />
<span class="font-medium">Atividades no Sistema</span>
</button>
<button
class="tab flex items-center gap-2 {abaAtiva === 'logins' ? 'tab-active' : ''}"
onclick={() => (abaAtiva = 'logins')}
>
<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"
/>
</svg>
<LogIn class="h-5 w-5" strokeWidth={2} />
<span class="font-medium">Histórico de Logins</span>
</button>
</div>
@@ -630,20 +558,7 @@
{#if exportando}
<span class="loading loading-spinner loading-xs"></span>
{:else}
<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"
/>
</svg>
<Download class="h-4 w-4" strokeWidth={2} />
{/if}
Exportar CSV
</button>
@@ -656,20 +571,7 @@
{#if exportando}
<span class="loading loading-spinner loading-xs"></span>
{:else}
<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="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"
/>
</svg>
<FileText class="h-4 w-4" strokeWidth={2} />
{/if}
Exportar PDF
</button>
@@ -677,20 +579,7 @@
class="btn btn-outline btn-secondary btn-sm gap-2"
onclick={() => (mostrarFiltros = !mostrarFiltros)}
>
<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"
/>
</svg>
<Filter class="h-4 w-4" strokeWidth={2} />
Filtros Avançados
</button>
</div>
@@ -764,20 +653,7 @@
<div class="card-body">
<div class="mb-4 flex items-center justify-between">
<h2 class="card-title text-xl">
<svg
xmlns="http://www.w3.org/2000/svg"
class="mr-2 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"
/>
</svg>
<Clipboard class="mr-2 h-5 w-5" strokeWidth={2} />
Atividades Recentes
</h2>
{#if atividades}
@@ -794,20 +670,7 @@
</div>
{:else if atividades.length === 0}
<div class="text-base-content/60 flex flex-col items-center justify-center py-16">
<svg
xmlns="http://www.w3.org/2000/svg"
class="mb-4 h-16 w-16 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>
<Inbox class="mb-4 h-16 w-16 opacity-50" strokeWidth={2} />
<p class="text-lg font-medium">Nenhuma atividade registrada</p>
<p class="mt-1 text-sm">As atividades do sistema aparecerão aqui</p>
</div>
@@ -828,20 +691,7 @@
<tr class="hover transition-colors">
<td>
<div class="flex items-center gap-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/40 h-4 w-4"
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>
<Clock class="text-base-content/40 h-4 w-4" strokeWidth={2} />
<span class="font-mono text-xs">{formatarData(atividade.timestamp)}</span>
</div>
</td>
@@ -892,20 +742,7 @@
<div class="card-body">
<div class="mb-4 flex items-center justify-between">
<h2 class="card-title text-xl">
<svg
xmlns="http://www.w3.org/2000/svg"
class="mr-2 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"
/>
</svg>
<LogIn class="mr-2 h-5 w-5" strokeWidth={2} />
Histórico de Logins
</h2>
{#if logins}
@@ -922,20 +759,7 @@
</div>
{:else if logins.length === 0}
<div class="text-base-content/60 flex flex-col items-center justify-center py-16">
<svg
xmlns="http://www.w3.org/2000/svg"
class="mb-4 h-16 w-16 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>
<LogIn class="mb-4 h-16 w-16 opacity-50" strokeWidth={2} />
<p class="text-lg font-medium">Nenhum login registrado</p>
<p class="mt-1 text-sm">Os acessos ao sistema aparecerão aqui</p>
</div>
@@ -959,20 +783,7 @@
<tr class="hover transition-colors">
<td>
<div class="flex items-center gap-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/40 h-4 w-4"
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>
<Clock class="text-base-content/40 h-4 w-4" strokeWidth={2} />
<span class="font-mono text-xs">{formatarData(login.timestamp)}</span>
</div>
</td>
@@ -980,39 +791,13 @@
<div class="flex flex-col gap-1">
{#if login.usuarioNome}
<div class="flex items-center gap-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/40 h-4 w-4"
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>
<User class="text-base-content/40 h-4 w-4" strokeWidth={2} />
<span class="text-sm font-semibold">{login.usuarioNome}</span>
</div>
{/if}
{#if login.usuarioEmail || login.matriculaOuEmail}
<div class="flex items-center gap-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/40 h-3 w-3"
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"
/>
</svg>
<Mail class="text-base-content/40 h-3 w-3" strokeWidth={2} />
<span class="text-base-content/70 font-mono text-xs">
{login.usuarioEmail ||
(login.matriculaOuEmail &&
@@ -1030,38 +815,12 @@
<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>
<CheckCircle class="h-3 w-3" strokeWidth={2} />
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>
<XCircle class="h-3 w-3" strokeWidth={2} />
Falhou
</span>
{#if login.motivoFalha}
@@ -1079,26 +838,7 @@
</td>
<td>
<div class="flex max-w-xs items-center gap-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/40 h-4 w-4 flex-shrink-0"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"
/>
</svg>
<MapPin class="text-base-content/40 h-4 w-4 flex-shrink-0" strokeWidth={2} />
<span
class="text-base-content/70 truncate text-xs"
title={formatarLocalizacao(login)}
@@ -1128,19 +868,7 @@
<!-- Informação -->
<div class="alert alert-info mt-6 shadow-lg">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="h-6 w-6 shrink-0 stroke-current"
>
<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>
<Info class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<div>
<h3 class="font-bold">Informação Importante</h3>
<div class="text-sm">

View File

@@ -2,6 +2,15 @@
import { useQuery, useConvexClient } from 'convex-svelte';
import { api } from '@sgse-app/backend/convex/_generated/api';
import type { Id } from '@sgse-app/backend/convex/_generated/dataModel';
import {
Video,
CheckCircle,
XCircle,
AlertTriangle,
Check,
Save,
Info
} from 'lucide-svelte';
const client = useConvexClient();
const currentUser = useQuery(api.auth.getCurrentUser, {});
@@ -141,20 +150,7 @@
<div class="mb-6 flex items-center justify-between">
<div class="flex items-center gap-4">
<div class="bg-primary/10 rounded-xl p-3">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"
/>
</svg>
<Video class="text-primary h-8 w-8" strokeWidth={2} />
</div>
<div>
<h1 class="text-base-content text-3xl font-bold">Configurações do Jitsi Meet</h1>
@@ -172,28 +168,11 @@
class:alert-success={mensagem.tipo === 'success'}
class:alert-error={mensagem.tipo === 'error'}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
{#if mensagem.tipo === 'success'}
<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"
/>
{:else}
<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"
/>
{/if}
</svg>
{#if mensagem.tipo === 'success'}
<CheckCircle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
{:else}
<XCircle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
{/if}
<div class="flex-1">
<span>{mensagem.texto}</span>
{#if mensagem.detalhes}
@@ -218,28 +197,11 @@
<!-- Status -->
{#if !isLoading}
<div class="alert {configAtual?.data?.ativo ? 'alert-success' : 'alert-warning'} mb-6">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="h-6 w-6 shrink-0 stroke-current"
>
{#if configAtual?.data?.ativo}
<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"
/>
{:else}
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
/>
{/if}
</svg>
{#if configAtual?.data?.ativo}
<CheckCircle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
{:else}
<AlertTriangle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
{/if}
<span>
<strong>Status:</strong>
{statusConfig}
@@ -357,20 +319,7 @@
{#if testando}
<span class="loading loading-spinner loading-sm"></span>
{:else}
<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 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<CheckCircle class="h-5 w-5" strokeWidth={2} />
{/if}
Testar Conexão
</button>
@@ -383,20 +332,7 @@
{#if processando}
<span class="loading loading-spinner loading-sm"></span>
{:else}
<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="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4"
/>
</svg>
<Save class="h-5 w-5" strokeWidth={2} />
{/if}
Salvar Configuração
</button>
@@ -451,19 +387,7 @@
<!-- Avisos -->
<div class="alert alert-info mt-6">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="h-6 w-6 shrink-0 stroke-current"
>
<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>
<Info class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<div>
<p>
<strong>Dica:</strong> Para servidor Jitsi Docker local, use
@@ -480,19 +404,7 @@
<!-- Aviso sobre Certificados Autoassinados -->
{#if acceptSelfSignedCert}
<div class="alert alert-warning mt-4">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="h-6 w-6 shrink-0 stroke-current"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
></path>
</svg>
<AlertTriangle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<div>
<p class="font-bold">Certificados Autoassinados Ativados</p>
<p class="mt-1 text-sm">
@@ -507,19 +419,7 @@
<!-- Aviso sobre HTTP -->
{#if !useHttps}
<div class="alert alert-error mt-4">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="h-6 w-6 shrink-0 stroke-current"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
></path>
</svg>
<AlertTriangle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<div>
<p class="font-bold">HTTP Ativado (Não Seguro)</p>
<p class="mt-1 text-sm">

View File

@@ -1,6 +1,7 @@
<script lang="ts">
import { resolve } from '$app/paths';
import SystemMonitorCardLocal from '$lib/components/ti/SystemMonitorCardLocal.svelte';
import { Monitor, ArrowLeft } from 'lucide-svelte';
</script>
<div class="container mx-auto max-w-7xl px-4 py-6">
@@ -8,20 +9,7 @@
<div class="mb-8 flex items-center justify-between">
<div class="flex items-center gap-4">
<div class="from-primary/20 to-primary/10 rounded-2xl bg-linear-to-br p-3">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary h-10 w-10"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"
/>
</svg>
<Monitor class="text-primary h-10 w-10" strokeWidth={2} />
</div>
<div>
<h1 class="text-primary text-4xl font-bold">
@@ -33,20 +21,7 @@
</div>
</div>
<a href={resolve('/ti')} class="btn">
<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>
<ArrowLeft class="h-5 w-5" strokeWidth={2} />
Voltar
</a>
</div>

View File

@@ -5,6 +5,26 @@
import { format } from 'date-fns';
import { ptBR } from 'date-fns/locale';
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
import {
Bell,
CheckCircle,
XCircle,
Info,
Mail,
Send,
MessageSquare,
Calendar,
Clock,
X,
User,
FileText,
Trash2,
Edit,
MoreVertical,
Plus,
AlertTriangle,
Check
} from 'lucide-svelte';
type StatusAgendamento = 'agendado' | 'enviado' | 'cancelado';
@@ -1166,20 +1186,7 @@
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div class="flex items-center gap-4">
<div class="from-primary/15 via-info/10 to-secondary/10 rounded-2xl bg-gradient-to-br p-3">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary h-9 w-9"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
/>
</svg>
<Bell class="text-primary h-9 w-9" strokeWidth={2} />
</div>
<div>
<h1 class="text-base-content text-3xl font-bold">Notificações e Mensagens</h1>
@@ -1213,42 +1220,20 @@
class:alert-error={mensagem.tipo === 'error'}
class:alert-info={mensagem.tipo === 'info'}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
{#if mensagem.tipo === 'success'}
<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"
/>
{:else if mensagem.tipo === 'error'}
<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"
/>
{:else}
<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"
/>
{/if}
</svg>
{#if mensagem.tipo === 'success'}
<CheckCircle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
{:else if mensagem.tipo === 'error'}
<XCircle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
{:else}
<Info class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
{/if}
<span class="font-medium">{mensagem.texto}</span>
<button
type="button"
class="btn btn-sm btn-circle btn-ghost"
onclick={() => (mensagem = null)}
>
<X class="h-4 w-4" strokeWidth={2} />
</button>
</div>
{/if}
@@ -1417,19 +1402,7 @@
{#if templateSelecionado}
<div class="alert alert-info mb-4">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="h-6 w-6 shrink-0 stroke-current"
>
<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>
<Info class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<div>
<div class="font-bold">{templateSelecionado.titulo}</div>
<div class="mt-1 text-sm">{templateSelecionado.corpo}</div>
@@ -1496,19 +1469,7 @@
{#if getPreviewAgendamento()}
<div class="alert alert-info mt-4">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="h-6 w-6 shrink-0 stroke-current"
>
<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>
<Info class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<span>{getPreviewAgendamento()}</span>
</div>
{/if}
@@ -1532,20 +1493,7 @@
<span class="ml-2">Enviando...</span>
{/if}
{:else}
<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 19l9 2-9-18-9 18 9-2zm0 0v-8"
/>
</svg>
<Send class="h-5 w-5" strokeWidth={2} />
{/if}
{#if processando}
<!-- Texto já está no bloco acima -->
@@ -1569,20 +1517,7 @@
</div>
{#if logsEnvio.length > 0}
<button type="button" class="btn btn-sm btn-ghost" onclick={limparLogs}>
<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="M6 18L18 6M6 6l12 12"
/>
</svg>
<X class="h-4 w-4" strokeWidth={2} />
Limpar
</button>
{/if}
@@ -1630,20 +1565,7 @@
class="btn btn-sm btn-outline btn-primary"
onclick={() => abrirModalNovoTemplate()}
>
<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="M12 4v16m8-8H4"
/>
</svg>
<Plus class="h-4 w-4" strokeWidth={2} />
Novo Template
</button>
</div>
@@ -1687,20 +1609,7 @@
class="btn btn-xs"
aria-label="Opções do template"
>
<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="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z"
/>
</svg>
<MoreVertical class="h-4 w-4" strokeWidth={2} />
</button>
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
<ul
@@ -1722,20 +1631,7 @@
{:else}
<!-- Nenhum template disponível - mostrar botão para criar -->
<div class="py-10 text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="mx-auto mb-4 h-12 w-12 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>
<FileText class="mx-auto mb-4 h-12 w-12 opacity-50" strokeWidth={2} />
<p class="text-base-content mb-2 font-medium">Nenhum template disponível</p>
<p class="text-base-content/60 mb-4 text-sm">
Clique no botão abaixo para criar os templates padrão do sistema.
@@ -1749,20 +1645,7 @@
<span class="loading loading-spinner loading-xs"></span>
Criando templates...
{:else}
<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="M12 4v16m8-8H4"
/>
</svg>
<Plus class="h-4 w-4" strokeWidth={2} />
Criar Templates Padrão
{/if}
</button>
@@ -1797,20 +1680,7 @@
<div class="mb-4 flex items-center justify-between">
<div class="flex items-center gap-3">
<div class="bg-secondary/10 rounded-lg p-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-secondary h-6 w-6"
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>
<Clock class="text-secondary h-6 w-6" strokeWidth={2} />
</div>
<h2 class="card-title">Histórico de Agendamentos</h2>
</div>
@@ -1843,20 +1713,7 @@
{#if agendamentosFiltrados.length === 0}
<div class="py-10 text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="mx-auto mb-4 h-12 w-12 opacity-50"
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>
<Clock class="mx-auto mb-4 h-12 w-12 opacity-50" strokeWidth={2} />
<p class="text-base-content mb-2 font-medium">Nenhum agendamento encontrado</p>
<p class="text-base-content/60 text-sm">
Os agendamentos aparecerão aqui quando você agendar envios.
@@ -1886,36 +1743,10 @@
<td>
<div class="flex items-center gap-2">
{#if agendamento.tipo === 'email'}
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-info h-5 w-5"
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"
/>
</svg>
<Mail class="text-info h-5 w-5" strokeWidth={2} />
<span class="badge badge-info badge-sm">Email</span>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
/>
</svg>
<MessageSquare class="text-primary h-5 w-5" strokeWidth={2} />
<span class="badge badge-primary badge-sm">Chat</span>
{/if}
</div>
@@ -1981,20 +1812,7 @@
class="btn btn-sm btn-error btn-outline"
onclick={() => cancelarAgendamento(agendamento)}
>
<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="M6 18L18 6M6 6l12 12"
/>
</svg>
<X class="h-4 w-4" strokeWidth={2} />
Cancelar
</button>
{:else}
@@ -2013,19 +1831,7 @@
<!-- Info -->
<div class="alert alert-warning mt-6">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="h-6 w-6 shrink-0 stroke-current"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
></path>
</svg>
<AlertTriangle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<span>Para enviar emails, certifique-se de configurar o SMTP em Configurações de Email.</span>
</div>
</div>
@@ -2147,20 +1953,7 @@
<span class="loading loading-spinner loading-sm"></span>
Criando...
{:else}
<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"
/>
</svg>
<Check class="h-5 w-5" strokeWidth={2} />
Criar Template
{/if}
</button>

View File

@@ -7,7 +7,21 @@
import type { Id } from '@sgse-app/backend/convex/_generated/dataModel';
import { format } from 'date-fns';
import { ptBR } from 'date-fns/locale';
import { Users, Shield, AlertTriangle, Info, Building2 } from 'lucide-svelte';
import {
Users,
Shield,
AlertTriangle,
Info,
Building2,
Filter,
X,
Search,
Smile,
Tag,
Eye,
Calendar,
Settings
} from 'lucide-svelte';
type Role = {
_id: Id<'roles'>;
@@ -144,20 +158,7 @@
<div class="mb-8 flex items-center justify-between">
<div class="flex items-center gap-4">
<div class="bg-primary/10 rounded-xl p-3">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary 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 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"
/>
</svg>
<Users class="text-primary h-8 w-8" strokeWidth={2} />
</div>
<div>
<h1 class="text-base-content text-3xl font-bold">Gestão de Perfis</h1>
@@ -216,20 +217,7 @@
<div class="card-body">
<div class="mb-4 flex flex-wrap items-center justify-between gap-4">
<div class="flex items-center gap-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary h-5 w-5"
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"
/>
</svg>
<Filter class="text-primary h-5 w-5" strokeWidth={2} />
<h2 class="card-title text-lg">Filtros de Busca</h2>
</div>
{#if temFiltrosAtivos}
@@ -238,20 +226,7 @@
class="btn btn-sm btn-outline btn-error"
onclick={limparFiltros}
>
<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="M6 18L18 6M6 6l12 12"
/>
</svg>
<X class="h-4 w-4" strokeWidth={2} />
Limpar Filtros
</button>
{/if}
@@ -271,20 +246,7 @@
placeholder="Buscar por nome ou descrição..."
class="input input-bordered w-full pl-10"
/>
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/40 absolute top-1/2 left-3 h-5 w-5 -translate-y-1/2 transform"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
<Search class="text-base-content/40 absolute top-1/2 left-3 h-5 w-5 -translate-y-1/2 transform" strokeWidth={2} />
</div>
</div>
@@ -338,20 +300,7 @@
</div>
{:else if roles.length === 0}
<div class="flex flex-col items-center justify-center py-16 text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/30 h-16 w-16"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"
/>
</svg>
<Users class="text-base-content/30 h-16 w-16" strokeWidth={2} />
<h3 class="mt-4 text-xl font-semibold">Nenhum perfil encontrado</h3>
<p class="text-base-content/60 mt-2">Não há perfis cadastrados no sistema.</p>
</div>
@@ -359,20 +308,7 @@
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<div class="flex flex-col items-center justify-center py-16 text-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/30 mb-4 h-16 w-16"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<Smile class="text-base-content/30 mb-4 h-16 w-16" strokeWidth={2} />
<h3 class="mt-4 text-xl font-semibold">Nenhum perfil encontrado</h3>
<p class="text-base-content/60 mt-2">
Nenhum perfil corresponde aos filtros aplicados.
@@ -403,79 +339,27 @@
</div>
</div>
<div class="bg-base-200 rounded-lg p-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary h-6 w-6"
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>
<User class="text-primary h-6 w-6" strokeWidth={2} />
</div>
</div>
<div class="space-y-3 text-sm">
<div class="bg-base-200 flex items-center gap-2 rounded-lg p-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/40 h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"
/>
</svg>
<Tag class="text-base-content/40 h-4 w-4" strokeWidth={2} />
<span class="text-base-content/60 font-medium">Nome técnico:</span>
<code class="bg-base-100 rounded px-2 py-1 font-mono text-xs">{role.nome}</code>
</div>
{#if role.setor}
<div class="bg-base-200 flex items-center gap-2 rounded-lg p-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/40 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 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"
/>
</svg>
<Building2 class="text-base-content/40 h-4 w-4" strokeWidth={2} />
<span class="text-base-content/60 font-medium">Setor:</span>
<span class="font-medium">{role.setor}</span>
</div>
{/if}
<div class="bg-base-200 flex items-center gap-2 rounded-lg p-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/40 h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
/>
</svg>
<Shield class="text-base-content/40 h-4 w-4" strokeWidth={2} />
<span class="text-base-content/60 font-medium">Nível:</span>
<span class="text-lg font-bold">{role.nivel}</span>
</div>
@@ -489,26 +373,7 @@
abrirDetalhes(role);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="mr-1 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>
<Eye class="mr-1 h-4 w-4" strokeWidth={2} />
Ver Detalhes
</button>
</div>
@@ -526,20 +391,7 @@
<div class="mb-6 flex items-center justify-between">
<h3 class="text-2xl font-bold">Detalhes do Perfil</h3>
<button type="button" class="btn btn-sm btn-circle btn-ghost" onclick={fecharDetalhes}>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
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>
<X class="h-6 w-6" strokeWidth={2} />
</button>
</div>
@@ -560,20 +412,7 @@
</div>
</div>
<div class="bg-base-100 rounded-lg p-3 shadow-sm">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary h-8 w-8"
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>
<User class="text-primary h-8 w-8" strokeWidth={2} />
</div>
</div>
</div>
@@ -585,20 +424,7 @@
<div class="card-body">
<label class="label">
<span class="label-text flex items-center gap-2 font-semibold">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"
/>
</svg>
<Tag class="text-primary h-5 w-5" strokeWidth={2} />
Nome Técnico
</span>
</label>
@@ -612,20 +438,7 @@
<div class="card-body">
<label class="label">
<span class="label-text flex items-center gap-2 font-semibold">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"
/>
</svg>
<Building2 class="text-primary h-5 w-5" strokeWidth={2} />
Setor
</span>
</label>
@@ -645,20 +458,7 @@
<div class="card-body">
<label class="label">
<span class="label-text flex items-center gap-2 font-semibold">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary 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 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
/>
</svg>
<Shield class="text-primary h-5 w-5" strokeWidth={2} />
Nível de Acesso
</span>
</label>
@@ -670,19 +470,7 @@
</div>
</div>
<div class="alert alert-info">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="h-6 w-6 shrink-0 stroke-current"
>
<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>
<Info class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<span class="text-sm">
{roleSelecionada.nivel === 0 &&
'Acesso total irrestrito ao sistema. Pode realizar todas as operações sem restrições.'}
@@ -703,20 +491,7 @@
<div class="card-body">
<label class="label">
<span class="label-text flex items-center gap-2 font-semibold">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary h-5 w-5"
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>
<Calendar class="text-primary h-5 w-5" strokeWidth={2} />
Data de Criação
</span>
</label>
@@ -728,19 +503,7 @@
<!-- Informação sobre Permissões -->
<div class="alert alert-info">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="h-6 w-6 shrink-0 stroke-current"
>
<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>
<Info class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<div>
<h4 class="mb-1 font-semibold">Configuração de Permissões</h4>
<p class="text-sm">
@@ -756,26 +519,7 @@
<div class="modal-action mt-6">
<button type="button" class="btn" onclick={fecharDetalhes}> Fechar </button>
<a href={resolve('/ti/painel-permissoes')} class="btn btn-primary">
<svg
xmlns="http://www.w3.org/2000/svg"
class="mr-2 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.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
</svg>
<Settings class="mr-2 h-5 w-5" strokeWidth={2} />
Configurar Permissões
</a>
</div>

View File

@@ -2,6 +2,7 @@
import ProtectedRoute from '$lib/components/ProtectedRoute.svelte';
import { goto } from '$app/navigation';
import { resolve } from '$app/paths';
import { Home, User, ArrowLeft, Info } from 'lucide-svelte';
</script>
<ProtectedRoute allowedRoles={['ti_master', 'admin']} maxLevel={1}>
@@ -10,20 +11,7 @@
<ul>
<li>
<a href={resolve('/')} class="text-primary hover:text-primary-focus">
<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 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
/>
</svg>
<Home class="h-4 w-4" strokeWidth={2} />
Dashboard
</a>
</li>
@@ -38,20 +26,7 @@
<div class="mb-6">
<div class="mb-2 flex items-center gap-3">
<div class="bg-info/10 rounded-xl p-3">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-info h-8 w-8"
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>
<User class="text-info h-8 w-8" strokeWidth={2} />
</div>
<div class="flex-1">
<h1 class="text-base-content text-3xl font-bold">Funcionalidade descontinuada</h1>
@@ -60,38 +35,13 @@
</p>
</div>
<button class="btn gap-2" onclick={() => goto(resolve('/ti'))}>
<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>
<ArrowLeft class="h-5 w-5" strokeWidth={2} />
Voltar
</button>
</div>
</div>
<div class="alert alert-info shadow-lg">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<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"
/>
</svg>
<Info class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<span>
A personalização por usuário foi substituída por <strong>permissões por ação</strong>
por perfil. Utilize o