feat: update ESLint and TypeScript configurations across frontend and backend; enhance component structure and improve data handling in various modules

This commit is contained in:
2025-12-02 16:36:02 -03:00
parent f48d28067c
commit d79e6959c3
215 changed files with 29474 additions and 28173 deletions

View File

@@ -1,170 +1,170 @@
<script lang="ts">
import { FileText, ClipboardCopy, Building2, Workflow, ChevronRight } from 'lucide-svelte';
import { resolve } from '$app/paths';
import ProtectedRoute from '$lib/components/ProtectedRoute.svelte';
import type { Component } from 'svelte';
</script>
<ProtectedRoute>
<main class="container mx-auto px-4 py-4">
<!-- Breadcrumb -->
<div class="breadcrumbs mb-4 text-sm">
<ul>
<li>
<a href={resolve('/')} class="text-primary hover:underline">Dashboard</a>
</li>
<li>Licitações</li>
</ul>
</div>
<!-- Cabeçalho -->
<div class="mb-8">
<h1 class="text-4xl font-bold text-primary mb-2">Licitações</h1>
<p class="text-lg text-base-content/70">
Gerencie empresas, contratos e processos licitatórios
</p>
</div>
<!-- Cards Principais -->
<div class="grid gap-4 md:grid-cols-3 mb-8">
<a
href={resolve('/licitacoes/empresas')}
class="card bg-base-100 border-base-200 hover:border-primary border shadow-md transition-shadow hover:shadow-lg"
>
<div class="card-body">
<div class="mb-2 flex items-center gap-3">
<div class="bg-primary/10 rounded-lg p-2">
<Building2 class="text-primary h-6 w-6" strokeWidth={2} />
</div>
<h4 class="font-semibold">Empresas</h4>
</div>
<p class="text-base-content/70 text-sm">
Cadastro, listagem e edição de empresas e seus contatos.
</p>
</div>
</a>
<a
href={resolve('/licitacoes/contratos')}
class="card bg-base-100 border-base-200 hover:border-primary border shadow-md transition-shadow hover:shadow-lg"
>
<div class="card-body">
<div class="mb-2 flex items-center gap-3">
<div class="bg-primary/10 rounded-lg p-2">
<FileText class="text-primary h-6 w-6" strokeWidth={2} />
</div>
<h4 class="font-semibold">Contratos</h4>
</div>
<p class="text-base-content/70 text-sm">Gestão de contratos, vigências e situações.</p>
</div>
</a>
<div class="card bg-base-100 opacity-70 shadow-md">
<div class="card-body">
<div class="mb-2 flex items-center gap-3">
<div class="bg-base-200 rounded-lg p-2">
<ClipboardCopy class="text-base-content/50 h-6 w-6" strokeWidth={2} />
</div>
<h4 class="text-base-content/70 font-semibold">Processos Licitatórios</h4>
</div>
<p class="text-base-content/60 text-sm">
Em breve: cadastro e acompanhamento de licitações.
</p>
</div>
</div>
<div class="card bg-base-100 opacity-70 shadow-md">
<div class="card-body">
<div class="mb-2 flex items-center gap-3">
<div class="bg-base-200 rounded-lg p-2">
<FileText class="text-base-content/50 h-6 w-6" strokeWidth={2} />
</div>
<h4 class="text-base-content/70 font-semibold">Documentação</h4>
</div>
<p class="text-base-content/60 text-sm">Em breve: gestão de documentos e editais.</p>
</div>
</div>
</div>
<!-- Seção Fluxos -->
<div class="card bg-base-100 shadow-xl hover:shadow-2xl transition-all duration-300">
<div class="card-body">
<!-- Cabeçalho da Categoria -->
<div class="flex items-start gap-6 mb-6">
<div class="p-4 bg-secondary/20 rounded-2xl">
<Workflow class="h-12 w-12 text-secondary" strokeWidth={2} />
</div>
<div class="flex-1">
<h2 class="card-title text-2xl mb-2 text-secondary">
Fluxos de Trabalho
</h2>
<p class="text-base-content/70">Gerencie templates e fluxos de trabalho para contratos e processos</p>
</div>
</div>
<!-- Grid de Opções -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<a
href={resolve('/licitacoes/fluxos')}
class="group relative overflow-hidden rounded-xl border-2 border-base-300 bg-linear-to-br from-secondary/10 to-secondary/20 p-6 hover:border-secondary hover:shadow-lg transition-all duration-300 transform hover:-translate-y-1"
>
<div class="flex flex-col h-full">
<div class="flex items-start justify-between mb-4">
<div
class="p-3 bg-base-100 rounded-lg group-hover:bg-secondary group-hover:text-white transition-colors duration-300"
>
<Workflow
class="h-5 w-5 text-secondary group-hover:text-white transition-colors duration-300"
strokeWidth={2}
/>
</div>
<ChevronRight
class="h-5 w-5 text-base-content/30 group-hover:text-secondary transition-colors duration-300"
strokeWidth={2}
/>
</div>
<h3
class="text-lg font-bold text-base-content mb-2 group-hover:text-secondary transition-colors duration-300"
>
Meus Fluxos
</h3>
<p class="text-sm text-base-content/70 flex-1">
Visualize e gerencie os fluxos de trabalho em execução
</p>
</div>
</a>
<a
href={resolve('/fluxos')}
class="group relative overflow-hidden rounded-xl border-2 border-base-300 bg-linear-to-br from-secondary/10 to-secondary/20 p-6 hover:border-secondary hover:shadow-lg transition-all duration-300 transform hover:-translate-y-1"
>
<div class="flex flex-col h-full">
<div class="flex items-start justify-between mb-4">
<div
class="p-3 bg-base-100 rounded-lg group-hover:bg-secondary group-hover:text-white transition-colors duration-300"
>
<FileText
class="h-5 w-5 text-secondary group-hover:text-white transition-colors duration-300"
strokeWidth={2}
/>
</div>
<ChevronRight
class="h-5 w-5 text-base-content/30 group-hover:text-secondary transition-colors duration-300"
strokeWidth={2}
/>
</div>
<h3
class="text-lg font-bold text-base-content mb-2 group-hover:text-secondary transition-colors duration-300"
>
Templates
</h3>
<p class="text-sm text-base-content/70 flex-1">
Crie e edite templates de fluxos de trabalho
</p>
</div>
</a>
</div>
</div>
</div>
</main>
</ProtectedRoute>
<script lang="ts">
import { FileText, ClipboardCopy, Building2, Workflow, ChevronRight } from 'lucide-svelte';
import { resolve } from '$app/paths';
import ProtectedRoute from '$lib/components/ProtectedRoute.svelte';
import type { Component } from 'svelte';
</script>
<ProtectedRoute>
<main class="container mx-auto px-4 py-4">
<!-- Breadcrumb -->
<div class="breadcrumbs mb-4 text-sm">
<ul>
<li>
<a href={resolve('/')} class="text-primary hover:underline">Dashboard</a>
</li>
<li>Licitações</li>
</ul>
</div>
<!-- Cabeçalho -->
<div class="mb-8">
<h1 class="text-primary mb-2 text-4xl font-bold">Licitações</h1>
<p class="text-base-content/70 text-lg">
Gerencie empresas, contratos e processos licitatórios
</p>
</div>
<!-- Cards Principais -->
<div class="mb-8 grid gap-4 md:grid-cols-3">
<a
href={resolve('/licitacoes/empresas')}
class="card bg-base-100 border-base-200 hover:border-primary border shadow-md transition-shadow hover:shadow-lg"
>
<div class="card-body">
<div class="mb-2 flex items-center gap-3">
<div class="bg-primary/10 rounded-lg p-2">
<Building2 class="text-primary h-6 w-6" strokeWidth={2} />
</div>
<h4 class="font-semibold">Empresas</h4>
</div>
<p class="text-base-content/70 text-sm">
Cadastro, listagem e edição de empresas e seus contatos.
</p>
</div>
</a>
<a
href={resolve('/licitacoes/contratos')}
class="card bg-base-100 border-base-200 hover:border-primary border shadow-md transition-shadow hover:shadow-lg"
>
<div class="card-body">
<div class="mb-2 flex items-center gap-3">
<div class="bg-primary/10 rounded-lg p-2">
<FileText class="text-primary h-6 w-6" strokeWidth={2} />
</div>
<h4 class="font-semibold">Contratos</h4>
</div>
<p class="text-base-content/70 text-sm">Gestão de contratos, vigências e situações.</p>
</div>
</a>
<div class="card bg-base-100 opacity-70 shadow-md">
<div class="card-body">
<div class="mb-2 flex items-center gap-3">
<div class="bg-base-200 rounded-lg p-2">
<ClipboardCopy class="text-base-content/50 h-6 w-6" strokeWidth={2} />
</div>
<h4 class="text-base-content/70 font-semibold">Processos Licitatórios</h4>
</div>
<p class="text-base-content/60 text-sm">
Em breve: cadastro e acompanhamento de licitações.
</p>
</div>
</div>
<div class="card bg-base-100 opacity-70 shadow-md">
<div class="card-body">
<div class="mb-2 flex items-center gap-3">
<div class="bg-base-200 rounded-lg p-2">
<FileText class="text-base-content/50 h-6 w-6" strokeWidth={2} />
</div>
<h4 class="text-base-content/70 font-semibold">Documentação</h4>
</div>
<p class="text-base-content/60 text-sm">Em breve: gestão de documentos e editais.</p>
</div>
</div>
</div>
<!-- Seção Fluxos -->
<div class="card bg-base-100 shadow-xl transition-all duration-300 hover:shadow-2xl">
<div class="card-body">
<!-- Cabeçalho da Categoria -->
<div class="mb-6 flex items-start gap-6">
<div class="bg-secondary/20 rounded-2xl p-4">
<Workflow class="text-secondary h-12 w-12" strokeWidth={2} />
</div>
<div class="flex-1">
<h2 class="card-title text-secondary mb-2 text-2xl">Fluxos de Trabalho</h2>
<p class="text-base-content/70">
Gerencie templates e fluxos de trabalho para contratos e processos
</p>
</div>
</div>
<!-- Grid de Opções -->
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
<a
href={resolve('/licitacoes/fluxos')}
class="group border-base-300 from-secondary/10 to-secondary/20 hover:border-secondary relative transform overflow-hidden rounded-xl border-2 bg-linear-to-br p-6 transition-all duration-300 hover:-translate-y-1 hover:shadow-lg"
>
<div class="flex h-full flex-col">
<div class="mb-4 flex items-start justify-between">
<div
class="bg-base-100 group-hover:bg-secondary rounded-lg p-3 transition-colors duration-300 group-hover:text-white"
>
<Workflow
class="text-secondary h-5 w-5 transition-colors duration-300 group-hover:text-white"
strokeWidth={2}
/>
</div>
<ChevronRight
class="text-base-content/30 group-hover:text-secondary h-5 w-5 transition-colors duration-300"
strokeWidth={2}
/>
</div>
<h3
class="text-base-content group-hover:text-secondary mb-2 text-lg font-bold transition-colors duration-300"
>
Meus Fluxos
</h3>
<p class="text-base-content/70 flex-1 text-sm">
Visualize e gerencie os fluxos de trabalho em execução
</p>
</div>
</a>
<a
href={resolve('/fluxos')}
class="group border-base-300 from-secondary/10 to-secondary/20 hover:border-secondary relative transform overflow-hidden rounded-xl border-2 bg-linear-to-br p-6 transition-all duration-300 hover:-translate-y-1 hover:shadow-lg"
>
<div class="flex h-full flex-col">
<div class="mb-4 flex items-start justify-between">
<div
class="bg-base-100 group-hover:bg-secondary rounded-lg p-3 transition-colors duration-300 group-hover:text-white"
>
<FileText
class="text-secondary h-5 w-5 transition-colors duration-300 group-hover:text-white"
strokeWidth={2}
/>
</div>
<ChevronRight
class="text-base-content/30 group-hover:text-secondary h-5 w-5 transition-colors duration-300"
strokeWidth={2}
/>
</div>
<h3
class="text-base-content group-hover:text-secondary mb-2 text-lg font-bold transition-colors duration-300"
>
Templates
</h3>
<p class="text-base-content/70 flex-1 text-sm">
Crie e edite templates de fluxos de trabalho
</p>
</div>
</a>
</div>
</div>
</div>
</main>
</ProtectedRoute>

