init commit,

This commit is contained in:
louiscklaw
2025-05-28 09:55:51 +08:00
commit efe70ceb69
8042 changed files with 951668 additions and 0 deletions

View File

@@ -0,0 +1,171 @@
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';
import { today, fIsAfter } from 'src/utils/format-time';
import { _addressBooks } from 'src/_mock';
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';
// ----------------------------------------------------------------------
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!' } }),
items: zod.array(
zod.object({
title: zod.string().min(1, { message: 'Title is required!' }),
service: zod.string().min(1, { message: 'Service is required!' }),
quantity: zod.number().int().positive().min(1, { message: 'Quantity must be more than 0' }),
// Not required
price: zod.number(),
total: zod.number(),
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(),
})
.refine((data) => !fIsAfter(data.createDate, data.dueDate), {
message: 'Due date cannot be earlier than create date!',
path: ['dueDate'],
});
// ----------------------------------------------------------------------
type Props = {
currentInvoice?: IInvoice;
};
export function InvoiceNewEditForm({ currentInvoice }: Props) {
const router = useRouter();
const loadingSave = useBoolean();
const loadingSend = useBoolean();
const defaultValues: NewInvoiceSchemaType = {
invoiceNumber: 'INV-1990',
createDate: today(),
dueDate: null,
taxes: 0,
shipping: 0,
status: 'draft',
discount: 0,
invoiceFrom: _addressBooks[0],
invoiceTo: null,
subtotal: 0,
totalAmount: 0,
items: [defaultItem],
};
const methods = useForm<NewInvoiceSchemaType>({
mode: 'all',
resolver: zodResolver(NewInvoiceSchema),
defaultValues,
values: currentInvoice,
});
const {
reset,
handleSubmit,
formState: { isSubmitting },
} = methods;
const handleSaveAsDraft = handleSubmit(async (data) => {
loadingSave.onTrue();
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));
} catch (error) {
console.error(error);
loadingSave.onFalse();
}
});
const handleCreateAndSend = handleSubmit(async (data) => {
loadingSend.onTrue();
try {
await new Promise((resolve) => setTimeout(resolve, 500));
reset();
loadingSend.onFalse();
router.push(paths.dashboard.invoice.root);
console.info('DATA', JSON.stringify(data, null, 2));
} catch (error) {
console.error(error);
loadingSend.onFalse();
}
});
return (
<Form methods={methods}>
<Card>
<InvoiceNewEditAddress />
<InvoiceNewEditStatusDate />
<InvoiceNewEditDetails />
</Card>
<Box
sx={{
mt: 3,
gap: 2,
display: 'flex',
justifyContent: 'flex-end',
}}
>
<Button
color="inherit"
size="large"
variant="outlined"
loading={loadingSave.value && isSubmitting}
onClick={handleSaveAsDraft}
>
Save as draft
</Button>
<Button
size="large"
variant="contained"
loading={loadingSend.value && isSubmitting}
onClick={handleCreateAndSend}
>
{currentInvoice ? 'Update' : 'Create'} & send
</Button>
</Box>
</Form>
);
}