feat: replace SVG icons with Lucide components in user management and dashboard pages for improved consistency and maintainability

This commit is contained in:
2025-12-05 04:44:43 -03:00
parent 7621fbea36
commit 6e659514e3
5 changed files with 118 additions and 807 deletions

View File

@@ -1,13 +1,13 @@
<script lang="ts">
import { resolve } from '$app/paths';
import WidgetGestaoPontos from '$lib/components/ponto/WidgetGestaoPontos.svelte';
import { Clock, ChevronRight, Info } from 'lucide-svelte';
const menuItems = [
{
categoria: 'Gestão de Ausências',
descricao: 'Gerencie solicitações de ausências e aprovações',
icon: `<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12" 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>`,
iconComponent: Clock,
gradient: 'from-orange-500/10 to-orange-600/20',
accentColor: 'text-orange-600',
bgIcon: 'bg-orange-500/20',
@@ -16,9 +16,7 @@
nome: 'Gestão de Ausências',
descricao: 'Visualizar e gerenciar solicitações de ausências',
href: '/gestao-pessoas/gestao-ausencias',
icon: `<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 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>`
iconComponent: Clock
}
]
}
@@ -48,9 +46,11 @@
<!-- Cabeçalho da Categoria -->
<div class="mb-6 flex items-start gap-6">
<div class="p-4 {categoria.bgIcon} rounded-2xl">
<div class={categoria.accentColor}>
{@html categoria.icon}
</div>
<svelte:component
this={categoria.iconComponent}
class="h-12 w-12 {categoria.accentColor}"
strokeWidth={2}
/>
</div>
<div class="flex-1">
<h2 class="card-title mb-2 text-2xl {categoria.accentColor}">
@@ -72,24 +72,16 @@
<div
class="bg-base-100 group-hover:bg-primary rounded-lg p-3 transition-colors duration-300 group-hover:text-white"
>
<div class="{categoria.accentColor} group-hover:text-white">
{@html opcao.icon}
</div>
</div>
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/30 group-hover:text-primary h-5 w-5 transition-colors duration-300"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 5l7 7-7 7"
<svelte:component
this={opcao.iconComponent}
class="h-5 w-5 {categoria.accentColor} group-hover:text-white"
strokeWidth={2}
/>
</svg>
</div>
<ChevronRight
class="text-base-content/30 group-hover:text-primary h-5 w-5 transition-colors duration-300"
strokeWidth={2}
/>
</div>
<h3
class="text-base-content group-hover:text-primary mb-2 text-lg font-bold transition-colors duration-300"
@@ -115,19 +107,7 @@
<!-- Card de Ajuda -->
<div class="alert alert-info mt-8 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">Precisa de ajuda?</h3>
<div class="text-sm">

View File

