125 lines
4.8 KiB
TypeScript
125 lines
4.8 KiB
TypeScript
import { useForm } from '@inertiajs/react';
|
|
import { createOperationKey } from '@/lib/operation-key';
|
|
import { button, card, input } from '@/pages/investment/shared';
|
|
|
|
type CaseState = { id: string; version: number; closed_at?: string | null };
|
|
export default function DeskCaseStateForm({
|
|
dossier,
|
|
activity,
|
|
disabled = false,
|
|
onChanged,
|
|
}: {
|
|
dossier: CaseState;
|
|
activity: {
|
|
open_requests: number | null;
|
|
open_tasks: number | null;
|
|
pending_payments: number | null;
|
|
} | null;
|
|
disabled?: boolean;
|
|
onChanged?: () => void;
|
|
}) {
|
|
const target = dossier.closed_at ? 'open' : 'closed';
|
|
const form = useForm({
|
|
version: dossier.version,
|
|
state: target,
|
|
reason: '',
|
|
client_key: createOperationKey(),
|
|
});
|
|
const stale =
|
|
form.data.version !== dossier.version || form.data.state !== target;
|
|
return (
|
|
<form
|
|
className={card + ' space-y-3'}
|
|
onSubmit={(event) => {
|
|
event.preventDefault();
|
|
if (form.processing || stale || disabled) return;
|
|
form.put(`/balcao-virtual/dossiers/${dossier.id}/estado`, {
|
|
onSuccess: (page) => {
|
|
const current = page.props.case as
|
|
| CaseState
|
|
| undefined;
|
|
if (
|
|
current?.id === dossier.id &&
|
|
Number.isInteger(current.version)
|
|
) {
|
|
form.setData('version', current.version);
|
|
form.setData(
|
|
'state',
|
|
current.closed_at ? 'open' : 'closed',
|
|
);
|
|
form.reset('reason');
|
|
form.setData('client_key', createOperationKey());
|
|
onChanged?.();
|
|
}
|
|
},
|
|
});
|
|
}}
|
|
>
|
|
<h2 className="text-xl font-bold">
|
|
{target === 'closed' ? 'Encerrar dossier' : 'Reabrir dossier'}
|
|
</h2>
|
|
<p>
|
|
Esta decisão pertence ao dono do dossier e fica registada com o
|
|
motivo e a versão.
|
|
</p>
|
|
<p>
|
|
{target === 'closed'
|
|
? 'O encerramento deixa o dossier disponível para consulta. Mantém os estados e as pendências dos pedidos, pagamentos e tarefas.'
|
|
: 'A reabertura permite continuar as operações autorizadas. Cada pedido, pagamento e tarefa mantém o seu estado e histórico.'}
|
|
</p>
|
|
<p>
|
|
Pedidos em curso: {activity?.open_requests ?? 'por confirmar'} ·
|
|
tarefas em curso: {activity?.open_tasks ?? 'por confirmar'} ·
|
|
comprovativos por conferir:{' '}
|
|
{activity?.pending_payments ?? 'por confirmar'}.
|
|
</p>
|
|
{stale && (
|
|
<p role="alert">
|
|
O dossier foi actualizado. Confira o estado actual antes de
|
|
confirmar.{' '}
|
|
<button
|
|
type="button"
|
|
disabled={form.processing}
|
|
onClick={() => {
|
|
form.setData('version', dossier.version);
|
|
form.setData('state', target);
|
|
form.setData('client_key', createOperationKey());
|
|
}}
|
|
>
|
|
Usar estado actual, conservando o motivo
|
|
</button>
|
|
</p>
|
|
)}
|
|
<label className="block">
|
|
Motivo{' '}
|
|
{target === 'closed' ? 'do encerramento' : 'da reabertura'}
|
|
<textarea
|
|
className={input}
|
|
required
|
|
minLength={3}
|
|
maxLength={5000}
|
|
disabled={form.processing}
|
|
value={form.data.reason}
|
|
onChange={(event) => {
|
|
form.setData('reason', event.target.value);
|
|
form.setData('client_key', createOperationKey());
|
|
}}
|
|
/>
|
|
</label>
|
|
<button
|
|
className={button}
|
|
disabled={form.processing || stale || disabled}
|
|
>
|
|
{target === 'closed'
|
|
? 'Confirmar encerramento do dossier'
|
|
: 'Confirmar reabertura do dossier'}
|
|
</button>
|
|
{Object.entries(form.errors).map(([key, error]) => (
|
|
<p role="alert" key={key}>
|
|
{error}
|
|
</p>
|
|
))}
|
|
</form>
|
|
);
|
|
}
|