Files
compras/resources/js/pages/purchases/recommendation-policy.tsx
T

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>
</>
);
}