change food to product name

This commit is contained in:
hamid zarghami
2026-02-09 14:04:21 +03:30
parent eae2ba0e7a
commit 687fc1e6c2
28 changed files with 186 additions and 194 deletions
+207
View File
@@ -0,0 +1,207 @@
import { type FC, useState, useEffect } from 'react'
import { useFormik } from 'formik'
import * as Yup from 'yup'
import { TickCircle } from 'iconsax-react'
import { toast } from 'react-toastify'
import { useNavigate, useParams } from 'react-router-dom'
import Button from '@/components/Button'
import CreateProductSidebar from './components/CreateProductSidebar'
import BasicInfoSection from './components/BasicInfoSection'
import ProductContentSection from './components/ProductContentSection'
import MealTimesSection from './components/MealTimesSection'
import WeekDaysSection from './components/WeekDaysSection'
import ServiceOptionsSection from './components/ServiceOptionsSection'
import type { CreateProductType } from './types/Types'
import { useUpdateProduct, useGetProductDetails, useGetCategories } from './hooks/useProductData'
import { useMultipleUpload } from '../uploader/hooks/useUploaderData'
import { Pages } from '@/config/Pages'
import type { ErrorType } from '@/helpers/types'
import { extractErrorMessage } from '@/config/func'
const UpdateProduct: FC = () => {
const { id } = useParams<{ id: string }>()
const { data: productData, isLoading } = useGetProductDetails(id || '')
const { data: categoriesData } = useGetCategories()
const [isActive, setIsActive] = useState<boolean>(true)
const [isSpecial, setIsSpecial] = useState<boolean>(false)
const [imageFiles, setImageFiles] = useState<File[]>([])
const [existingImages, setExistingImages] = useState<string[]>([])
const { mutate: updateProduct, isPending } = useUpdateProduct()
const { mutate: multipleUpload, isPending: isUploading } = useMultipleUpload()
const navigate = useNavigate()
const categories = categoriesData?.data?.map(category => ({
label: category.title,
value: category.id
})) || []
const product = productData?.data
const formik = useFormik<CreateProductType>({
initialValues: {
title: '',
desc: '',
content: [],
categoryId: '',
price: 0,
discount: 0,
prepareTime: 0,
weekDays: [],
mealTypes: [],
pickupServe: false,
inPlaceServe: false,
isActive: true,
images: [],
isSpecialOffer: false,
dailyStock: 0,
order: 0
},
validationSchema: Yup.object().shape({
title: Yup.string().required('نام کالا الزامی است'),
categoryId: Yup.string().required('دسته‌بندی الزامی است'),
price: Yup.number().required('قیمت الزامی است').min(0, 'قیمت باید مثبت باشد'),
prepareTime: Yup.number().required('زمان آماده‌سازی الزامی است').min(0, 'زمان آماده‌سازی باید مثبت باشد'),
discount: Yup.number().min(0, 'تخفیف باید مثبت باشد'),
dailyStock: Yup.number().required('موجودی روزانه الزامی است').min(0, 'موجودی روزانه باید مثبت باشد'),
content: Yup.array().of(Yup.string()),
weekDays: Yup.array().of(Yup.number()),
mealTypes: Yup.array().of(Yup.string())
}),
onSubmit: (values) => {
if (!id) {
toast.error('شناسه کالا یافت نشد')
return
}
const submitProduct = (newImageUrls: string[] = []) => {
const allImages = [...values.images, ...newImageUrls]
const productData: CreateProductType = {
...values,
isActive,
isSpecialOffer: isSpecial,
images: allImages,
content: values.content.filter(item => item && item.trim().length > 0)
}
updateProduct({ id, params: productData }, {
onSuccess: () => {
toast.success('کالا با موفقیت به‌روزرسانی شد')
navigate(Pages.products.list)
},
onError: (error: ErrorType) => {
toast.error(extractErrorMessage(error))
}
})
}
if (imageFiles.length > 0) {
multipleUpload(imageFiles, {
onSuccess: (response) => {
const imageUrls = response?.data?.map(item => item.url) || []
submitProduct(imageUrls)
},
onError: (error: ErrorType) => {
toast.error(error?.response?.data?.error?.message[0] || 'خطا در آپلود تصاویر')
}
})
} else {
submitProduct()
}
}
})
useEffect(() => {
if (product) {
formik.setValues({
title: product.title || '',
desc: product.desc || '',
content: product.content || [],
categoryId: product.category?.id || '',
price: product.price || 0,
discount: product.discount || 0,
prepareTime: product.prepareTime || 0,
weekDays: product.weekDays || [],
mealTypes: product.mealTypes || [],
pickupServe: product.pickupServe || false,
inPlaceServe: product.inPlaceServe || false,
isActive: product.isActive || false,
images: product.images || [],
isSpecialOffer: product.isSpecialOffer || false,
dailyStock: product.inventory?.totalStock || 0,
order: product.order || 0
})
setIsActive(product.isActive || false)
setIsSpecial(product.isSpecialOffer || false)
setExistingImages(product.images || [])
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [product])
useEffect(() => {
formik.setFieldValue('images', existingImages)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [existingImages])
if (isLoading) {
return (
<div className='w-full mt-4 flex justify-center items-center'>
<div>در حال بارگذاری...</div>
</div>
)
}
if (!product) {
return (
<div className='w-full mt-4 flex justify-center items-center'>
<div>کالا یافت نشد</div>
</div>
)
}
return (
<div className='w-full mt-4'>
<div className='flex flex-col sm:flex-row w-full justify-between items-start sm:items-center gap-4'>
<div className='text-lg font-light'>
ویرایش کالا
</div>
<div>
<Button
className='px-5 w-full sm:w-auto'
onClick={() => formik.handleSubmit()}
isloading={isPending || isUploading}
>
<div className='flex gap-2 items-center'>
<TickCircle className='size-5' color='white' />
<div>ذخیره تغییرات</div>
</div>
</Button>
</div>
</div>
<div className='flex flex-col lg:flex-row gap-6 mt-6'>
<div className='flex-1'>
<div className='bg-white py-6 sm:py-8 xl:px-10 px-4 rounded-3xl'>
<BasicInfoSection formik={formik} categories={categories} />
<ProductContentSection formik={formik} />
<MealTimesSection formik={formik} />
<WeekDaysSection formik={formik} />
<ServiceOptionsSection formik={formik} />
</div>
</div>
<div className='w-full lg:w-auto'>
<CreateProductSidebar
isActive={isActive}
isSpecial={isSpecial}
onChangeActive={setIsActive}
onChangeSpecial={setIsSpecial}
onChangeImages={setImageFiles}
existingImages={existingImages}
onChangeExistingImages={setExistingImages}
/>
</div>
</div>
</div>
)
}
export default UpdateProduct