feat: Add 'atas' (minutes/records) management feature, and implement various improvements across UI, backend logic, and authentication.
This commit is contained in:
@@ -1,19 +1,18 @@
|
||||
<script lang="ts">
|
||||
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 ActionGuard from '$lib/components/ActionGuard.svelte';
|
||||
import { useConvexClient, useQuery } from 'convex-svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import ActionGuard from '$lib/components/ActionGuard.svelte';
|
||||
|
||||
const client = useConvexClient();
|
||||
|
||||
// Estado do filtro
|
||||
let statusFilter = $state<'draft' | 'published' | 'archived' | undefined>(undefined);
|
||||
const statusFilter = $state<'draft' | 'published' | 'archived' | undefined>(undefined);
|
||||
|
||||
// Query de templates
|
||||
const templatesQuery = useQuery(
|
||||
api.flows.listTemplates,
|
||||
() => (statusFilter ? { status: statusFilter } : {})
|
||||
const templatesQuery = useQuery(api.flows.listTemplates, () =>
|
||||
statusFilter ? { status: statusFilter } : {}
|
||||
);
|
||||
|
||||
// Modal de criação
|
||||
@@ -25,7 +24,10 @@
|
||||
|
||||
// Modal de confirmação de exclusão
|
||||
let showDeleteModal = $state(false);
|
||||
let templateToDelete = $state<{ _id: Id<'flowTemplates'>; name: string } | null>(null);
|
||||
let templateToDelete = $state<{
|
||||
_id: Id<'flowTemplates'>;
|
||||
name: string;
|
||||
} | null>(null);
|
||||
let isDeleting = $state(false);
|
||||
let deleteError = $state<string | null>(null);
|
||||
|
||||
@@ -86,7 +88,9 @@
|
||||
deleteError = null;
|
||||
|
||||
try {
|
||||
await client.mutation(api.flows.deleteTemplate, { id: templateToDelete._id });
|
||||
await client.mutation(api.flows.deleteTemplate, {
|
||||
id: templateToDelete._id
|
||||
});
|
||||
closeDeleteModal();
|
||||
} catch (e) {
|
||||
deleteError = e instanceof Error ? e.message : 'Erro ao excluir template';
|
||||
@@ -95,7 +99,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function handleStatusChange(templateId: Id<'flowTemplates'>, newStatus: 'draft' | 'published' | 'archived') {
|
||||
async function handleStatusChange(
|
||||
templateId: Id<'flowTemplates'>,
|
||||
newStatus: 'draft' | 'published' | 'archived'
|
||||
) {
|
||||
try {
|
||||
await client.mutation(api.flows.updateTemplate, {
|
||||
id: templateId,
|
||||
@@ -150,10 +157,7 @@
|
||||
</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="draft">Rascunho</option>
|
||||
<option value="published">Publicado</option>
|
||||
@@ -209,7 +213,9 @@
|
||||
</svg>
|
||||
<h3 class="text-base-content/70 mt-4 text-lg font-semibold">Nenhum template encontrado</h3>
|
||||
<p class="text-base-content/50 mt-2">
|
||||
{statusFilter ? 'Não há templates com este status.' : 'Clique em "Novo Template" para criar o primeiro.'}
|
||||
{statusFilter
|
||||
? 'Não há templates com este status.'
|
||||
: 'Clique em "Novo Template" para criar o primeiro.'}
|
||||
</p>
|
||||
</div>
|
||||
{:else}
|
||||
@@ -226,21 +232,45 @@
|
||||
</div>
|
||||
|
||||
{#if template.description}
|
||||
<p class="text-base-content/60 text-sm line-clamp-2">
|
||||
<p class="text-base-content/60 line-clamp-2 text-sm">
|
||||
{template.description}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<div class="text-base-content/50 mt-2 flex flex-wrap gap-4 text-xs">
|
||||
<span class="flex items-center gap-1">
|
||||
<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="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
|
||||
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="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>
|
||||
{template.stepsCount} passos
|
||||
</span>
|
||||
<span class="flex items-center gap-1">
|
||||
<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="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
|
||||
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="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>
|
||||
{formatDate(template.createdAt)}
|
||||
</span>
|
||||
@@ -249,11 +279,26 @@
|
||||
<div class="card-actions mt-4 justify-between">
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-ghost btn-sm" aria-label="Alterar status">
|
||||
<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="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
|
||||
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="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>
|
||||
</button>
|
||||
<ul class="dropdown-content menu bg-base-100 rounded-box z-10 w-52 p-2 shadow" role="menu">
|
||||
<ul
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-10 w-52 p-2 shadow"
|
||||
role="menu"
|
||||
>
|
||||
{#if template.status !== 'draft'}
|
||||
<li>
|
||||
<button onclick={() => handleStatusChange(template._id, 'draft')}>
|
||||
@@ -283,12 +328,21 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<a
|
||||
href="/fluxos/{template._id}/editor"
|
||||
class="btn btn-secondary 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="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" />
|
||||
<a href="/fluxos/{template._id}/editor" class="btn btn-secondary 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="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>
|
||||
Editar
|
||||
</a>
|
||||
@@ -303,8 +357,20 @@
|
||||
<!-- Link para Instâncias -->
|
||||
<section class="flex justify-center">
|
||||
<a href="/licitacoes/fluxos" class="btn btn-outline btn-lg">
|
||||
<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="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
|
||||
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="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>
|
||||
Ver Fluxos de Trabalho
|
||||
</a>
|
||||
@@ -337,7 +403,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-name">
|
||||
<span class="label-text">Nome do Template</span>
|
||||
@@ -378,7 +450,12 @@
|
||||
</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}
|
||||
|
||||
@@ -386,7 +463,7 @@
|
||||
{#if showDeleteModal && templateToDelete}
|
||||
<div class="modal modal-open">
|
||||
<div class="modal-box">
|
||||
<h3 class="text-lg font-bold text-error">Confirmar Exclusão</h3>
|
||||
<h3 class="text-error text-lg font-bold">Confirmar Exclusão</h3>
|
||||
|
||||
{#if deleteError}
|
||||
<div class="alert alert-error mt-4">
|
||||
@@ -412,13 +489,12 @@
|
||||
Tem certeza que deseja excluir o template <strong>{templateToDelete.name}</strong>?
|
||||
</p>
|
||||
<p class="text-base-content/60 text-sm">
|
||||
Esta ação não pode ser desfeita. Templates com instâncias vinculadas não podem ser excluídos.
|
||||
Esta ação não pode ser desfeita. Templates com instâncias vinculadas não podem ser
|
||||
excluídos.
|
||||
</p>
|
||||
|
||||
<div class="modal-action">
|
||||
<button class="btn" onclick={closeDeleteModal} disabled={isDeleting}>
|
||||
Cancelar
|
||||
</button>
|
||||
<button class="btn" onclick={closeDeleteModal} disabled={isDeleting}> Cancelar </button>
|
||||
<button class="btn btn-error" onclick={handleDelete} disabled={isDeleting}>
|
||||
{#if isDeleting}
|
||||
<span class="loading loading-spinner loading-sm"></span>
|
||||
@@ -427,7 +503,11 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="modal-backdrop" onclick={closeDeleteModal} aria-label="Fechar modal"></button>
|
||||
<button
|
||||
type="button"
|
||||
class="modal-backdrop"
|
||||
onclick={closeDeleteModal}
|
||||
aria-label="Fechar modal"
|
||||
></button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user