202 lines
6.8 KiB
TypeScript
202 lines
6.8 KiB
TypeScript
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 CreateFoodSidebar from './components/CreateFoodSidebar'
|
||
import BasicInfoSection from './components/BasicInfoSection'
|
||
import FoodContentSection from './components/FoodContentSection'
|
||
import MealTimesSection from './components/MealTimesSection'
|
||
import WeekDaysSection from './components/WeekDaysSection'
|
||
import ServiceOptionsSection from './components/ServiceOptionsSection'
|
||
import type { CreateFoodType } from './types/Types'
|
||
import { useUpdateFood, useGetFoodDetails, useGetCategories } from './hooks/useFoodData'
|
||
import { useMultipleUpload } from '../uploader/hooks/useUploaderData'
|
||
import { Pages } from '@/config/Pages'
|
||
import type { ErrorType } from '@/helpers/types'
|
||
import { extractErrorMessage } from '@/config/func'
|
||
|
||
const UpdateFood: FC = () => {
|
||
const { id } = useParams<{ id: string }>()
|
||
const { data: foodData, isLoading } = useGetFoodDetails(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: updateFood, isPending } = useUpdateFood()
|
||
const { mutate: multipleUpload, isPending: isUploading } = useMultipleUpload()
|
||
const navigate = useNavigate()
|
||
const categories = categoriesData?.data?.map(category => ({
|
||
label: category.title,
|
||
value: category.id
|
||
})) || []
|
||
|
||
const food = foodData?.data
|
||
|
||
const formik = useFormik<CreateFoodType>({
|
||
initialValues: {
|
||
title: '',
|
||
desc: '',
|
||
content: [],
|
||
categoryId: '',
|
||
price: 0,
|
||
discount: 0,
|
||
prepareTime: 0,
|
||
weekDays: [],
|
||
mealTypes: [],
|
||
pickupServe: false,
|
||
inPlaceServe: false,
|
||
isActive: true,
|
||
images: [],
|
||
isSpecialOffer: false
|
||
},
|
||
validationSchema: Yup.object().shape({
|
||
title: Yup.string().required('نام غذا الزامی است'),
|
||
desc: Yup.string().required('توضیحات غذا الزامی است'),
|
||
categoryId: Yup.string().required('دستهبندی الزامی است'),
|
||
price: Yup.number().required('قیمت الزامی است').min(0, 'قیمت باید مثبت باشد'),
|
||
prepareTime: Yup.number().required('زمان آمادهسازی الزامی است').min(0, 'زمان آمادهسازی باید مثبت باشد'),
|
||
discount: Yup.number().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 submitFood = (newImageUrls: string[] = []) => {
|
||
const allImages = [...values.images, ...newImageUrls]
|
||
const foodData: CreateFoodType = {
|
||
...values,
|
||
isActive,
|
||
isSpecialOffer: isSpecial,
|
||
images: allImages,
|
||
content: values.content.filter(item => item && item.trim().length > 0)
|
||
}
|
||
|
||
updateFood({ id, params: foodData }, {
|
||
onSuccess: () => {
|
||
toast.success('غذا با موفقیت بهروزرسانی شد')
|
||
navigate(Pages.foods.list)
|
||
},
|
||
onError: (error: ErrorType) => {
|
||
toast.error(extractErrorMessage(error))
|
||
}
|
||
})
|
||
}
|
||
|
||
if (imageFiles.length > 0) {
|
||
multipleUpload(imageFiles, {
|
||
onSuccess: (response) => {
|
||
const imageUrls = response?.data?.map(item => item.url) || []
|
||
submitFood(imageUrls)
|
||
},
|
||
onError: (error: ErrorType) => {
|
||
toast.error(error?.response?.data?.error?.message[0] || 'خطا در آپلود تصاویر')
|
||
}
|
||
})
|
||
} else {
|
||
submitFood()
|
||
}
|
||
}
|
||
})
|
||
|
||
useEffect(() => {
|
||
if (food) {
|
||
formik.setValues({
|
||
title: food.title || '',
|
||
desc: food.desc || '',
|
||
content: food.content || [],
|
||
categoryId: food.category?.id || '',
|
||
price: food.price || 0,
|
||
discount: food.discount || 0,
|
||
prepareTime: food.prepareTime || 0,
|
||
weekDays: food.weekDays || [],
|
||
mealTypes: food.mealTypes || [],
|
||
pickupServe: food.pickupServe || false,
|
||
inPlaceServe: food.inPlaceServe || false,
|
||
isActive: food.isActive || false,
|
||
images: food.images || [],
|
||
isSpecialOffer: food.isSpecialOffer || false
|
||
})
|
||
setIsActive(food.isActive || false)
|
||
setIsSpecial(food.isSpecialOffer || false)
|
||
setExistingImages(food.images || [])
|
||
}
|
||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||
}, [food])
|
||
|
||
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 (!food) {
|
||
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 w-full justify-between items-center'>
|
||
<div className='text-lg font-light'>
|
||
ویرایش غذا
|
||
</div>
|
||
<div>
|
||
<Button
|
||
className='px-5'
|
||
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 gap-6 mt-6'>
|
||
<div className='flex-1'>
|
||
<div className='bg-white py-8 xl:px-10 px-4 rounded-3xl'>
|
||
<BasicInfoSection formik={formik} categories={categories} />
|
||
<FoodContentSection formik={formik} />
|
||
<MealTimesSection formik={formik} />
|
||
<WeekDaysSection formik={formik} />
|
||
<ServiceOptionsSection formik={formik} />
|
||
</div>
|
||
</div>
|
||
|
||
<CreateFoodSidebar
|
||
isActive={isActive}
|
||
isSpecial={isSpecial}
|
||
onChangeActive={setIsActive}
|
||
onChangeSpecial={setIsSpecial}
|
||
onChangeImages={setImageFiles}
|
||
existingImages={existingImages}
|
||
onChangeExistingImages={setExistingImages}
|
||
/>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default UpdateFood
|