import sum from 'lodash/sum'; import { useCallback, useEffect } from 'react'; import { useFormContext, useFieldArray } from 'react-hook-form'; // @mui import Box from '@mui/material/Box'; import Stack from '@mui/material/Stack'; import Button from '@mui/material/Button'; import Divider from '@mui/material/Divider'; import MenuItem from '@mui/material/MenuItem'; import Typography from '@mui/material/Typography'; import { inputBaseClasses } from '@mui/material/InputBase'; import InputAdornment from '@mui/material/InputAdornment'; // utils import { fCurrency } from 'src/utils/format-number'; // types import { InvoiceItem } from 'src/schemas'; // components import Iconify from 'src/components/iconify'; import { RHFSelect, RHFTextField } from 'src/components/hook-form'; import { useGetServices } from 'src/api/service'; // ---------------------------------------------------------------------- export default function InvoiceNewEditDetails() { const { control, setValue, watch, resetField } = useFormContext(); const { fields, append, remove } = useFieldArray({ control, name: 'items', }); const { services: invoiceServices } = useGetServices(); const values = watch(); const currencySign = values.currency === 'EUR' ? '€' : '$'; const totalOnRow = values.items.map((item: InvoiceItem) => item.quantity * item.price); const subTotal = sum(totalOnRow); const taxAmount = (values.taxes / 100) * subTotal; const totalAmount = subTotal - values.discount + taxAmount; useEffect(() => { setValue('subTotal', subTotal); }, [setValue, subTotal]); useEffect(() => { setValue('totalAmount', totalAmount); }, [setValue, totalAmount]); const handleAdd = () => { append({ title: '', description: '', service: '', quantity: 1, price: 0, total: 0, }); }; const handleRemove = (index: number) => { remove(index); }; const handleClearService = useCallback( (index: number) => { resetField(`items[${index}].quantity`); resetField(`items[${index}]`); resetField(`items[${index}].total`); }, [resetField] ); const handleSelectService = useCallback( (index: number, option: string) => { const service = invoiceServices.find((service) => service.id === option); if (!service) return; const quantityType = values.quantityType?.toLowerCase(); let price = 0; switch (quantityType) { case 'sprint': price = service.sprint; break; case 'hour': price = service.hour; break; case 'month': price = service.month; break; default: price = 0; } setValue(`items[${index}].price`, price); setValue(`items[${index}].total`, values.items[index].quantity * price); }, [setValue, values.items, values.quantityType, invoiceServices] ); const handleChangeQuantity = useCallback( (event: React.ChangeEvent, index: number) => { setValue(`items[${index}].quantity`, Number(event.target.value)); setValue( `items[${index}].total`, values.items.map((item: InvoiceItem) => item.quantity * item.price)[index] ); }, [setValue, values.items] ); const handleChangePrice = useCallback( (event: React.ChangeEvent, index: number) => { setValue(`items[${index}].price`, Number(event.target.value)); setValue( `items[${index}].total`, values.items.map((item: InvoiceItem) => item.quantity * item.price)[index] ); }, [setValue, values.items] ); const renderTotal = ( Subtotal {fCurrency(subTotal, values.currency) || '-'} {/* Discount {values.discount ? `- ${fCurrency(values.discount, values.currency)}` : '-'} Taxes {values.taxes ? fCurrency(values.taxes, values.currency) : '-'} */} Total {fCurrency(totalAmount, values.currency) || '-'} ); return ( Details: } spacing={3}> {fields.map((item, index) => ( {invoiceServices?.length && ( handleClearService(index)} sx={{ fontStyle: 'italic', color: 'text.secondary' }} > None {invoiceServices.map((service) => ( handleSelectService(index, service.id)} > {service.name} ))} )} handleChangeQuantity(event, index)} InputLabelProps={{ shrink: true }} sx={{ maxWidth: { md: 96 } }} /> handleChangePrice(event, index)} InputProps={{ startAdornment: ( {currencySign} ), }} sx={{ maxWidth: { md: 96 } }} /> handleChangePrice(event, index)} InputProps={{ startAdornment: ( {currencySign} ), }} sx={{ maxWidth: { md: 104 }, [`& .${inputBaseClasses.input}`]: { textAlign: { md: 'right' }, }, }} /> ))} {renderTotal} ); }