Files
Investidor-V2/resources/js/components/desk-case-state-form.tsx
T

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