@@ -33,7 +33,11 @@
Fingerprint,
Palette,
Camera,
Users as UsersIcon
Users as UsersIcon,
FileText,
Building,
XCircle,
Smile
} from 'lucide-svelte';
import RegistroPonto from '$lib/components/ponto/RegistroPonto.svelte';
import TicketCard from '$lib/components/chamados/TicketCard.svelte';
@@ -551,9 +555,7 @@
toast.className = 'toast toast-top toast-end';
toast.innerHTML = `
<div class="alert alert-success">
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
<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="stroke-current shrink-0 h-6 w-6" strokeWidth={2} />
<span>Foto de perfil atualizada com sucesso!</span>
</div>
`;
@@ -716,20 +718,7 @@
class="badge badge-lg border-0 bg-white/80 px-4 font-semibold shadow-lg"
style="color: {meuTime.cor}"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="mr-2 h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
/>
</svg>
<Users class="mr-2 h-4 w-4" strokeWidth={2} />
{meuTime.nome}
</div>
{/if}
@@ -929,20 +918,7 @@
{funcionario?.matricula || '---'}
</p>
</div>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-12 w-12 opacity-80"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 6H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V8a2 2 0 00-2-2h-5m-4 0V5a2 2 0 114 0v1m-4 0a2 2 0 104 0m-5 8a2 2 0 100-4 2 2 0 000 4zm0 0c1.306 0 2.417.835 2.83 2M9 14a3.001 3.001 0 00-2.83 2M15 11h3m-3 4h2"
/>
</svg>
<Briefcase class="h-12 w-12 opacity-80" strokeWidth={2} />
</div>
</div>
</div>
@@ -1196,20 +1172,7 @@
>
<div class="card-body">
<h2 class="card-title text-warning mb-6 flex items-center gap-2 text-2xl">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-7 w-7"
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>
<Building class="h-7 w-7" strokeWidth={2} />
Times que Você Gerencia
<div class="badge badge-warning badge-lg ml-2">
{meusTimesGestor.length}
@@ -1218,19 +1181,7 @@
{#if meusTimesGestor.length === 0}
<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>Você não gerencia nenhum time no momento.</span>
</div>
{:else}
@@ -1256,20 +1207,7 @@
<div class="flex items-center justify-between">
<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="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-5 w-5" strokeWidth={2} />
<span class="text-lg font-bold">{time.membros?.length || 0}</span>
<span class="text-base-content/70 text-sm">membros</span>
</div>
@@ -1529,20 +1467,7 @@
<div class="grid grid-cols-1 gap-4 md:grid-cols-5">
<div class="stat bg-base-100 rounded-box border-base-300 border 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 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" strokeWidth={2} />
</div>
<div class="stat-title">Total</div>
<div class="stat-value text-primary">{statsMinhasFerias.total}</div>
@@ -1551,20 +1476,7 @@
<div class="stat bg-base-100 rounded-box border-warning/30 border shadow-lg">
<div class="stat-figure text-warning">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<Clock class="h-8 w-8" strokeWidth={2} />
</div>
<div class="stat-title">Aguardando</div>
<div class="stat-value text-warning">
@@ -1575,20 +1487,7 @@
<div class="stat bg-base-100 rounded-box border-success/30 border shadow-lg">
<div class="stat-figure text-success">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<CheckCircle class="h-8 w-8" strokeWidth={2} />
</div>
<div class="stat-title">Aprovadas</div>
<div class="stat-value text-success">
@@ -1599,20 +1498,7 @@
<div class="stat bg-base-100 rounded-box border-error/30 border shadow-lg">
<div class="stat-figure text-error">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<XCircle class="h-8 w-8" strokeWidth={2} />
</div>
<div class="stat-title">Reprovadas</div>
<div class="stat-value text-error">
@@ -1668,20 +1554,7 @@
? 'Clique para agendar suas férias'
: 'Estamos validando seus dados de funcionário...'}
>
<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 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="h-5 w-5" strokeWidth={2} />
Agendar Férias
</button>
</div>
@@ -1828,20 +1701,7 @@
<div class="stat bg-base-100 rounded-box border-warning/30 border shadow-lg">
<div class="stat-figure text-warning">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<Clock class="h-8 w-8" strokeWidth={2} />
</div>
<div class="stat-title">Aguardando</div>
<div class="stat-value text-warning">
@@ -1852,20 +1712,7 @@
<div class="stat bg-base-100 rounded-box border-success/30 border shadow-lg">
<div class="stat-figure text-success">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<CheckCircle class="h-8 w-8" strokeWidth={2} />
</div>
<div class="stat-title">Aprovadas</div>
<div class="stat-value text-success">
@@ -1876,20 +1723,7 @@
<div class="stat bg-base-100 rounded-box border-error/30 border shadow-lg">
<div class="stat-figure text-error">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<XCircle class="h-8 w-8" strokeWidth={2} />
</div>
<div class="stat-title">Reprovadas</div>
<div class="stat-value text-error">
@@ -1903,20 +1737,7 @@
<div class="card bg-base-100 shadow-lg">
<div class="card-body">
<h2 class="card-title mb-4 text-lg">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 text-warning"
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="h-6 w-6 text-warning" strokeWidth={2} />
Calendário de Ausências
</h2>
<p class="text-base-content/70 mb-4 text-sm">
@@ -1978,20 +1799,7 @@
? 'Clique para solicitar uma ausência'
: 'Funcionário não identificado. Entre em contato com o suporte.'}
>
<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 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<Clock class="h-5 w-5" strokeWidth={2} />
Solicitar Ausência
</button>
</div>
@@ -2024,15 +1832,7 @@
{#if ausenciasFiltradas.length === 0}
<div class="alert">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="stroke-info h-6 w-6 shrink-0"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
<Info class="stroke-info h-6 w-6 shrink-0" strokeWidth={2} />
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
></path>

View File

@@ -5,6 +5,17 @@
import { goto } from '$app/navigation';
import { resolve } from '$app/paths';
import type { Id } from '@sgse-app/backend/convex/_generated/dataModel';
import {
Home,
ShieldCheck,
Plus,
ArrowLeft,
CheckCircle,
XCircle,
Search,
X,
ChevronDown
} from 'lucide-svelte';
const client = useConvexClient();
@@ -216,20 +227,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>
@@ -244,20 +242,7 @@
<div class="mb-6">
<div class="mb-2 flex flex-wrap items-center gap-3">
<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="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>
<ShieldCheck class="text-primary h-8 w-8" strokeWidth={2} />
</div>
<div class="flex-1">
<h1 class="text-base-content text-3xl font-bold">
@@ -268,37 +253,11 @@
</p>
</div>
<button class="btn btn-primary gap-2" onclick={abrirModalNovoPerfil}>
<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"
/>
</svg>
<Plus class="h-5 w-5" strokeWidth={2} />
Criar novo perfil
</button>
<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>
@@ -312,33 +271,9 @@
class:alert-error={mensagem.tipo === 'error'}
>
{#if mensagem.tipo === 'success'}
<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="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<CheckCircle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
{:else}
<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="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-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
{/if}
<span class="font-semibold">{mensagem.texto}</span>
</div>
@@ -361,20 +296,7 @@
class="input input-bordered w-full pr-10"
bind:value={busca}
/>
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/40 absolute top-3.5 right-3 h-5 w-5"
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-3.5 right-3 h-5 w-5" strokeWidth={2} />
</div>
</div>
@@ -431,39 +353,14 @@
</div>
{:else if rolesQuery.error}
<div class="alert alert-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"
>
<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-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<span>Erro ao carregar perfis: {rolesQuery.error.message}</span>
</div>
{:else if rolesQuery.data && catalogoQuery.data}
{#if rolesFiltradas.length === 0}
<div class="card bg-base-100 shadow-xl">
<div class="card-body items-center 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="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
<Search class="text-base-content/30 h-16 w-16" strokeWidth={2} />
<h3 class="mt-4 text-xl font-bold">Nenhum resultado encontrado</h3>
<p class="text-base-content/60">
{busca
@@ -496,20 +393,7 @@
</div>
{#if roleRow.nivel <= 1}
<div class="badge badge-lg badge-success gap-1">
<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="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<CheckCircle class="h-4 w-4" strokeWidth={2} />
Acesso Total
</div>
{/if}
@@ -522,19 +406,7 @@
{#if roleRow.nivel <= 1}
<div class="alert alert-success shadow-md">
<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="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<CheckCircle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<div>
<h3 class="font-bold">Perfil Administrativo</h3>
<div class="text-sm">
@@ -556,21 +428,11 @@
disabled={salvando}
>
<span class="text-lg font-semibold">{item.recurso}</span>
<svg
xmlns="http://www.w3.org/2000/svg"
<ChevronDown
class="h-5 w-5 transition-transform"
class:rotate-180={recursoExpandido}
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 9l-7 7-7-7"
/>
</svg>
strokeWidth={2}
/>
</button>
<!-- Lista de ações (visível quando expandido) -->

View File

@@ -5,6 +5,17 @@
import { goto } from '$app/navigation';
import { resolve } from '$app/paths';
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
import {
Users,
ArrowLeft,
Plus,
MoreVertical,
Edit,
Trash2,
UserPlus,
X,
Info
} from 'lucide-svelte';
// Tipos baseados nos retornos das queries do backend
type Usuario = {
@@ -295,20 +306,7 @@
<div class="flex items-center justify-between">
<div class="flex items-center gap-4">
<div class="bg-secondary/10 rounded-xl p-3">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-secondary h-8 w-8"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
/>
</svg>
<Users class="text-secondary h-8 w-8" strokeWidth={2} />
</div>
<div>
<h1 class="text-base-content text-3xl font-bold">Gestão de Times</h1>
@@ -319,37 +317,11 @@
</div>
<div class="flex gap-2">
<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>
<button class="btn btn-primary gap-2" onclick={novoTime}>
<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"
/>
</svg>
<Plus class="h-5 w-5" strokeWidth={2} />
Novo Time
</button>
</div>
@@ -456,20 +428,7 @@
</div>
<div class="dropdown dropdown-end">
<button type="button" class="btn btn-sm" aria-label="Menu do time">
<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 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-5 w-5" strokeWidth={2} />
</button>
<ul
role="menu"
@@ -477,39 +436,13 @@
>
<li>
<button type="button" onclick={() => editarTime(time)}>
<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"
/>
</svg>
<Edit class="h-4 w-4" strokeWidth={2} />
Editar
</button>
</li>
<li>
<button type="button" onclick={() => abrirGerenciarMembros(time)}>
<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 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="h-4 w-4" strokeWidth={2} />
Gerenciar Membros
</button>
</li>
@@ -519,20 +452,7 @@
onclick={() => confirmarExclusao(time)}
class="text-error"
>
<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"
/>
</svg>
<Trash2 class="h-4 w-4" strokeWidth={2} />
Desativar
</button>
</li>
@@ -548,40 +468,14 @@
<div class="space-y-2">
<div class="flex items-center gap-2 text-sm">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5.121 17.804A13.937 13.937 0 0112 16c2.5 0 4.847.655 6.879 1.804M15 10a3 3 0 11-6 0 3 3 0 016 0zm6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<UserPlus class="text-primary h-4 w-4" strokeWidth={2} />
<span class="text-base-content/70"
><strong>Gestor:</strong>
{time.gestor?.nome || 'Não definido'}</span
>
</div>
<div class="flex items-center gap-2 text-sm">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-primary 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 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-4 w-4" strokeWidth={2} />
<span class="text-base-content/70"
><strong>Membros:</strong>
<span class="badge badge-primary badge-sm">{time.totalMembros || 0}</span></span
@@ -604,20 +498,7 @@
{#if times.filter((t: TimeComDetalhes) => t.ativo).length === 0}
<div class="col-span-full">
<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="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
/>
</svg>
<Users class="text-base-content/30 h-16 w-16" strokeWidth={2} />
<h3 class="mt-4 text-xl font-semibold">Nenhum time cadastrado</h3>
<p class="text-base-content/60 mt-2">
Clique em "Novo Time" para criar seu primeiro time
@@ -670,39 +551,14 @@
disabled={processando}
aria-label="Remover membro"
>
<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} />
</button>
</div>
{/each}
</div>
{:else}
<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>Nenhum membro neste time ainda.</span>
</div>
{/if}
@@ -747,19 +603,7 @@
</div>
{:else}
<div class="alert">
<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>Todos os funcionários já estão em times.</span>
</div>
{/if}

View File

@@ -7,6 +7,19 @@
import UserStatusBadge from '$lib/components/ti/UserStatusBadge.svelte';
import { format } from 'date-fns';
import { ptBR } from 'date-fns/locale';
import {
Users,
Plus,
AlertTriangle,
CheckCircle,
XCircle,
Info,
X,
Check,
UserPlus,
Search,
MoreVertical
} from 'lucide-svelte';
type AvisoUsuario = {
tipo: 'erro' | 'aviso' | 'info';
@@ -541,20 +554,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="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 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 Usuários</h1>
@@ -563,20 +563,7 @@
</div>
<div class="flex gap-3">
<a href={resolve('/ti/usuarios/criar')} class="btn btn-primary">
<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"
/>
</svg>
<Plus class="h-5 w-5" strokeWidth={2} />
Criar Usuário
</a>
</div>
@@ -585,19 +572,7 @@
<!-- Alerta de Usuários com Problemas -->
{#if !carregandoUsuarios && usuariosComProblemas.length > 0}
<div class="alert alert-warning mb-6 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="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"
/>
</svg>
<AlertTriangle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<div>
<h3 class="font-bold">Atenção: Usuários com Problemas Detectados</h3>
<div class="mt-2 text-sm">
@@ -636,47 +611,11 @@
class:alert-info={mensagem.tipo === 'info'}
>
{#if mensagem.tipo === 'success'}
<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="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<CheckCircle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
{:else if 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"
>
<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-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
{:else}
<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} />
{/if}
<span class="font-semibold">{mensagem.texto}</span>
</div>
@@ -689,20 +628,7 @@
<div class="mb-4 flex items-center justify-between">
<h2 class="card-title">Filtros de Busca</h2>
<button type="button" class="btn btn-sm btn-outline" 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>
</div>
@@ -838,19 +764,7 @@
</div>
{:else if erroUsuarios}
<div class="alert alert-error 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="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-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<div>
<h3 class="font-bold">Erro ao carregar usuários</h3>
<div class="mt-1 text-sm">{erroUsuarios}</div>
@@ -862,20 +776,7 @@
</div>
{:else if usuarios.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="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
/>
</svg>
<Users class="text-base-content/30 h-16 w-16" strokeWidth={2} />
<h3 class="mt-4 text-xl font-semibold">Nenhum usuário encontrado</h3>
<p class="text-base-content/60 mt-2">
Cadastre um usuário para começar a gestão de acessos.
@@ -913,20 +814,7 @@
<div class="space-y-1">
{#if usuario.role.erro}
<div class="badge badge-error 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="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<AlertTriangle class="h-3 w-3" strokeWidth={2} />
{usuario.role.descricao}
</div>
{#if usuario.avisos && usuario.avisos.length > 0}
@@ -958,20 +846,7 @@
{#if usuario.funcionario}
<div class="space-y-1">
<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"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5 13l4 4L19 7"
/>
</svg>
<Check class="h-3 w-3" strokeWidth={2} />
Associado
</div>
<div class="text-sm font-medium">
@@ -985,20 +860,7 @@
</div>
{:else}
<div class="badge badge-warning gap-2">
<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="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"
/>
</svg>
<AlertTriangle class="h-3 w-3" strokeWidth={2} />
Não associado
</div>
{/if}
@@ -1026,20 +888,7 @@
class="btn btn-sm btn-ghost"
aria-label="Menu de ações"
>
<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 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-5 w-5" strokeWidth={2} />
</button>
<ul
role="menu"
@@ -1122,19 +971,7 @@
{#if usuarioSelecionado.funcionario}
<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>
Este usuário já possui um funcionário associado. Você pode alterá-lo ou
desassociá-lo.
@@ -1261,19 +1098,7 @@
{usuarioSelecionado.nome} ({usuarioSelecionado.matricula})
</p>
<div class="alert alert-error">
<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="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
></path>
</svg>
<XCircle class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
<span>
Esta ação não pode ser desfeita. O usuário será permanentemente excluído do sistema.
</span>