191 lines
8.6 KiB
TypeScript
191 lines
8.6 KiB
TypeScript
import { Link } from '@inertiajs/react';
|
|
import { Panel } from '@/components/procurement';
|
|
|
|
type Person = {
|
|
id: number;
|
|
name: string;
|
|
current_permissions: string[];
|
|
configured_permissions: string[];
|
|
added: string[];
|
|
removed: string[];
|
|
current_can_request: boolean;
|
|
configured_can_request: boolean;
|
|
configured_maintenance_only: boolean;
|
|
permanent_admin: boolean;
|
|
current_contexts: string[] | null;
|
|
configured_contexts: string[] | null;
|
|
loses_access: boolean;
|
|
};
|
|
export type ActivationPreview = {
|
|
ready: boolean;
|
|
active?: boolean;
|
|
version?: number;
|
|
checked_at?: string;
|
|
users: Person[];
|
|
permanent_administrators?: number;
|
|
provisional_rules?: boolean;
|
|
can_activate?: boolean;
|
|
losing_access?: number;
|
|
context_labels?: Record<string, string>;
|
|
};
|
|
|
|
export function OrganizationActivationPreview({
|
|
preview,
|
|
permissions,
|
|
tasks,
|
|
}: {
|
|
preview: ActivationPreview;
|
|
permissions: Record<string, string>;
|
|
tasks: Record<string, { key: string; label: string }[]>;
|
|
}) {
|
|
if (!preview.ready) return null;
|
|
const labels = (keys: string[], source = permissions) =>
|
|
keys.map((key) => source[key] ?? key).join('; ') || 'Nenhuma';
|
|
return (
|
|
<Panel
|
|
title={
|
|
preview.active
|
|
? 'Acessos e tarefas da configuração activa'
|
|
: 'Conferir o efeito da activação'
|
|
}
|
|
description="Esta consulta reutiliza os perfis e as atribuições guardados. Não altera acessos, não cria contas e não decide processos."
|
|
>
|
|
<div className="space-y-4 text-sm">
|
|
<p>
|
|
{preview.users.length} utilizador(es) ·{' '}
|
|
{preview.permanent_administrators} administrador(es)
|
|
permanente(s)
|
|
{preview.active
|
|
? ''
|
|
: ` · ${preview.losing_access} utilizador(es) ficaria(m) sem competência de acesso`}
|
|
</p>
|
|
{!preview.active && (
|
|
<p className="rounded border p-3">
|
|
{preview.can_activate
|
|
? 'As condições existentes de dois administradores permanentes e regras confirmadas estão preenchidas. Confira o efeito em cada pessoa antes de activar.'
|
|
: 'A activação exige dois administradores permanentes atribuídos e regras de aprovação confirmadas.'}
|
|
{preview.provisional_rules &&
|
|
' As regras actuais continuam provisórias.'}
|
|
</p>
|
|
)}
|
|
<p>
|
|
As tarefas descritas dependem também do processo,
|
|
departamento, contexto, independência e competências
|
|
específicas. Uma competência financeira não substitui os
|
|
acessos próprios às obrigações financeiras.
|
|
</p>
|
|
<Link
|
|
href="/administracao/parametrizacao"
|
|
preserveScroll
|
|
className="inline-block font-semibold underline"
|
|
>
|
|
Actualizar diagnóstico e configuração
|
|
</Link>
|
|
{preview.users.map((person) => (
|
|
<details key={person.id} className="rounded border p-3">
|
|
<summary className="cursor-pointer font-semibold">
|
|
{person.name}
|
|
{person.loses_access && !preview.active
|
|
? ' · Ficaria sem acesso'
|
|
: ''}
|
|
{person.permanent_admin
|
|
? ' · Administração permanente'
|
|
: ''}
|
|
</summary>
|
|
<div className="mt-3 space-y-3">
|
|
<p>
|
|
<strong>Competências actuais:</strong>{' '}
|
|
{labels(person.current_permissions)}
|
|
</p>
|
|
<p>
|
|
<strong>
|
|
Competências dos perfis guardados:
|
|
</strong>{' '}
|
|
{labels(person.configured_permissions)}
|
|
</p>
|
|
{!preview.active && (
|
|
<>
|
|
<p>
|
|
<strong>Acrescentadas:</strong>{' '}
|
|
{labels(person.added)}
|
|
</p>
|
|
<p>
|
|
<strong>Retiradas:</strong>{' '}
|
|
{labels(person.removed)}
|
|
</p>
|
|
</>
|
|
)}
|
|
<p>
|
|
<strong>
|
|
Preparação de requisição de compra:
|
|
</strong>{' '}
|
|
actualmente{' '}
|
|
{person.current_can_request ? 'sim' : 'não'};
|
|
pelos perfis guardados{' '}
|
|
{person.configured_can_request ? 'sim' : 'não'}.
|
|
</p>
|
|
{person.configured_contexts === null ? (
|
|
<p>
|
|
A selecção de contextos ainda não está
|
|
activa nesta empresa.
|
|
</p>
|
|
) : (
|
|
<>
|
|
<p>
|
|
<strong>Contextos actuais:</strong>{' '}
|
|
{labels(
|
|
person.current_contexts ?? [],
|
|
preview.context_labels,
|
|
)}
|
|
</p>
|
|
<p>
|
|
<strong>
|
|
Contextos pelos perfis guardados:
|
|
</strong>{' '}
|
|
{labels(
|
|
person.configured_contexts,
|
|
preview.context_labels,
|
|
)}
|
|
</p>
|
|
</>
|
|
)}
|
|
{person.configured_maintenance_only ? (
|
|
<p>
|
|
Manutenção temporária: diagnóstico e
|
|
consulta, sem operações de negócio.
|
|
</p>
|
|
) : (
|
|
<div>
|
|
<strong>
|
|
Tarefas associadas às competências
|
|
guardadas:
|
|
</strong>
|
|
<ul className="mt-2 list-disc space-y-1 pl-5">
|
|
{person.configured_permissions
|
|
.flatMap(
|
|
(permission) =>
|
|
tasks[permission] ?? [],
|
|
)
|
|
.map((task) => (
|
|
<li key={task.key}>
|
|
{task.label}
|
|
</li>
|
|
))}
|
|
{person.configured_permissions
|
|
.length === 0 && (
|
|
<li>
|
|
Sem tarefas atribuídas pelos
|
|
perfis.
|
|
</li>
|
|
)}
|
|
</ul>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</details>
|
|
))}
|
|
</div>
|
|
</Panel>
|
|
);
|
|
}
|