feat: Enhance pedidos management with detailed item linking, object search, and improved UI for item configuration and details
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import type { Doc, Id } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||
import { useConvexClient, useQuery } from 'convex-svelte';
|
||||
import { Plus, Trash2, X } from 'lucide-svelte';
|
||||
import { Plus, Trash2, X, Info } from 'lucide-svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
acaoId?: Id<'acoes'>;
|
||||
ataId?: Id<'atas'>;
|
||||
ataNumero?: string; // For display
|
||||
ata?: Doc<'atas'>; // Full ata object for details
|
||||
};
|
||||
|
||||
let selectedItems = $state<SelectedItem[]>([]);
|
||||
@@ -55,6 +56,20 @@
|
||||
|
||||
let availableAtas = $state<Doc<'atas'>[]>([]);
|
||||
|
||||
// Item Details Modal
|
||||
let showDetailsModal = $state(false);
|
||||
let detailsItem = $state<SelectedItem | null>(null);
|
||||
|
||||
function openDetails(item: SelectedItem) {
|
||||
detailsItem = item;
|
||||
showDetailsModal = true;
|
||||
}
|
||||
|
||||
function closeDetails() {
|
||||
showDetailsModal = false;
|
||||
detailsItem = null;
|
||||
}
|
||||
|
||||
async function openItemModal(objeto: Doc<'objetos'>) {
|
||||
// Fetch linked Atas for this object
|
||||
const linkedAtas = await client.query(api.objetos.getAtas, { objetoId: objeto._id });
|
||||
@@ -90,7 +105,8 @@
|
||||
modalidade: itemConfig.modalidade,
|
||||
acaoId: itemConfig.acaoId ? (itemConfig.acaoId as Id<'acoes'>) : undefined,
|
||||
ataId: itemConfig.ataId ? (itemConfig.ataId as Id<'atas'>) : undefined,
|
||||
ataNumero: selectedAta?.numero
|
||||
ataNumero: selectedAta?.numero,
|
||||
ata: selectedAta
|
||||
}
|
||||
];
|
||||
checkExisting();
|
||||
@@ -223,58 +239,70 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="container mx-auto max-w-3xl p-6">
|
||||
<h1 class="mb-6 text-2xl font-bold">Novo Pedido</h1>
|
||||
<div class="container mx-auto max-w-4xl p-6">
|
||||
<h1 class="mb-6 text-3xl font-bold">Novo Pedido</h1>
|
||||
|
||||
<div class="rounded-lg bg-white p-6 shadow-md">
|
||||
<div class="space-y-6">
|
||||
{#if error}
|
||||
<div class="mb-4 rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700">
|
||||
{error}
|
||||
<div class="rounded-lg border border-red-400 bg-red-50 px-4 py-3 text-red-700">
|
||||
<p class="font-semibold">Erro</p>
|
||||
<p class="text-sm">{error}</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<form onsubmit={handleSubmit}>
|
||||
<div class="mb-6">
|
||||
<label class="mb-2 block text-sm font-bold text-gray-700" for="numeroSei">
|
||||
Número SEI (Opcional)
|
||||
</label>
|
||||
<input
|
||||
class="focus:shadow-outline w-full appearance-none rounded border px-3 py-2 leading-tight text-gray-700 shadow focus:outline-none"
|
||||
id="numeroSei"
|
||||
type="text"
|
||||
bind:value={formData.numeroSei}
|
||||
placeholder="Ex: 12345.000000/2023-00"
|
||||
onblur={checkExisting}
|
||||
/>
|
||||
<p class="mt-1 text-xs text-gray-500">Você pode adicionar o número SEI posteriormente.</p>
|
||||
<form onsubmit={handleSubmit} class="space-y-6">
|
||||
<!-- Section 1: Basic Information -->
|
||||
<div class="rounded-lg bg-white p-6 shadow-md">
|
||||
<h2 class="mb-4 text-lg font-semibold text-gray-800">Informações Básicas</h2>
|
||||
<div>
|
||||
<label class="mb-2 block text-sm font-medium text-gray-700" for="numeroSei">
|
||||
Número SEI (Opcional)
|
||||
</label>
|
||||
<input
|
||||
class="focus:shadow-outline w-full appearance-none rounded-lg border border-gray-300 px-4 py-2.5 leading-tight text-gray-700 shadow-sm transition focus:border-blue-500 focus:ring-2 focus:ring-blue-200 focus:outline-none"
|
||||
id="numeroSei"
|
||||
type="text"
|
||||
bind:value={formData.numeroSei}
|
||||
placeholder="Ex: 12345.000000/2023-00"
|
||||
onblur={checkExisting}
|
||||
/>
|
||||
<p class="mt-1.5 text-xs text-gray-500">
|
||||
Você pode adicionar o número SEI posteriormente.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-6">
|
||||
<label class="mb-2 block text-sm font-bold text-gray-700" for="produtos">
|
||||
Adicionar Objetos
|
||||
</label>
|
||||
<!-- Section 2: Add Objects -->
|
||||
<div class="rounded-lg bg-white p-6 shadow-md">
|
||||
<h2 class="mb-4 text-lg font-semibold text-gray-800">Adicionar Objetos ao Pedido</h2>
|
||||
|
||||
<div class="relative mb-2">
|
||||
<div class="relative mb-4">
|
||||
<label class="mb-2 block text-sm font-medium text-gray-700" for="search-objetos">
|
||||
Buscar Objetos
|
||||
</label>
|
||||
<input
|
||||
id="search-objetos"
|
||||
type="text"
|
||||
placeholder="Buscar objetos..."
|
||||
class="focus:shadow-outline w-full appearance-none rounded border px-3 py-2 leading-tight text-gray-700 shadow focus:outline-none"
|
||||
placeholder="Digite o nome do objeto..."
|
||||
class="focus:shadow-outline w-full appearance-none rounded-lg border border-gray-300 px-4 py-2.5 leading-tight text-gray-700 shadow-sm transition focus:border-blue-500 focus:ring-2 focus:ring-blue-200 focus:outline-none"
|
||||
bind:value={searchQuery}
|
||||
/>
|
||||
{#if searchQuery.length > 0 && searchResults}
|
||||
<div class="absolute z-10 mt-1 w-full rounded border bg-white shadow-lg">
|
||||
<div
|
||||
class="absolute z-10 mt-2 w-full rounded-lg border border-gray-200 bg-white shadow-xl"
|
||||
>
|
||||
{#if searchResults.length === 0}
|
||||
<div class="p-2 text-sm text-gray-500">Nenhum objeto encontrado.</div>
|
||||
<div class="p-4 text-sm text-gray-500">Nenhum objeto encontrado.</div>
|
||||
{:else}
|
||||
<ul class="max-h-60 overflow-y-auto">
|
||||
<ul class="max-h-64 overflow-y-auto">
|
||||
{#each searchResults as objeto (objeto._id)}
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-full items-center justify-between px-4 py-2 text-left hover:bg-gray-100"
|
||||
class="flex w-full items-center justify-between px-4 py-3 text-left transition hover:bg-blue-50"
|
||||
onclick={() => openItemModal(objeto)}
|
||||
>
|
||||
<span>{objeto.nome}</span>
|
||||
<span class="font-medium text-gray-800">{objeto.nome}</span>
|
||||
<Plus size={16} class="text-blue-600" />
|
||||
</button>
|
||||
</li>
|
||||
@@ -286,68 +314,97 @@
|
||||
</div>
|
||||
|
||||
{#if selectedItems.length > 0}
|
||||
<div class="mt-4">
|
||||
<h3 class="mb-2 text-sm font-semibold text-gray-700">Itens Selecionados:</h3>
|
||||
<div class="mt-6">
|
||||
<h3 class="mb-3 text-sm font-semibold text-gray-700">
|
||||
Itens Selecionados ({selectedItems.length})
|
||||
</h3>
|
||||
<div class="space-y-3">
|
||||
{#each selectedItems as item, index (index)}
|
||||
<div class="rounded-md border bg-gray-50 p-3">
|
||||
<div
|
||||
class="rounded-lg border border-gray-200 bg-gray-50 p-4 transition hover:shadow-md"
|
||||
>
|
||||
<div class="flex items-start justify-between">
|
||||
<div>
|
||||
<div class="font-medium">{item.objeto.nome}</div>
|
||||
<div class="text-xs text-gray-500">
|
||||
Qtd: {item.quantidade} | Unid: {item.objeto.unidade}
|
||||
</div>
|
||||
<div class="mt-1 text-xs">
|
||||
<span class="font-semibold text-gray-600">Modalidade:</span>
|
||||
{item.modalidade}
|
||||
{#if item.acaoId}
|
||||
<span class="ml-2 font-semibold text-gray-600">Ação:</span>
|
||||
{getAcaoNome(item.acaoId)}
|
||||
{/if}
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center gap-2">
|
||||
<p class="font-semibold text-gray-900">{item.objeto.nome}</p>
|
||||
{#if item.ataNumero}
|
||||
<span class="ml-2 font-semibold text-gray-600">Ata:</span>
|
||||
{item.ataNumero}
|
||||
<span
|
||||
class="rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800"
|
||||
>
|
||||
Ata {item.ataNumero}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="mt-2 flex flex-wrap gap-x-4 gap-y-1 text-sm text-gray-600">
|
||||
<span><strong>Qtd:</strong> {item.quantidade} {item.objeto.unidade}</span>
|
||||
<span><strong>Modalidade:</strong> {item.modalidade}</span>
|
||||
{#if item.acaoId}
|
||||
<span><strong>Ação:</strong> {getAcaoNome(item.acaoId)}</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="text-red-600 hover:text-red-800"
|
||||
onclick={() => removeItem(index)}
|
||||
>
|
||||
<Trash2 size={18} />
|
||||
</button>
|
||||
<div class="ml-4 flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="rounded p-2 text-blue-600 transition hover:bg-blue-50"
|
||||
onclick={() => openDetails(item)}
|
||||
aria-label="Ver detalhes"
|
||||
>
|
||||
<Info size={18} />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded p-2 text-red-600 transition hover:bg-red-50"
|
||||
onclick={() => removeItem(index)}
|
||||
aria-label="Remover item"
|
||||
>
|
||||
<Trash2 size={18} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="mt-4 rounded-lg border-2 border-dashed border-gray-300 p-8 text-center">
|
||||
<p class="text-sm text-gray-500">
|
||||
Nenhum item adicionado. Use a busca acima para adicionar objetos ao pedido.
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Warnings Section -->
|
||||
{#if warning}
|
||||
<div
|
||||
class="mb-4 rounded border border-yellow-400 bg-yellow-100 px-4 py-3 text-sm text-yellow-800"
|
||||
class="rounded-lg border border-yellow-400 bg-yellow-50 px-4 py-3 text-sm text-yellow-800"
|
||||
>
|
||||
{warning}
|
||||
<p class="font-semibold">Aviso</p>
|
||||
<p>{warning}</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if checking}
|
||||
<p class="mb-4 text-sm text-gray-500">Verificando pedidos existentes...</p>
|
||||
<p class="text-sm text-gray-500">Verificando pedidos existentes...</p>
|
||||
{/if}
|
||||
|
||||
{#if existingPedidos.length > 0}
|
||||
<div class="mb-6 rounded border border-yellow-300 bg-yellow-50 p-4">
|
||||
<p class="mb-2 text-sm text-yellow-800">Pedidos similares encontrados:</p>
|
||||
<div class="rounded-lg border border-yellow-300 bg-yellow-50 p-4">
|
||||
<p class="mb-3 font-semibold text-yellow-900">Pedidos similares encontrados:</p>
|
||||
<ul class="space-y-2">
|
||||
{#each existingPedidos as pedido (pedido._id)}
|
||||
<li class="flex flex-col rounded bg-white px-3 py-2 shadow-sm">
|
||||
<li class="flex flex-col rounded-lg bg-white px-4 py-3 shadow-sm">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<div class="text-sm font-medium">
|
||||
<p class="text-sm font-medium text-gray-900">
|
||||
Pedido {pedido.numeroSei || 'sem número SEI'} — {formatStatus(pedido.status)}
|
||||
</div>
|
||||
</p>
|
||||
{#if getMatchingInfo(pedido)}
|
||||
<p class="mt-1 text-xs text-blue-700">
|
||||
{getMatchingInfo(pedido)}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
<a
|
||||
href={resolve(`/pedidos/${pedido._id}`)}
|
||||
@@ -356,28 +413,24 @@
|
||||
Abrir
|
||||
</a>
|
||||
</div>
|
||||
{#if getMatchingInfo(pedido)}
|
||||
<div class="mt-1 text-xs font-semibold text-blue-700">
|
||||
{getMatchingInfo(pedido)}
|
||||
</div>
|
||||
{/if}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex items-center justify-end border-t pt-4">
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex items-center justify-end gap-3 border-t pt-6">
|
||||
<a
|
||||
href={resolve('/pedidos')}
|
||||
class="mr-2 rounded bg-gray-300 px-4 py-2 font-bold text-gray-800 hover:bg-gray-400"
|
||||
class="rounded-lg bg-gray-200 px-6 py-2.5 font-semibold text-gray-800 transition hover:bg-gray-300"
|
||||
>
|
||||
Cancelar
|
||||
</a>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={creating || selectedItems.length === 0}
|
||||
class="focus:shadow-outline rounded bg-blue-600 px-4 py-2 font-bold text-white hover:bg-blue-700 focus:outline-none disabled:opacity-50"
|
||||
class="rounded-lg bg-blue-600 px-6 py-2.5 font-semibold text-white shadow-md transition hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50"
|
||||
>
|
||||
{creating ? 'Criando...' : 'Criar Pedido'}
|
||||
</button>
|
||||
@@ -385,92 +438,191 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Item Configuration Modal -->
|
||||
{#if showItemModal && itemConfig.objeto}
|
||||
<div
|
||||
class="fixed inset-0 z-50 flex h-full w-full items-center justify-center overflow-y-auto bg-black/40"
|
||||
class="fixed inset-0 z-50 flex h-full w-full items-center justify-center overflow-y-auto bg-black/40 p-4"
|
||||
>
|
||||
<div class="relative w-full max-w-md rounded-lg bg-white p-6 shadow-xl">
|
||||
<div class="relative w-full max-w-lg rounded-xl bg-white p-6 shadow-2xl">
|
||||
<button
|
||||
onclick={closeItemModal}
|
||||
class="absolute top-4 right-4 text-gray-400 hover:text-gray-600"
|
||||
class="absolute top-4 right-4 rounded-lg p-1 text-gray-400 transition hover:bg-gray-100 hover:text-gray-600"
|
||||
aria-label="Fechar"
|
||||
>
|
||||
<X size={24} />
|
||||
</button>
|
||||
<h3 class="mb-4 text-lg font-bold">Configurar Item</h3>
|
||||
<div class="mb-4">
|
||||
<p class="font-medium">{itemConfig.objeto.nome}</p>
|
||||
<p class="text-sm text-gray-500">Unidade: {itemConfig.objeto.unidade}</p>
|
||||
|
||||
<h3 class="mb-4 text-xl font-bold text-gray-900">Configurar Item</h3>
|
||||
|
||||
<div class="mb-6 rounded-lg bg-blue-50 p-4">
|
||||
<p class="font-semibold text-gray-900">{itemConfig.objeto.nome}</p>
|
||||
<p class="text-sm text-gray-600">Unidade: {itemConfig.objeto.unidade}</p>
|
||||
<p class="mt-1 text-xs text-gray-500">
|
||||
Valor estimado: {itemConfig.objeto.valorEstimado}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="mb-1 block text-sm font-bold text-gray-700" for="quantidade">
|
||||
Quantidade
|
||||
</label>
|
||||
<input
|
||||
id="quantidade"
|
||||
type="number"
|
||||
min="1"
|
||||
class="w-full rounded border px-3 py-2"
|
||||
bind:value={itemConfig.quantidade}
|
||||
/>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="mb-2 block text-sm font-medium text-gray-700" for="quantidade">
|
||||
Quantidade
|
||||
</label>
|
||||
<input
|
||||
id="quantidade"
|
||||
type="number"
|
||||
min="1"
|
||||
class="w-full rounded-lg border border-gray-300 px-4 py-2.5 transition focus:border-blue-500 focus:ring-2 focus:ring-blue-200 focus:outline-none"
|
||||
bind:value={itemConfig.quantidade}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="mb-1 block text-sm font-bold text-gray-700" for="modalidade">
|
||||
Modalidade
|
||||
</label>
|
||||
<select
|
||||
id="modalidade"
|
||||
class="w-full rounded border px-3 py-2"
|
||||
bind:value={itemConfig.modalidade}
|
||||
>
|
||||
<option value="consumo">Consumo</option>
|
||||
<option value="dispensa">Dispensa</option>
|
||||
<option value="inexgibilidade">Inexigibilidade</option>
|
||||
<option value="adesao">Adesão</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{#if availableAtas.length > 0}
|
||||
<div class="mb-4">
|
||||
<label class="mb-1 block text-sm font-bold text-gray-700" for="itemAta">
|
||||
Ata de Registro de Preços (Opcional)
|
||||
<div>
|
||||
<label class="mb-2 block text-sm font-medium text-gray-700" for="modalidade">
|
||||
Modalidade
|
||||
</label>
|
||||
<select
|
||||
id="itemAta"
|
||||
class="w-full rounded border px-3 py-2"
|
||||
bind:value={itemConfig.ataId}
|
||||
id="modalidade"
|
||||
class="w-full rounded-lg border border-gray-300 px-4 py-2.5 transition focus:border-blue-500 focus:ring-2 focus:ring-blue-200 focus:outline-none"
|
||||
bind:value={itemConfig.modalidade}
|
||||
>
|
||||
<option value="">Selecione uma ata...</option>
|
||||
{#each availableAtas as ata (ata._id)}
|
||||
<option value={ata._id}>Ata {ata.numero} ({ata.numeroSei})</option>
|
||||
<option value="consumo">Consumo</option>
|
||||
<option value="dispensa">Dispensa</option>
|
||||
<option value="inexgibilidade">Inexigibilidade</option>
|
||||
<option value="adesao">Adesão</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{#if availableAtas.length > 0}
|
||||
<div class="rounded-lg border-2 border-green-200 bg-green-50 p-4">
|
||||
<div class="mb-2 flex items-center gap-2">
|
||||
<span class="rounded-full bg-green-600 px-2 py-0.5 text-xs font-bold text-white">
|
||||
{availableAtas.length}
|
||||
{availableAtas.length === 1 ? 'Ata' : 'Atas'}
|
||||
</span>
|
||||
<span class="text-sm font-semibold text-green-900">disponível para este objeto</span
|
||||
>
|
||||
</div>
|
||||
<label class="mb-2 block text-sm font-medium text-gray-700" for="itemAta">
|
||||
Selecionar Ata (Opcional)
|
||||
</label>
|
||||
<select
|
||||
id="itemAta"
|
||||
class="w-full rounded-lg border border-green-300 bg-white px-4 py-2.5 transition focus:border-green-500 focus:ring-2 focus:ring-green-200 focus:outline-none"
|
||||
bind:value={itemConfig.ataId}
|
||||
>
|
||||
<option value="">Nenhuma</option>
|
||||
{#each availableAtas as ata (ata._id)}
|
||||
<option value={ata._id}>Ata {ata.numero} (SEI: {ata.numeroSei})</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div>
|
||||
<label class="mb-2 block text-sm font-medium text-gray-700" for="itemAcao">
|
||||
Ação (Opcional)
|
||||
</label>
|
||||
<select
|
||||
id="itemAcao"
|
||||
class="w-full rounded-lg border border-gray-300 px-4 py-2.5 transition focus:border-blue-500 focus:ring-2 focus:ring-blue-200 focus:outline-none"
|
||||
bind:value={itemConfig.acaoId}
|
||||
>
|
||||
<option value="">Selecione uma ação...</option>
|
||||
{#each acoes as acao (acao._id)}
|
||||
<option value={acao._id}>{acao.nome}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="mb-6">
|
||||
<label class="mb-1 block text-sm font-bold text-gray-700" for="itemAcao">
|
||||
Ação (Opcional)
|
||||
</label>
|
||||
<select
|
||||
id="itemAcao"
|
||||
class="w-full rounded border px-3 py-2"
|
||||
bind:value={itemConfig.acaoId}
|
||||
>
|
||||
<option value="">Selecione uma ação...</option>
|
||||
{#each acoes as acao (acao._id)}
|
||||
<option value={acao._id}>{acao.nome}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end">
|
||||
<div class="mt-6 flex justify-end gap-3">
|
||||
<button
|
||||
onclick={confirmAddItem}
|
||||
class="rounded bg-blue-600 px-4 py-2 font-bold text-white hover:bg-blue-700"
|
||||
type="button"
|
||||
onclick={closeItemModal}
|
||||
class="rounded-lg bg-gray-200 px-5 py-2.5 font-semibold text-gray-800 transition hover:bg-gray-300"
|
||||
>
|
||||
Adicionar
|
||||
Cancelar
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onclick={confirmAddItem}
|
||||
class="rounded-lg bg-blue-600 px-5 py-2.5 font-semibold text-white shadow-md transition hover:bg-blue-700"
|
||||
>
|
||||
Adicionar Item
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Details Modal -->
|
||||
{#if showDetailsModal && detailsItem}
|
||||
<div
|
||||
class="fixed inset-0 z-50 flex h-full w-full items-center justify-center overflow-y-auto bg-black/40 p-4"
|
||||
>
|
||||
<div class="relative w-full max-w-lg rounded-xl bg-white p-6 shadow-2xl">
|
||||
<button
|
||||
onclick={closeDetails}
|
||||
class="absolute top-4 right-4 rounded-lg p-1 text-gray-400 transition hover:bg-gray-100 hover:text-gray-600"
|
||||
aria-label="Fechar"
|
||||
>
|
||||
<X size={24} />
|
||||
</button>
|
||||
|
||||
<h3 class="mb-4 text-xl font-bold text-gray-900">Detalhes do Item</h3>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="rounded-lg bg-gray-50 p-4">
|
||||
<h4 class="mb-2 font-semibold text-gray-800">Objeto</h4>
|
||||
<p class="text-gray-700"><strong>Nome:</strong> {detailsItem.objeto.nome}</p>
|
||||
<p class="text-gray-700"><strong>Unidade:</strong> {detailsItem.objeto.unidade}</p>
|
||||
<p class="text-gray-700">
|
||||
<strong>Valor Estimado:</strong>
|
||||
{detailsItem.objeto.valorEstimado}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-lg bg-gray-50 p-4">
|
||||
<h4 class="mb-2 font-semibold text-gray-800">Pedido</h4>
|
||||
<p class="text-gray-700"><strong>Quantidade:</strong> {detailsItem.quantidade}</p>
|
||||
<p class="text-gray-700"><strong>Modalidade:</strong> {detailsItem.modalidade}</p>
|
||||
{#if detailsItem.acaoId}
|
||||
<p class="text-gray-700">
|
||||
<strong>Ação:</strong>
|
||||
{getAcaoNome(detailsItem.acaoId)}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if detailsItem.ata}
|
||||
<div class="rounded-lg border border-green-100 bg-green-50 p-4">
|
||||
<h4 class="mb-2 font-semibold text-green-900">Ata de Registro de Preços</h4>
|
||||
<p class="text-green-800"><strong>Número:</strong> {detailsItem.ata.numero}</p>
|
||||
<p class="text-green-800">
|
||||
<strong>Processo SEI:</strong>
|
||||
{detailsItem.ata.numeroSei}
|
||||
</p>
|
||||
{#if detailsItem.ata.dataInicio}
|
||||
<p class="text-green-800">
|
||||
<strong>Vigência:</strong>
|
||||
{detailsItem.ata.dataInicio} até {detailsItem.ata.dataFim || 'Indefinido'}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="rounded-lg bg-gray-50 p-4">
|
||||
<p class="text-sm text-gray-500 italic">Nenhuma Ata vinculada a este item.</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<button
|
||||
type="button"
|
||||
onclick={closeDetails}
|
||||
class="rounded-lg bg-blue-600 px-5 py-2.5 font-semibold text-white shadow-md transition hover:bg-blue-700"
|
||||
>
|
||||
Fechar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user