187 lines
8.2 KiB
TypeScript
187 lines
8.2 KiB
TypeScript
import { Head, Link, useForm } from '@inertiajs/react';
|
|
import { FormErrors, PageTitle, Panel } from '@/components/procurement';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Input } from '@/components/ui/input';
|
|
import { Label } from '@/components/ui/label';
|
|
import { date, roleLabels } from '@/types/procurement';
|
|
|
|
type Policy = {
|
|
id: number;
|
|
revision: number;
|
|
enabled: boolean;
|
|
roles: string[];
|
|
required_count: number;
|
|
reason: string;
|
|
created_at: string;
|
|
};
|
|
type Props = {
|
|
latest: Policy | null;
|
|
policies: {
|
|
data: Policy[];
|
|
prev_page_url: string | null;
|
|
next_page_url: string | null;
|
|
};
|
|
};
|
|
export default function RecommendationPolicy({ latest, policies }: Props) {
|
|
return (
|
|
<PolicyForm key={latest?.id ?? 0} latest={latest} policies={policies} />
|
|
);
|
|
}
|
|
|
|
function PolicyForm({ latest, policies }: Props) {
|
|
const form = useForm({
|
|
previous_id: latest?.id ?? 0,
|
|
enabled: false,
|
|
roles: [] as string[],
|
|
required_count: '',
|
|
reason: '',
|
|
});
|
|
return (
|
|
<>
|
|
<Head title="Política de recomendação" />
|
|
<div className="mx-auto flex max-w-7xl flex-col gap-6 p-5 lg:p-8">
|
|
<PageTitle
|
|
eyebrow="Configuração da empresa"
|
|
title="Política de recomendação"
|
|
description="Sistema de Gestão de Compras (SGC) · Configuração da empresa"
|
|
/>
|
|
<Panel title="Nova versão da política">
|
|
<p className="mb-4 text-sm text-muted-foreground">
|
|
Defina os perfis e a quantidade de pessoas distintas.
|
|
Activar permite novas adopções expressas pelos
|
|
processos; desactivar impede novas adopções. As versões
|
|
já adoptadas mantêm-se. O limite técnico de 50
|
|
confirmações não define uma regra da empresa.
|
|
</p>
|
|
<form
|
|
className="space-y-4"
|
|
onSubmit={(e) => {
|
|
e.preventDefault();
|
|
form.post('/politica-recomendacao');
|
|
}}
|
|
>
|
|
<FormErrors errors={form.errors} />
|
|
<Label className="flex items-center gap-2">
|
|
<input
|
|
type="checkbox"
|
|
checked={form.data.enabled}
|
|
onChange={(e) =>
|
|
form.setData('enabled', e.target.checked)
|
|
}
|
|
/>
|
|
Activar para novas adopções
|
|
</Label>
|
|
<fieldset className="space-y-2">
|
|
<legend className="mb-2 text-sm font-medium">
|
|
Perfis autorizados a conferir
|
|
</legend>
|
|
{['finance', 'department_head'].map((role) => (
|
|
<Label
|
|
key={role}
|
|
className="flex items-center gap-2"
|
|
>
|
|
<input
|
|
type="checkbox"
|
|
checked={form.data.roles.includes(role)}
|
|
onChange={(e) =>
|
|
form.setData(
|
|
'roles',
|
|
e.target.checked
|
|
? [...form.data.roles, role]
|
|
: form.data.roles.filter(
|
|
(r) => r !== role,
|
|
),
|
|
)
|
|
}
|
|
/>
|
|
{roleLabels[role] ?? role}
|
|
{role === 'department_head' &&
|
|
' do departamento do processo'}
|
|
</Label>
|
|
))}
|
|
</fieldset>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="required-count">
|
|
Quantidade de pessoas distintas exigida
|
|
</Label>
|
|
<Input
|
|
id="required-count"
|
|
type="number"
|
|
min={1}
|
|
max={50}
|
|
required
|
|
value={form.data.required_count}
|
|
onChange={(e) =>
|
|
form.setData(
|
|
'required_count',
|
|
e.target.value,
|
|
)
|
|
}
|
|
/>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="policy-reason">
|
|
Fundamento desta versão
|
|
</Label>
|
|
<textarea
|
|
id="policy-reason"
|
|
className="min-h-24 w-full rounded-md border p-3"
|
|
required
|
|
minLength={10}
|
|
maxLength={4000}
|
|
value={form.data.reason}
|
|
onChange={(e) =>
|
|
form.setData('reason', e.target.value)
|
|
}
|
|
/>
|
|
</div>
|
|
<Button disabled={form.processing}>
|
|
Registar versão {latest ? latest.revision + 1 : 1}
|
|
</Button>
|
|
</form>
|
|
</Panel>
|
|
<Panel title="Versões preservadas">
|
|
<div className="space-y-4">
|
|
{policies.data.length === 0 && (
|
|
<p>A empresa ainda não definiu uma política.</p>
|
|
)}
|
|
{policies.data.map((p) => (
|
|
<article
|
|
key={p.id}
|
|
className="rounded-md border p-4"
|
|
>
|
|
<h2 className="font-semibold">
|
|
Versão {p.revision} ·{' '}
|
|
{p.enabled ? 'Activada' : 'Desactivada'} ·{' '}
|
|
{date(p.created_at)}
|
|
</h2>
|
|
<p>
|
|
{p.required_count} pessoa(s) ·{' '}
|
|
{p.roles
|
|
.map((r) => roleLabels[r] ?? r)
|
|
.join(', ')}
|
|
</p>
|
|
<p className="text-sm whitespace-pre-wrap">
|
|
{p.reason}
|
|
</p>
|
|
</article>
|
|
))}
|
|
<div className="flex gap-4">
|
|
{policies.prev_page_url && (
|
|
<Link href={policies.prev_page_url}>
|
|
Anteriores
|
|
</Link>
|
|
)}
|
|
{policies.next_page_url && (
|
|
<Link href={policies.next_page_url}>
|
|
Seguintes
|
|
</Link>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</Panel>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|