"feat: enhance invoice management with schema updates, seed data, and new APIs"
This commit is contained in:
@@ -1,16 +1,4 @@
|
||||
import type { IInvoice } from 'src/types/invoice';
|
||||
|
||||
import { z as zod } from 'zod';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useBoolean } from 'minimal-shared/hooks';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
|
||||
import Box from '@mui/material/Box';
|
||||
import Card from '@mui/material/Card';
|
||||
import Button from '@mui/material/Button';
|
||||
|
||||
import { paths } from 'src/routes/paths';
|
||||
import { useRouter } from 'src/routes/hooks';
|
||||
// src/sections/invoice/invoice-new-edit-form.tsx
|
||||
|
||||
import { today, fIsAfter } from 'src/utils/format-time';
|
||||
|
||||
@@ -21,18 +9,37 @@ import { Form, schemaHelper } from 'src/components/hook-form';
|
||||
import { InvoiceNewEditAddress } from './invoice-new-edit-address';
|
||||
import { InvoiceNewEditStatusDate } from './invoice-new-edit-status-date';
|
||||
import { defaultItem, InvoiceNewEditDetails } from './invoice-new-edit-details';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useBoolean } from 'minimal-shared/hooks';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
|
||||
import Box from '@mui/material/Box';
|
||||
import Button from '@mui/material/Button';
|
||||
import Card from '@mui/material/Card';
|
||||
|
||||
import { toast } from 'src/components/snackbar';
|
||||
import { useRouter } from 'src/routes/hooks';
|
||||
import { paths } from 'src/routes/paths';
|
||||
import type { IInvoiceItem } from 'src/types/invoice';
|
||||
import { fileToBase64 } from 'src/utils/file-to-base64';
|
||||
import { z as zod } from 'zod';
|
||||
import { saveInvoice } from 'src/actions/invoice';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export type NewInvoiceSchemaType = zod.infer<typeof NewInvoiceSchema>;
|
||||
|
||||
export const NewInvoiceSchema = zod
|
||||
.object({
|
||||
invoiceTo: schemaHelper.nullableInput(zod.custom<IInvoice['invoiceTo']>(), {
|
||||
message: 'Invoice to is required!',
|
||||
}),
|
||||
createDate: schemaHelper.date({ message: { required: 'Create date is required!' } }),
|
||||
dueDate: schemaHelper.date({ message: { required: 'Due date is required!' } }),
|
||||
id: zod.string(),
|
||||
taxes: zod.number(),
|
||||
status: zod.string(),
|
||||
discount: zod.number(),
|
||||
shipping: zod.number(),
|
||||
subtotal: zod.number(),
|
||||
totalAmount: zod.number(),
|
||||
|
||||
items: zod.array(
|
||||
zod.object({
|
||||
title: zod.string().min(1, { message: 'Title is required!' }),
|
||||
@@ -44,17 +51,18 @@ export const NewInvoiceSchema = zod
|
||||
description: zod.string(),
|
||||
})
|
||||
),
|
||||
// Not required
|
||||
taxes: zod.number(),
|
||||
status: zod.string(),
|
||||
discount: zod.number(),
|
||||
shipping: zod.number(),
|
||||
subtotal: zod.number(),
|
||||
totalAmount: zod.number(),
|
||||
invoiceNumber: zod.string(),
|
||||
invoiceFrom: zod.custom<IInvoice['invoiceFrom']>().nullable(),
|
||||
invoiceFrom: zod.custom<IInvoiceItem['invoiceFrom']>().nullable(),
|
||||
|
||||
invoiceTo: schemaHelper.nullableInput(zod.custom<IInvoiceItem['invoiceTo']>(), {
|
||||
message: 'Invoice to is required!',
|
||||
}),
|
||||
sent: zod.number().default(0),
|
||||
createdDate: schemaHelper.date({ message: { required: 'Create date is required!' } }),
|
||||
dueDate: schemaHelper.date({ message: { required: 'Due date is required!' } }),
|
||||
// Not required
|
||||
})
|
||||
.refine((data) => !fIsAfter(data.createDate, data.dueDate), {
|
||||
.refine((data) => !fIsAfter(data.createdDate, data.dueDate), {
|
||||
message: 'Due date cannot be earlier than create date!',
|
||||
path: ['dueDate'],
|
||||
});
|
||||
@@ -62,18 +70,19 @@ export const NewInvoiceSchema = zod
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type Props = {
|
||||
currentInvoice?: IInvoice;
|
||||
currentInvoice?: IInvoiceItem;
|
||||
};
|
||||
|
||||
export function InvoiceNewEditForm({ currentInvoice }: Props) {
|
||||
const router = useRouter();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const loadingSave = useBoolean();
|
||||
const loadingSend = useBoolean();
|
||||
|
||||
const defaultValues: NewInvoiceSchemaType = {
|
||||
invoiceNumber: 'INV-1990',
|
||||
createDate: today(),
|
||||
createdDate: today(),
|
||||
dueDate: null,
|
||||
taxes: 0,
|
||||
shipping: 0,
|
||||
@@ -105,6 +114,7 @@ export function InvoiceNewEditForm({ currentInvoice }: Props) {
|
||||
try {
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
reset();
|
||||
|
||||
loadingSave.onFalse();
|
||||
router.push(paths.dashboard.invoice.root);
|
||||
console.info('DATA', JSON.stringify(data, null, 2));
|
||||
@@ -118,10 +128,15 @@ export function InvoiceNewEditForm({ currentInvoice }: Props) {
|
||||
loadingSend.onTrue();
|
||||
|
||||
try {
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
reset();
|
||||
if (currentInvoice) {
|
||||
await saveInvoice(currentInvoice.id, data);
|
||||
}
|
||||
|
||||
loadingSend.onFalse();
|
||||
toast.success(currentInvoice ? 'Update success!' : 'Create success!');
|
||||
|
||||
router.push(paths.dashboard.invoice.root);
|
||||
|
||||
console.info('DATA', JSON.stringify(data, null, 2));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@@ -151,6 +166,7 @@ export function InvoiceNewEditForm({ currentInvoice }: Props) {
|
||||
color="inherit"
|
||||
size="large"
|
||||
variant="outlined"
|
||||
disabled={loadingSave.value && isSubmitting}
|
||||
loading={loadingSave.value && isSubmitting}
|
||||
onClick={handleSaveAsDraft}
|
||||
>
|
||||
@@ -160,6 +176,7 @@ export function InvoiceNewEditForm({ currentInvoice }: Props) {
|
||||
<Button
|
||||
size="large"
|
||||
variant="contained"
|
||||
disabled={loadingSend.value && isSubmitting}
|
||||
loading={loadingSend.value && isSubmitting}
|
||||
onClick={handleCreateAndSend}
|
||||
>
|
||||
|
Reference in New Issue
Block a user