// src/sections/invoice/invoice-new-edit-form.tsx 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'; 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; export const NewInvoiceSchema = zod .object({ 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!' }), 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(), }) ), invoiceNumber: zod.string(), invoiceFrom: zod.custom().nullable(), invoiceTo: schemaHelper.nullableInput(zod.custom(), { message: 'Invoice to is required!', }), sent: zod.number().default(0), createDate: 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), { message: 'Due date cannot be earlier than create date!', path: ['dueDate'], }); // ---------------------------------------------------------------------- type Props = { currentInvoice?: IInvoiceItem; }; export function InvoiceNewEditForm({ currentInvoice }: Props) { const router = useRouter(); const { t } = useTranslation(); const loadingSave = useBoolean(); const loadingSend = useBoolean(); const defaultValues: NewInvoiceSchemaType = { id: '', sent: 0, 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({ 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 { if (currentInvoice) { data.dueDate = '2029-01-01'; 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); loadingSend.onFalse(); } }); return (
); }