copy dmenu-admin to dkala-admin

This commit is contained in:
hamid zarghami
2026-02-07 16:20:18 +03:30
commit 6b9e808bfd
292 changed files with 27167 additions and 0 deletions
+178
View File
@@ -0,0 +1,178 @@
import { type FC, useState, useMemo, useEffect } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import { useFormik } from 'formik'
import * as Yup from 'yup'
import { TickCircle } from 'iconsax-react'
import { toast } from 'react-toastify'
import Button from '@/components/Button'
import type { CreateCouponType } from './types/Types'
import { useGetCouponDetails, useUpdateCoupon } from './hooks/useCouponData'
import { useGetCategories } from '@/pages/food/hooks/useFoodData'
import { useGetFoods } from '@/pages/food/hooks/useFoodData'
import { Pages } from '@/config/Pages'
import type { ErrorType } from '@/helpers/types'
import { extractErrorMessage } from '@/config/func'
import CouponBasicInfo from './components/CouponBasicInfo'
import CouponDiscountSettings from './components/CouponDiscountSettings'
import CouponUsageSettings from './components/CouponUsageSettings'
import CouponSidebar from './components/CouponSidebar'
const UpdateCoupon: FC = () => {
const navigate = useNavigate()
const { id } = useParams<{ id: string }>()
const { data: couponData, isLoading } = useGetCouponDetails(id || '')
const { mutate: updateCoupon, isPending: isUpdating } = useUpdateCoupon()
const { data: categoriesData } = useGetCategories()
const { data: foodsData } = useGetFoods()
const [couponType, setCouponType] = useState<'PERCENTAGE' | 'FIXED'>('PERCENTAGE')
const categories = useMemo(() => categoriesData?.data || [], [categoriesData?.data])
const foods = useMemo(() => foodsData?.data || [], [foodsData?.data])
const formik = useFormik<CreateCouponType>({
initialValues: {
code: '',
name: '',
description: '',
value: 0,
maxDiscount: null,
minOrderAmount: 0,
maxUses: 0,
maxUsesPerUser: null,
startDate: null,
endDate: null,
isActive: true,
foodCategories: [],
foods: [],
userPhone: '',
type: 'PERCENTAGE',
},
validationSchema: Yup.object().shape({
type: Yup.string().required('نوع کوپن الزامی است'),
code: Yup.string().required('کد کوپن الزامی است'),
name: Yup.string().required('نام کوپن الزامی است'),
description: Yup.string(),
value: Yup.number().min(0, 'مقدار باید بیشتر از صفر باشد').required('مقدار کوپن الزامی است'),
maxDiscount: Yup.number().nullable().min(0, 'حداکثر تخفیف باید بیشتر از صفر باشد'),
minOrderAmount: Yup.number().min(0, 'حداقل مبلغ سفارش باید بیشتر از صفر باشد').required('حداقل مبلغ سفارش الزامی است'),
maxUses: Yup.number().min(0, 'حداکثر استفاده باید بیشتر از صفر باشد').required('حداکثر استفاده الزامی است'),
maxUsesPerUser: Yup.number().nullable().min(0, 'حداکثر استفاده برای هر کاربر باید بیشتر از صفر باشد'),
startDate: Yup.string().nullable(),
endDate: Yup.string().nullable(),
userPhone: Yup.string().nullable(),
}),
enableReinitialize: true,
onSubmit: (values) => {
if (!id) {
toast.error('شناسه کوپن یافت نشد')
return
}
const submitValues = {
...values,
userPhone: values.userPhone?.trim() || undefined,
}
updateCoupon(
{ id, params: submitValues },
{
onSuccess: () => {
toast.success('کوپن با موفقیت به‌روزرسانی شد')
navigate(Pages.coupons.list)
},
onError: (error: ErrorType) => {
toast.error(extractErrorMessage(error))
},
}
)
},
})
useEffect(() => {
if (couponData?.data) {
const coupon = couponData.data
setCouponType(coupon.type)
formik.setValues({
code: coupon.code,
name: coupon.name,
description: coupon.description || '',
value: coupon.value,
maxDiscount: coupon.maxDiscount,
minOrderAmount: coupon.minOrderAmount,
maxUses: coupon.maxUses,
maxUsesPerUser: coupon.maxUsesPerUser,
startDate: coupon.startDate,
endDate: coupon.endDate,
isActive: coupon.isActive,
foodCategories: coupon.foodCategories || [],
foods: coupon.foods || [],
userPhone: coupon.userPhone || '',
type: coupon.type,
})
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [couponData?.data])
if (isLoading) {
return (
<div className='mt-5'>
<div className='text-center'>در حال بارگذاری...</div>
</div>
)
}
return (
<div className='mt-5'>
<div className='flex justify-between items-center mb-6'>
<h1 className='text-lg font-light'>ویرایش کد تخفیف</h1>
</div>
<div className='flex justify-end'>
<Button
className='flex gap-4 w-full sm:w-fit px-5'
isloading={isUpdating}
onClick={() => formik.handleSubmit()}
>
<div className='flex gap-2 items-center'>
<TickCircle color='white' size={20} className='ml-2' />
<span>ویرایش تخفیف</span>
</div>
</Button>
</div>
<div className='flex flex-col lg:flex-row gap-7 mt-7'>
<div className='flex-1'>
<div className='bg-white rounded-4xl p-4 sm:p-6 lg:p-8'>
<div className='text-lg font-light mb-6'>ویرایش کد تخفیف</div>
<CouponBasicInfo
formik={formik}
/>
<CouponDiscountSettings
formik={formik}
couponType={couponType}
onCouponTypeChange={setCouponType}
/>
{
formik.values.startDate && (
<CouponUsageSettings formik={formik} />
)
}
</div>
</div>
<div className='w-full lg:w-80 flex-shrink-0'>
<CouponSidebar
formik={formik}
categories={categories}
foods={foods}
/>
</div>
</div>
</div>
)
}
export default UpdateCoupon