feat: complete approval workflow
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Head, Link, useForm } from '@inertiajs/react';
|
||||
import { Ban, CalendarDays, Plus } from 'lucide-react';
|
||||
import { Ban, CalendarDays, MessageSquareText, Plus } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
import InputError from '@/components/input-error';
|
||||
import { PageHeading } from '@/components/page-heading';
|
||||
@@ -22,7 +22,11 @@ export default function ReservationsIndex({
|
||||
reservations: Paginated<Reservation>;
|
||||
}) {
|
||||
const [selected, setSelected] = useState<Reservation | null>(null);
|
||||
const [clarification, setClarification] = useState<Reservation | null>(
|
||||
null,
|
||||
);
|
||||
const cancelForm = useForm({ reason: '' });
|
||||
const clarificationForm = useForm({ response: '' });
|
||||
const format = new Intl.DateTimeFormat('pt-PT', {
|
||||
dateStyle: 'medium',
|
||||
timeStyle: 'short',
|
||||
@@ -54,6 +58,25 @@ export default function ReservationsIndex({
|
||||
});
|
||||
}
|
||||
|
||||
function openClarification(reservation: Reservation) {
|
||||
clarificationForm.reset();
|
||||
clarificationForm.clearErrors();
|
||||
setClarification(reservation);
|
||||
}
|
||||
|
||||
function submitClarification(event: React.FormEvent) {
|
||||
event.preventDefault();
|
||||
|
||||
if (!clarification) {
|
||||
return;
|
||||
}
|
||||
|
||||
clarificationForm.post(`/requisicoes/${clarification.uuid}/responder`, {
|
||||
preserveScroll: true,
|
||||
onSuccess: () => setClarification(null),
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head title="As minhas requisições" />
|
||||
@@ -87,7 +110,20 @@ export default function ReservationsIndex({
|
||||
<span className="font-mono text-sm font-medium">
|
||||
{reservation.reference}
|
||||
</span>
|
||||
<div>
|
||||
<div className="flex flex-col items-start gap-1">
|
||||
{reservation.status ===
|
||||
'awaiting_information' && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
openClarification(reservation)
|
||||
}
|
||||
>
|
||||
<MessageSquareText /> Responder
|
||||
</Button>
|
||||
)}
|
||||
<p className="text-sm font-medium">
|
||||
{reservation.items
|
||||
.map((item) => item.asset.name)
|
||||
@@ -232,6 +268,61 @@ export default function ReservationsIndex({
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Dialog
|
||||
open={clarification !== null}
|
||||
onOpenChange={(open) => !open && setClarification(null)}
|
||||
>
|
||||
<DialogContent>
|
||||
<form onSubmit={submitClarification}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
Prestar esclarecimentos
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
{clarification?.decision_reason ??
|
||||
'O aprovador pediu informação adicional para poder decidir.'}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="my-5">
|
||||
<Label htmlFor="clarification-response">
|
||||
Resposta
|
||||
</Label>
|
||||
<textarea
|
||||
id="clarification-response"
|
||||
value={clarificationForm.data.response}
|
||||
onChange={(event) =>
|
||||
clarificationForm.setData(
|
||||
'response',
|
||||
event.target.value,
|
||||
)
|
||||
}
|
||||
rows={5}
|
||||
className="mt-2 w-full rounded-md border bg-transparent px-3 py-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||
autoFocus
|
||||
/>
|
||||
<InputError
|
||||
message={clarificationForm.errors.response}
|
||||
/>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={() => setClarification(null)}
|
||||
>
|
||||
Voltar
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={clarificationForm.processing}
|
||||
>
|
||||
<MessageSquareText /> Enviar resposta
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user