View File

@@ -141,10 +141,7 @@
<div class="mx-auto flex max-w-4xl flex-col gap-6 p-6">
<div class="flex items-center gap-4">
<button
class="btn btn-ghost btn-square"
onclick={() => goto(resolve('/licitacoes/contratos'))}
>
<button class="btn btn-ghost btn-square" onclick={() => goto(resolve('/licitacoes/contratos'))}>
<ArrowLeft class="h-4 w-4" />
</button>
<div>
@@ -378,9 +375,8 @@
</div>
<div class="flex justify-end gap-4 pt-4">
<button
class="btn btn-outline"
onclick={() => goto(resolve('/licitacoes/contratos'))}>Cancelar</button
<button class="btn btn-outline" onclick={() => goto(resolve('/licitacoes/contratos'))}
>Cancelar</button
>
<button class="btn btn-primary" onclick={handleSubmit} disabled={loading}>
{#if loading}

View File

@@ -120,10 +120,7 @@
<div class="mx-auto flex max-w-4xl flex-col gap-6 p-6">
<div class="flex items-center gap-4">
<button
class="btn btn-ghost btn-square"
onclick={() => goto(resolve('/licitacoes/contratos'))}
>
<button class="btn btn-ghost btn-square" onclick={() => goto(resolve('/licitacoes/contratos'))}>
<ArrowLeft class="h-4 w-4" />
</button>
<div>
@@ -311,11 +308,7 @@
<label class="label" for="situacao">
<span class="label-text">Situação</span>
</label>
<select
id="situacao"
class="select select-bordered w-full"
bind:value={formData.situacao}
>
<select id="situacao" class="select select-bordered w-full" bind:value={formData.situacao}>
<option value="aguardando_assinatura">Aguardando Assinatura</option>
<option value="em_execucao">Em Execução</option>
<option value="rescendido">Rescindido</option>
@@ -348,9 +341,8 @@
</div>
<div class="flex justify-end gap-4 pt-4">
<button
class="btn btn-outline"
onclick={() => goto(resolve('/licitacoes/contratos'))}>Cancelar</button
<button class="btn btn-outline" onclick={() => goto(resolve('/licitacoes/contratos'))}
>Cancelar</button
>
<button class="btn btn-primary" onclick={handleSubmit} disabled={loading}>
{#if loading}

View File

@@ -11,9 +11,8 @@
let statusFilter = $state<'active' | 'completed' | 'cancelled' | undefined>(undefined);
// Query de instâncias
const instancesQuery = useQuery(
api.flows.listInstances,
() => (statusFilter ? { status: statusFilter } : {})
const instancesQuery = useQuery(api.flows.listInstances, () =>
statusFilter ? { status: statusFilter } : {}
);
// Query de templates publicados (para o modal de criação)
@@ -29,7 +28,7 @@
// Query de usuários (para seleção de gerente)
const usuariosQuery = useQuery(api.usuarios.listar, {});
// Query de contratos (para seleção)
const contratosQuery = useQuery(api.contratos.listar, {});
@@ -107,8 +106,20 @@
<div class="max-w-3xl space-y-4">
<div class="flex items-center gap-4">
<a href="/fluxos" class="btn btn-ghost btn-sm">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 19l-7-7m0 0l7-7m-7 7h18"
/>
</svg>
Templates
</a>
@@ -122,16 +133,13 @@
Fluxos de Trabalho
</h1>
<p class="text-base-content/70 text-base leading-relaxed sm:text-lg">
Acompanhe e gerencie os fluxos de trabalho. Visualize o progresso,
documentos e responsáveis de cada etapa.
Acompanhe e gerencie os fluxos de trabalho. Visualize o progresso, documentos e
responsáveis de cada etapa.
</p>
</div>
<div class="flex flex-col gap-4 sm:flex-row sm:items-center">
<!-- Filtro de status -->
<select
class="select select-bordered"
bind:value={statusFilter}
>
<select class="select select-bordered" bind:value={statusFilter}>
<option value={undefined}>Todos os status</option>
<option value="active">Em Andamento</option>
<option value="completed">Concluído</option>
@@ -187,7 +195,9 @@
</svg>
<h3 class="text-base-content/70 mt-4 text-lg font-semibold">Nenhum fluxo encontrado</h3>
<p class="text-base-content/50 mt-2">
{statusFilter ? 'Não há fluxos com este status.' : 'Clique em "Novo Fluxo" para iniciar um fluxo.'}
{statusFilter
? 'Não há fluxos com este status.'
: 'Clique em "Novo Fluxo" para iniciar um fluxo.'}
</p>
</div>
{:else}
@@ -207,7 +217,10 @@
<tbody>
{#each instancesQuery.data as instance (instance._id)}
{@const statusBadge = getStatusBadge(instance.status)}
{@const progressPercent = getProgressPercentage(instance.progress.completed, instance.progress.total)}
{@const progressPercent = getProgressPercentage(
instance.progress.completed,
instance.progress.total
)}
<tr class="hover">
<td>
<div class="font-medium">{instance.templateName ?? 'Template desconhecido'}</div>
@@ -222,12 +235,9 @@
<td class="text-base-content/70">{instance.managerName ?? '-'}</td>
<td>
<div class="flex items-center gap-2">
<progress
class="progress progress-info w-20"
value={progressPercent}
max="100"
<progress class="progress progress-info w-20" value={progressPercent} max="100"
></progress>
<span class="text-xs text-base-content/60">
<span class="text-base-content/60 text-xs">
{instance.progress.completed}/{instance.progress.total}
</span>
</div>
@@ -237,13 +247,27 @@
</td>
<td class="text-base-content/60 text-sm">{formatDate(instance.startedAt)}</td>
<td class="text-right">
<a
href="/licitacoes/fluxos/{instance._id}"
class="btn btn-ghost btn-sm"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<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" />
<a href="/licitacoes/fluxos/{instance._id}" class="btn btn-ghost btn-sm">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
/>
</svg>
Ver
</a>
@@ -283,7 +307,13 @@
</div>
{/if}
<form onsubmit={(e) => { e.preventDefault(); handleCreate(); }} class="mt-4 space-y-4">
<form
onsubmit={(e) => {
e.preventDefault();
handleCreate();
}}
class="mt-4 space-y-4"
>
<div class="form-control">
<label class="label" for="template-select">
<span class="label-text">Template de Fluxo</span>
@@ -302,7 +332,9 @@
{/if}
</select>
<p class="label">
<span class="label-text-alt text-base-content/60">Apenas templates publicados podem ser instanciados</span>
<span class="label-text-alt text-base-content/60"
>Apenas templates publicados podem ser instanciados</span
>
</p>
</div>
@@ -323,7 +355,9 @@
{/if}
</select>
<p class="label">
<span class="label-text-alt text-base-content/60">Opcional: vincule este fluxo a um contrato específico</span>
<span class="label-text-alt text-base-content/60"
>Opcional: vincule este fluxo a um contrato específico</span
>
</p>
</div>
@@ -359,7 +393,11 @@
</div>
</form>
</div>
<button type="button" class="modal-backdrop" onclick={closeCreateModal} aria-label="Fechar modal"></button>
<button
type="button"
class="modal-backdrop"
onclick={closeCreateModal}
aria-label="Fechar modal"
></button>
</div>
{/if}