-
-
-
-
-
Fluxos de Trabalho
+
+
+
+
+
+
+
+
+
+
+ Fluxos de Trabalho
+
+
Gerencie templates e fluxos de trabalho para contratos e processos
-
- Gerencie templates e instâncias de fluxos de trabalho para contratos e processos.
-
-
+
+
+
+
diff --git a/apps/web/src/routes/(dashboard)/licitacoes/fluxos/+page.svelte b/apps/web/src/routes/(dashboard)/licitacoes/fluxos/+page.svelte
new file mode 100644
index 0000000..a78a8bd
--- /dev/null
+++ b/apps/web/src/routes/(dashboard)/licitacoes/fluxos/+page.svelte
@@ -0,0 +1,365 @@
+
+
+
+
+
+
+
+
+
+
+
+ Fluxos de Trabalho
+
+
+ Acompanhe e gerencie os fluxos de trabalho. Visualize o progresso,
+ documentos e responsáveis de cada etapa.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#if instancesQuery.isLoading}
+
+
+
+ {:else if !instancesQuery.data || instancesQuery.data.length === 0}
+
+
+
Nenhum fluxo encontrado
+
+ {statusFilter ? 'Não há fluxos com este status.' : 'Clique em "Novo Fluxo" para iniciar um fluxo.'}
+
+
+ {:else}
+
+
+
+
+ | Template |
+ Contrato |
+ Gerente |
+ Progresso |
+ Status |
+ Iniciado em |
+ Ações |
+
+
+
+ {#each instancesQuery.data as instance (instance._id)}
+ {@const statusBadge = getStatusBadge(instance.status)}
+ {@const progressPercent = getProgressPercentage(instance.progress.completed, instance.progress.total)}
+
+ |
+ {instance.templateName ?? 'Template desconhecido'}
+ |
+
+ {#if instance.contratoId}
+ {instance.contratoId}
+ {:else}
+ -
+ {/if}
+ |
+ {instance.managerName ?? '-'} |
+
+
+
+
+ {instance.progress.completed}/{instance.progress.total}
+
+
+ |
+
+ {statusBadge.label}
+ |
+ {formatDate(instance.startedAt)} |
+
+
+
+ Ver
+
+ |
+
+ {/each}
+
+
+
+ {/if}
+
+
+
+
+{#if showCreateModal}
+
+
+
Novo Fluxo de Trabalho
+
+ {#if createError}
+
+ {/if}
+
+
+
+
+
+{/if}
+
diff --git a/apps/web/src/routes/(dashboard)/licitacoes/fluxos/[id]/+page.svelte b/apps/web/src/routes/(dashboard)/licitacoes/fluxos/[id]/+page.svelte
new file mode 100644
index 0000000..f8fd33e
--- /dev/null
+++ b/apps/web/src/routes/(dashboard)/licitacoes/fluxos/[id]/+page.svelte
@@ -0,0 +1,1251 @@
+
+
+
+ {#if instanceQuery.isLoading}
+
+
+
+ {:else if !instanceQuery.data}
+
+
+
Fluxo não encontrado
+
Voltar para lista
+
+ {:else}
+ {@const instance = instanceQuery.data.instance}
+ {@const steps = instanceQuery.data.steps}
+ {@const statusBadge = getInstanceStatusBadge(instance.status)}
+
+
+
+
+
+
+
+
+
{statusBadge.label}
+
+
+
+
+
+ {instance.templateName ?? 'Fluxo'}
+
+
+ {#if instance.contratoId}
+
+ Contrato
+ {instance.contratoId}
+
+ {/if}
+
+
+
+
Gerente: {instance.managerName ?? '-'}
+
+
+
+
+
+ Iniciado: {formatDate(instance.startedAt)}
+
+
+
+
+
+
+
+ {#if instance.status === 'active'}
+
+
+
+ {/if}
+
+
+
+
+
+ {#if processingError}
+
+
+
{processingError}
+
+
+ {/if}
+
+
+
+ Timeline do Fluxo
+
+
+ {#each steps as step, index (step._id)}
+ {@const stepStatus = getStatusBadge(step.status)}
+ {@const isCurrent = isStepCurrent(step._id)}
+ {@const overdue = step.status !== 'completed' && isOverdue(step.dueDate)}
+ {@const subEtapasQuery = useQuery(api.flows.listarSubEtapas, () => ({ flowInstanceStepId: step._id }))}
+ {@const subEtapas = subEtapasQuery.data}
+ {@const subEtapasCount = subEtapas?.length ?? 0}
+ {@const subEtapasCompleted = subEtapas?.filter((s: { status: string }) => s.status === 'completed').length ?? 0}
+
+
+
+ {#if index < steps.length - 1}
+
+ {/if}
+
+
+
+ {#if step.status === 'completed'}
+
+ {:else if step.status === 'blocked'}
+
+ {:else}
+
{index + 1}
+ {/if}
+
+
+
+
+
+
+
+
+
{step.stepName}
+ {stepStatus.label}
+
+
+ {#if step.stepDescription}
+
{step.stepDescription}
+ {/if}
+
+
+
+ {step.setorNome ?? 'Setor não definido'}
+
+ {#if step.assignedToName}
+
+
+ {step.assignedToName}
+
+ {/if}
+ {#if step.dueDate}
+
+
+ Prazo: {formatDate(step.dueDate)}
+
+ {/if}
+
+
+
+
+ {#if instance.status === 'active'}
+
+ {#if step.status === 'pending'}
+
+
+
+ {:else if step.status === 'in_progress'}
+
+
+
+
+ {:else if step.status === 'blocked'}
+
+
+
+ {/if}
+
+
+
+
+
+ {/if}
+
+
+
+
+
+
+
+
Sub-etapas
+ {#if subEtapasCount > 0}
+
+ {subEtapasCompleted} / {subEtapasCount} concluídas
+
+ {/if}
+
+ {#if instance.status === 'active'}
+
+ {/if}
+
+
+ {#if subEtapasQuery.isLoading}
+
+
+
+ {:else if subEtapas && subEtapas.length > 0}
+
+ {#each subEtapas as subEtapa (subEtapa._id)}
+
+
+
+
{subEtapa.name}
+
+ {subEtapa.status === 'completed' ? 'Concluída' : subEtapa.status === 'in_progress' ? 'Em Andamento' : subEtapa.status === 'blocked' ? 'Bloqueada' : 'Pendente'}
+
+
+ {#if subEtapa.description}
+
{subEtapa.description}
+ {/if}
+
+
+ {#if instance.status === 'active'}
+
+
+ {/if}
+
+
+ {/each}
+
+ {:else}
+
+ Nenhuma sub-etapa adicionada
+
+ {/if}
+
+
+
+
+
+
+
+
Documentos
+ {#if step.documents && step.documents.length > 0}
+
{step.documents.length}
+ {/if}
+
+ {#if instance.status === 'active'}
+
+
+
+ {/if}
+
+
+ {#if step.documents && step.documents.length > 0}
+
+ {#each step.documents as doc (doc._id)}
+
+
+
+ {#if instance.status === 'active'}
+
+
+
+ {/if}
+
+ {/each}
+
+ {:else}
+
+ Nenhum documento anexado
+
+ {/if}
+
+
+
+
+
+
+
+
Notas e Comentários
+ {#if step.notes}
+
Atualizado
+ {/if}
+
+
+
+
+ {#if step.notes}
+
+
{step.notes}
+ {#if step.notesUpdatedByName || step.notesUpdatedAt}
+
+
+ {#if step.notesUpdatedByName}
+
Atualizado por {step.notesUpdatedByName}
+ {/if}
+ {#if step.notesUpdatedAt}
+
•
+
{formatDate(step.notesUpdatedAt)}
+ {/if}
+
+ {/if}
+
+ {:else}
+
+ Nenhuma nota ou comentário adicionado
+
+ {/if}
+
+
+
+ {#if step.startedAt || step.finishedAt}
+
+ {#if step.startedAt}
+
+
+ Iniciado: {formatDate(step.startedAt)}
+
+ {/if}
+ {#if step.finishedAt}
+
+
+ Concluído: {formatDate(step.finishedAt)}
+
+ {/if}
+
+ {/if}
+
+
+ {/each}
+
+
+ {/if}
+
+
+ {#if showAlterarGestorModal}
+
+
+
Alterar Gestor do Fluxo
+
+ Selecione o novo gestor responsável por este fluxo
+
+
+ {#if alterarGestorError}
+
+
+
{alterarGestorError}
+
+ {/if}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/if}
+
+
+ {#if showSubEtapaModal && stepIdParaSubEtapas}
+
+
+
Nova Sub-etapa
+
+ {#if subEtapaError}
+
+
+
{subEtapaError}
+
+ {/if}
+
+
+
+
+
+ {/if}
+
+
+ {#if toastMessage}
+
+
+
{toastMessage}
+
+
+
+ {/if}
+
+
+
+{#if showReassignModal && stepToReassign}
+
+
+
Reatribuir Responsável
+
+ Selecione o novo responsável pelo passo {stepToReassign.stepName}
+
+
+
+
+
+
+
+
+
+
+
+{/if}
+
+
+{#if showNotesModal && stepForNotes}
+
+
+
Notas do Passo
+
+ Adicione ou edite notas para o passo {stepForNotes.stepName}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{/if}
+
+
+{#if showUploadModal && stepForUpload}
+
+
+
Upload de Documento
+
+ Anexe um documento ao passo {stepForUpload.stepName}
+
+
+
+
+
+
+
+ {#if uploadFile}
+
+ Arquivo selecionado: {uploadFile.name}
+
+ {/if}
+
+
+
+
+
+
+
+
+{/if}
+
+
+{#if showCancelModal}
+
+
+
Cancelar Fluxo
+
+ Tem certeza que deseja cancelar este fluxo?
+
+
+ Esta ação não pode ser desfeita. Todos os passos pendentes serão marcados como cancelados.
+
+
+
+
+
+
+
+
+
+{/if}
+
diff --git a/apps/web/src/routes/(dashboard)/recursos-humanos/funcionarios/+page.svelte b/apps/web/src/routes/(dashboard)/recursos-humanos/funcionarios/+page.svelte
index 515fd6a..ca05422 100644
--- a/apps/web/src/routes/(dashboard)/recursos-humanos/funcionarios/+page.svelte
+++ b/apps/web/src/routes/(dashboard)/recursos-humanos/funcionarios/+page.svelte
@@ -1,23 +1,42 @@
-
+
-
+
@@ -118,7 +186,7 @@
-
+