Files
negareh-admin/src/pages/order/components/Order.tsx
T
2026-02-01 10:02:45 +03:30

208 lines
7.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState, type ChangeEvent, type FC } from 'react'
import Button from '@/components/Button'
import Input from '@/components/Input'
import Select from '@/components/Select'
import UploadBox from '@/components/UploadBox'
import VoiceRecorder from '@/components/VoiceRecorder'
import { COLORS } from '@/constants/colors'
import { AddSquare, Edit } from 'iconsax-react'
import { useFormik } from 'formik'
import * as Yup from 'yup'
import type { AttachmentsType, CreateOrderType } from '../types/Types'
import { useGetAttributes, useGetProducts } from '../hooks/useOrderData'
import ManageAttribute from './ManageAttribute'
import { useMultiUpload, useSingleUpload } from '@/pages/uploader/hooks/useUploader'
import { useOrderStore } from '../store/OrderStore'
import { clx } from '@/helpers/utils'
import ProductsSelect from './ProductsSelect'
import type { ProductType } from '@/pages/product/types/Types'
type Props = {
addNewItem: () => void,
}
const Order: FC<Props> = ({ addNewItem }) => {
const { data } = useGetProducts()
const { setItems, items } = useOrderStore()
const [indexOrder, setIndexOrder] = useState<number>(-1)
const [isEditMode, setIsEditMode] = useState<boolean>(false)
const [productSelected, setProductSelected] = useState<ProductType>()
const [voiceFile, setVoiceFile] = useState<File>()
const [files, setFiles] = useState<File[]>([])
const { data: attributes } = useGetAttributes(productSelected?.id)
const singleUpload = useSingleUpload()
const multiUpload = useMultiUpload()
const formik = useFormik<CreateOrderType>({
initialValues: {
productId: undefined,
attachments: [],
quantity: undefined,
description: '',
attributes: [],
discount: undefined,
unitPrice: undefined,
},
validationSchema: Yup.object({
productId: Yup.number().required('این فیلد اجباری می باشد'),
quantity: Yup.number().required('این فیلد اجباری می باشد'),
unitPrice: Yup.number().required('این فیلد اجباری می باشد'),
}),
onSubmit: async (values) => {
const attachments: AttachmentsType[] = []
if (files.length) {
await multiUpload.mutateAsync(files, {
onSuccess: (data) => {
data?.data?.map((item) => {
attachments.push({
type: 'uploads_attach',
url: item.url
})
})
}
})
}
if (voiceFile) {
await singleUpload.mutateAsync(voiceFile, {
onSuccess: (data) => {
attachments.push({
type: 'voice',
url: data?.data?.url
})
}
})
}
if (indexOrder === -1) {
values.attachments = attachments
setIndexOrder(items.length)
setItems([...items, values])
addNewItem()
setIsEditMode(true)
} else {
if (values.attachments.length) {
values.attachments = [...values.attachments, ...attachments]
}
const items_edit = [...items]
items_edit[indexOrder] = values
setItems(items_edit)
}
}
})
const handleChange = (e: ChangeEvent<HTMLSelectElement>) => {
const productId = e.target.value
const product = data?.data?.find(o => Number(o.id) === Number(productId))
if (product) {
if (product.quantities[0] !== 0) {
product.quantities.unshift(0)
}
setProductSelected(product)
formik.setFieldValue('productId', productId)
}
}
return (
<div className='bg-white rounded-3xl p-6 mt-8'>
<div className='font-light'>اطلاعات سفارش</div>
<div className='mt-6 rowTwoInput'>
<ProductsSelect
onChange={handleChange}
error_text={formik.touched.productId && formik.errors.productId ? formik.errors.productId : ''}
/>
</div>
<div>
<ManageAttribute
attributes={attributes?.data}
formik={formik}
/>
</div>
<div className='mt-6 rowTwoInput'>
<Select
items={productSelected?.quantities?.map((item) => {
return {
label: item === 0 ? 'انتخاب دلخواه' : item + '',
value: item + ''
}
}) || []}
label='تعداد'
placeholder='انتخاب'
{...formik.getFieldProps('quantity')}
error_text={formik.touched.quantity && formik.errors.quantity ? formik.errors.quantity : ''}
/>
<Input
label='تعداد دلخواه'
readOnly={Number(formik.values.quantity) !== 0}
{...formik.getFieldProps('quantity')}
type='number'
error_text={formik.touched.quantity && formik.errors.quantity ? formik.errors.quantity : ''}
/>
</div>
<div className='rowTwoInput mt-6'>
<Input
{...formik.getFieldProps('unitPrice')}
label='مبلغ واحد'
error_text={formik.touched.unitPrice && formik.errors.unitPrice ? formik.errors.unitPrice : ''}
/>
<Input
{...formik.getFieldProps('discount')}
label='مبلغ تخفیف به تومان'
/>
</div>
<div className='mt-6'>
<VoiceRecorder
onChange={(value) => formik.setFieldValue('description', value)}
label='پیام صوتی'
onRecordingComplete={(blob) => {
const file = new File([blob], "recording.wav", { type: blob.type });
setVoiceFile(file);
}}
/>
</div>
<div className='mt-6'>
<UploadBox
label='آپلود فایل'
isMultiple
onChange={setFiles}
/>
</div>
<div className='mt-6 flex justify-end'>
<Button
className={clx(
'bg-transparent border border-primary text-primary w-fit px-6',
isEditMode && 'bg-transparent border-[#3B82F6] text-[#3B82F6] '
)}
onClick={() => formik.handleSubmit()}
isLoading={singleUpload.isPending || multiUpload.isPending}
>
<div className='flex gap-1'>
{
isEditMode ?
<Edit color='#3B82F6' size={20} />
:
<AddSquare color={COLORS.primary} size={20} />
}
<div>
{isEditMode ? 'ویرایش کردن' : 'اضافه کردن'}
</div>
</div>
</Button>
</div>
</div>
)
}
export default Order