117 lines
4.6 KiB
TypeScript
117 lines
4.6 KiB
TypeScript
import React from "react";
|
|
import AppLayout from "@/layouts/app-layout";
|
|
import { router, useForm } from "@inertiajs/react";
|
|
import { Badge, Button, Card, Container, Group, Title } from "@mantine/core";
|
|
import { IconArrowLeft } from "@tabler/icons-react";
|
|
import { Link } from "@inertiajs/react";
|
|
import InvoiceForm, { InvoiceFormValues } from "@/forms/account/InvoiceForm";
|
|
import { ClientInvoice } from "@/types";
|
|
|
|
type InvoiceOptionSource = Pick<ClientInvoice, "id" | "invoice_no"> & {
|
|
linked_invoice_id?: number | null;
|
|
};
|
|
|
|
interface Props {
|
|
invoice: ClientInvoice & { client?: { customer_id: string } };
|
|
availableInvoices: InvoiceOptionSource[];
|
|
}
|
|
|
|
export default function Page({ invoice, availableInvoices }: Props) {
|
|
const form = useForm<InvoiceFormValues>({
|
|
invoice_no: invoice.invoice_no ?? "",
|
|
linked_invoice_id: invoice.linked_invoice_id ? String(invoice.linked_invoice_id) : "",
|
|
is_credit_card: !!invoice.is_credit_card,
|
|
is_paid: !!invoice.is_paid,
|
|
payment_no: invoice.payment_no ?? "",
|
|
start_date: invoice.start_date ?? "",
|
|
end_date: invoice.end_date ?? "",
|
|
amount: invoice.amount !== null && invoice.amount !== undefined ? String(invoice.amount) : "",
|
|
management_fee:
|
|
invoice.management_fee !== null && invoice.management_fee !== undefined
|
|
? String(invoice.management_fee)
|
|
: "",
|
|
media_fee:
|
|
invoice.media_fee !== null && invoice.media_fee !== undefined
|
|
? String(invoice.media_fee)
|
|
: "",
|
|
tax_percent:
|
|
invoice.tax_percent !== null && invoice.tax_percent !== undefined
|
|
? String(invoice.tax_percent)
|
|
: "",
|
|
total_spending:
|
|
invoice.total_spending !== null && invoice.total_spending !== undefined
|
|
? String(invoice.total_spending)
|
|
: "",
|
|
client_id: invoice.client_id ? String(invoice.client_id) : undefined,
|
|
customer_id: invoice.client?.customer_id ?? "",
|
|
});
|
|
const isApproved = !!invoice.approved_at;
|
|
|
|
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
|
event.preventDefault();
|
|
const totalSpending = form.data.total_spending
|
|
? parseFloat(form.data.total_spending)
|
|
: null;
|
|
|
|
form.transform((data) => ({
|
|
...data,
|
|
linked_invoice_id: data.linked_invoice_id || null,
|
|
is_credit_card: !!data.is_credit_card,
|
|
is_paid: !!data.is_paid,
|
|
payment_no: data.payment_no || null,
|
|
start_date: data.start_date || null,
|
|
end_date: data.end_date || null,
|
|
amount: parseFloat(data.amount) || 0,
|
|
management_fee: parseFloat(data.management_fee) || 0,
|
|
media_fee: parseFloat(data.media_fee) || 0,
|
|
tax_percent: parseFloat(data.tax_percent) || 0,
|
|
total_spending: totalSpending,
|
|
}));
|
|
|
|
form.put(route("client-invoices.update", { invoice: invoice.id }));
|
|
};
|
|
|
|
const handleApprove = () => {
|
|
router.patch(route("client-invoices.approve", { invoice: invoice.id }));
|
|
};
|
|
|
|
const invoiceOptions = availableInvoices.map((item) => ({
|
|
value: String(item.id),
|
|
label: item.invoice_no,
|
|
}));
|
|
|
|
return (
|
|
<AppLayout>
|
|
<Container size="lg" px="xs">
|
|
<Group position="apart" mb="md">
|
|
<Group gap="sm">
|
|
<Title order={2}>Edit invoice</Title>
|
|
<Badge color={isApproved ? "green" : "yellow"} variant="light">
|
|
{isApproved ? "Approved" : "Pending approval"}
|
|
</Badge>
|
|
</Group>
|
|
<Group gap="sm">
|
|
{!isApproved && (
|
|
<Button color="green" onClick={handleApprove}>
|
|
Approve invoice
|
|
</Button>
|
|
)}
|
|
<Button
|
|
component={Link}
|
|
href={route("google-ads.accounts.show", { id: invoice.client?.customer_id ?? "" })}
|
|
leftIcon={<IconArrowLeft size={16} />}
|
|
variant="outline"
|
|
>
|
|
Back to account
|
|
</Button>
|
|
</Group>
|
|
</Group>
|
|
|
|
<Card withBorder>
|
|
<InvoiceForm form={form} onSubmit={handleSubmit} invoiceOptions={invoiceOptions} />
|
|
</Card>
|
|
</Container>
|
|
</AppLayout>
|
|
);
|
|
}
|