feat: Implement granular permission-based status transitions for pedidos.

This commit is contained in:
2025-12-05 19:34:22 -03:00
parent 80e9b76649
commit ff91d8a3ab
2 changed files with 341 additions and 43 deletions

View File

@@ -30,6 +30,7 @@
const historyQuery = $derived.by(() => useQuery(api.pedidos.getHistory, { pedidoId }));
const objetosQuery = $derived.by(() => useQuery(api.objetos.list, {}));
const acoesQuery = $derived.by(() => useQuery(api.acoes.list, {}));
const permissionsQuery = $derived.by(() => useQuery(api.pedidos.getPermissions, { pedidoId }));
// Derived state
let pedido = $derived(pedidoQuery.data);
@@ -37,6 +38,7 @@
let history = $derived(historyQuery.data || []);
let objetos = $derived(objetosQuery.data || []);
let acoes = $derived(acoesQuery.data || []);
let permissions = $derived(permissionsQuery.data);
type Modalidade = 'dispensa' | 'inexgibilidade' | 'adesao' | 'consumo';
@@ -114,7 +116,8 @@
itemsQuery.isLoading ||
historyQuery.isLoading ||
objetosQuery.isLoading ||
acoesQuery.isLoading
acoesQuery.isLoading ||
permissionsQuery.isLoading
);
let error = $derived(
@@ -256,23 +259,48 @@
}
}
async function updateStatus(
novoStatus:
| 'cancelado'
| 'concluido'
| 'em_rascunho'
| 'aguardando_aceite'
| 'em_analise'
| 'precisa_ajustes'
) {
if (!confirm(`Confirmar alteração de status para: ${novoStatus}?`)) return;
async function handleEnviarParaAceite() {
if (!confirm('Enviar para aceite?')) return;
try {
await client.mutation(api.pedidos.updateStatus, {
pedidoId,
novoStatus
});
await client.mutation(api.pedidos.enviarParaAceite, { pedidoId });
} catch (e) {
alert('Erro ao atualizar status: ' + (e as Error).message);
alert('Erro: ' + (e as Error).message);
}
}
async function handleIniciarAnalise() {
if (!confirm('Iniciar análise?')) return;
try {
await client.mutation(api.pedidos.iniciarAnalise, { pedidoId });
} catch (e) {
alert('Erro: ' + (e as Error).message);
}
}
async function handleConcluir() {
if (!confirm('Concluir pedido?')) return;
try {
await client.mutation(api.pedidos.concluirPedido, { pedidoId });
} catch (e) {
alert('Erro: ' + (e as Error).message);
}
}
async function handleSolicitarAjustes() {
if (!confirm('Solicitar ajustes?')) return;
try {
await client.mutation(api.pedidos.solicitarAjustes, { pedidoId });
} catch (e) {
alert('Erro: ' + (e as Error).message);
}
}
async function handleCancelar() {
if (!confirm('Cancelar pedido?')) return;
try {
await client.mutation(api.pedidos.cancelarPedido, { pedidoId });
} catch (e) {
alert('Erro: ' + (e as Error).message);
}
}
@@ -635,42 +663,45 @@
</div>
<div class="flex gap-2">
{#if pedido.status === 'em_rascunho' || pedido.status === 'precisa_ajustes'}
{#if permissions?.canSendToAcceptance}
<button
onclick={() => updateStatus('aguardando_aceite')}
onclick={handleEnviarParaAceite}
class="flex items-center gap-2 rounded bg-blue-600 px-4 py-2 text-white hover:bg-blue-700"
>
<Send size={18} /> Enviar para Aceite
</button>
{/if}
{#if pedido.status === 'aguardando_aceite'}
{#if permissions?.canStartAnalysis}
<button
onclick={() => updateStatus('em_analise')}
onclick={handleIniciarAnalise}
class="flex items-center gap-2 rounded bg-indigo-600 px-4 py-2 text-white hover:bg-indigo-700"
>
<Clock size={18} /> Iniciar Análise
</button>
{/if}
{#if pedido.status === 'em_analise'}
{#if permissions?.canConclude}
<button
onclick={() => updateStatus('concluido')}
onclick={handleConcluir}
class="flex items-center gap-2 rounded bg-green-600 px-4 py-2 text-white hover:bg-green-700"
>
<CheckCircle size={18} /> Concluir
</button>
{/if}
{#if permissions?.canRequestAdjustments}
<button
onclick={() => updateStatus('precisa_ajustes')}
onclick={handleSolicitarAjustes}
class="flex items-center gap-2 rounded bg-orange-500 px-4 py-2 text-white hover:bg-orange-600"
>
<AlertTriangle size={18} /> Solicitar Ajustes
</button>
{/if}
{#if pedido.status !== 'cancelado' && pedido.status !== 'concluido'}
{#if permissions?.canCancel}
<button
onclick={() => updateStatus('cancelado')}
onclick={handleCancelar}
class="flex items-center gap-2 rounded bg-red-100 px-4 py-2 text-red-700 hover:bg-red-200"
>
<XCircle size={18} /> Cancelar