185 lines
7.0 KiB
TypeScript
185 lines
7.0 KiB
TypeScript
import Button from '@/components/Button'
|
||
import Input from '@/components/Input';
|
||
import { clx } from '@/helpers/utils';
|
||
import { useFormik } from 'formik';
|
||
import { AddSquare } from 'iconsax-react'
|
||
import { useState, type FC } from 'react'
|
||
import type { CreateProductType } from './types/Types';
|
||
import * as Yup from 'yup'
|
||
import Textarea from '@/components/Textarea';
|
||
import CategoriesSelect from './components/CategoriesSelect';
|
||
import SwitchComponent from '@/components/Switch';
|
||
import UploadBoxDraggble from '@/components/UploadBoxDraggble';
|
||
import { useMultiUpload } from '../uploader/hooks/useUploader';
|
||
import { useCreateProduct } from './hooks/useProductData';
|
||
import { toast } from 'react-toastify';
|
||
import type { ErrorType } from '@/helpers/types';
|
||
import { extractErrorMessage } from '@/config/func';
|
||
import { useNavigate } from 'react-router-dom';
|
||
|
||
const CreateProduct: FC = () => {
|
||
|
||
const navigate = useNavigate()
|
||
const [files, setFiles] = useState<File[]>([])
|
||
const { mutate: upload, isPending: isUploading } = useMultiUpload()
|
||
const { mutate: createProduct, isPending } = useCreateProduct()
|
||
|
||
const handleSave = (values: CreateProductType) => {
|
||
createProduct(values, {
|
||
onSuccess: () => {
|
||
toast.success('عملیات با موفقیت انجام شد')
|
||
formik.resetForm()
|
||
navigate(-1)
|
||
},
|
||
onError: (error: ErrorType) => {
|
||
toast.error(extractErrorMessage(error))
|
||
}
|
||
})
|
||
}
|
||
|
||
const formik = useFormik<CreateProductType>({
|
||
initialValues: {
|
||
categoryId: '',
|
||
desc: '',
|
||
images: [],
|
||
isActive: true,
|
||
linkUrl: '',
|
||
order: 1,
|
||
quantities: [],
|
||
title: ''
|
||
},
|
||
validationSchema: Yup.object({
|
||
categoryId: Yup.string().required('این فیلد اجباری می باشد.'),
|
||
title: Yup.string().required('این فیلد اجباری می باشد.'),
|
||
}),
|
||
onSubmit: (values) => {
|
||
if (files.length > 0) {
|
||
upload(files, {
|
||
onSuccess: (data) => {
|
||
const imagesUrl: string[] = []
|
||
data.data?.map((item) => {
|
||
imagesUrl.push(item.url)
|
||
})
|
||
values.images = imagesUrl
|
||
handleSave(values)
|
||
}
|
||
})
|
||
} else {
|
||
handleSave(values)
|
||
}
|
||
}
|
||
})
|
||
|
||
const handleQuantities = (value: number) => {
|
||
const array = [...formik.values.quantities]
|
||
const index: number = array.findIndex(o => o === value)
|
||
if (index > -1) {
|
||
array.splice(index, 1)
|
||
} else {
|
||
array.push(value)
|
||
}
|
||
formik.setFieldValue('quantities', array)
|
||
}
|
||
|
||
return (
|
||
<div className='mt-5'>
|
||
<div className='flex justify-between items-center'>
|
||
|
||
<h1 className='text-lg font-light'>محصول جدید</h1>
|
||
<Button
|
||
className='w-fit px-6'
|
||
onClick={() => formik.handleSubmit()}
|
||
isLoading={isUploading || isPending}
|
||
>
|
||
<div className='flex gap-1.5'>
|
||
<AddSquare size={18} color='black' />
|
||
<div className='text-[13px] font-light'>محصول جدید</div>
|
||
</div>
|
||
</Button>
|
||
</div>
|
||
|
||
<div className='flex gap-6'>
|
||
<div className='mt-8 bg-white p-6 rounded-3xl flex-1'>
|
||
<div className='font-light'>
|
||
اطلاعات محصول
|
||
</div>
|
||
|
||
<div className='mt-6 rowTwoInput'>
|
||
<Input
|
||
label='عنوان محصول'
|
||
{...formik.getFieldProps('title')}
|
||
error_text={formik.touched.title && formik.errors.title ? formik.errors.title : ''}
|
||
/>
|
||
<Input
|
||
label='لینک در وبسایت'
|
||
{...formik.getFieldProps('linkUrl')}
|
||
|
||
/>
|
||
</div>
|
||
|
||
<div className='mt-6 rowTwoInput'>
|
||
<CategoriesSelect
|
||
{...formik.getFieldProps('categoryId')}
|
||
error_text={formik.touched.title && formik.errors.title ? formik.errors.title : ''}
|
||
/>
|
||
|
||
<Input
|
||
label='ترتیب'
|
||
{...formik.getFieldProps('order')}
|
||
/>
|
||
</div>
|
||
|
||
<div className='mt-6'>
|
||
<Textarea
|
||
label='توضیحات'
|
||
{...formik.getFieldProps('desc')}
|
||
/>
|
||
</div>
|
||
|
||
<div className='mt-6'>
|
||
<div>بسته تعداد</div>
|
||
<div className='mt-2.5 flex gap-4'>
|
||
{
|
||
[100, 150, 200, 250, 300, 350, 500, 1000].map((item) => {
|
||
return (
|
||
<div key={item} className={clx(
|
||
'h-8 w-[72px] cursor-pointer text-sm rounded-lg border border-[#C3C7DD] flex items-center justify-center',
|
||
formik.values.quantities.includes(item) && 'border-primary'
|
||
)}
|
||
onClick={() => handleQuantities(item)}
|
||
>
|
||
{item}
|
||
</div>
|
||
)
|
||
})
|
||
}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className='bg-white p-6 mt-8 rounded-3xl w-[250px]'>
|
||
<div className='flex justify-between items-center'>
|
||
<div>وضعیت</div>
|
||
<SwitchComponent
|
||
active={formik.values.isActive}
|
||
onChange={(value) => formik.setFieldValue('isActive', value)}
|
||
/>
|
||
</div>
|
||
|
||
<div className='mt-6'>
|
||
<div className='text-sm mb-4'>
|
||
تصاویر محصول
|
||
</div>
|
||
<UploadBoxDraggble
|
||
label='آپلود تصاویر'
|
||
onChange={setFiles}
|
||
isMultiple
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default CreateProduct; |