score setting
This commit is contained in:
@@ -49,13 +49,16 @@ const Input: FC<Props> = (props: Props) => {
|
||||
setFormattedValue(formatted);
|
||||
|
||||
// ارسال مقدار خام به `onChange` والد
|
||||
props.onChange?.({
|
||||
const syntheticEvent = {
|
||||
...event,
|
||||
target: {
|
||||
...event.target,
|
||||
name: event.target.name,
|
||||
value: inputValue,
|
||||
},
|
||||
});
|
||||
} as React.ChangeEvent<HTMLInputElement>;
|
||||
|
||||
props.onChange?.(syntheticEvent);
|
||||
} else {
|
||||
props.onChange?.(event);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import Tabs from '@/components/Tabs'
|
||||
import { Card, KeySquare, Setting4, TruckFast } from 'iconsax-react'
|
||||
import { KeySquare, Money2, Setting4, TruckFast } from 'iconsax-react'
|
||||
import { useState, type FC } from 'react'
|
||||
import { SettingTabEnum } from './enum/Enum'
|
||||
import GeneralSettings from './GeneralSettings'
|
||||
import ScoreSetting from './components/ScoreSetting'
|
||||
|
||||
const Setting: FC = () => {
|
||||
|
||||
@@ -26,8 +27,8 @@ const Setting: FC = () => {
|
||||
value: SettingTabEnum.PASSWORD,
|
||||
},
|
||||
{
|
||||
icon: <Card color={activeTab === SettingTabEnum.FINANCIAL ? 'black' : '#8C90A3'} size={24} />,
|
||||
label: 'مالی',
|
||||
icon: <Money2 color={activeTab === SettingTabEnum.FINANCIAL ? 'black' : '#8C90A3'} size={24} />,
|
||||
label: 'تنظیمات امتیاز',
|
||||
value: SettingTabEnum.FINANCIAL,
|
||||
},
|
||||
{
|
||||
@@ -45,6 +46,9 @@ const Setting: FC = () => {
|
||||
{
|
||||
activeTab === SettingTabEnum.GENERAL && <GeneralSettings />
|
||||
}
|
||||
{
|
||||
activeTab === SettingTabEnum.FINANCIAL && <ScoreSetting />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
import { useEffect, useState, type FC } from 'react'
|
||||
import { useGetRestaurant, useUpdateRestaurant } from '../hooks/useSettingData'
|
||||
import type { UpdateRestaurantType } from '../types/Types'
|
||||
import { useFormik } from 'formik'
|
||||
import * as Yup from 'yup'
|
||||
import Input from '@/components/Input'
|
||||
import Button from '@/components/Button'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
interface FlatFormValues {
|
||||
purchaseAmount: string
|
||||
purchaseScore: string
|
||||
scoreAmount: string
|
||||
scoreCredit: string
|
||||
birthdayScore: string
|
||||
registerScore: string
|
||||
marriageDateScore: string
|
||||
referrerScore: string
|
||||
}
|
||||
|
||||
const ScoreSetting: FC = () => {
|
||||
|
||||
const { data: restaurant } = useGetRestaurant()
|
||||
const { mutate: updateRestaurant, isPending } = useUpdateRestaurant()
|
||||
const [isInitialized, setIsInitialized] = useState(false)
|
||||
|
||||
const formik = useFormik<FlatFormValues>({
|
||||
initialValues: {
|
||||
purchaseAmount: '',
|
||||
purchaseScore: '',
|
||||
scoreAmount: '',
|
||||
scoreCredit: '',
|
||||
birthdayScore: '',
|
||||
registerScore: '',
|
||||
marriageDateScore: '',
|
||||
referrerScore: '',
|
||||
},
|
||||
validationSchema: Yup.object().shape({
|
||||
purchaseAmount: Yup.string().required('مبلغ خرید الزامی است'),
|
||||
purchaseScore: Yup.string().required('امتیاز خرید الزامی است'),
|
||||
scoreAmount: Yup.string().required('مبلغ امتیاز الزامی است'),
|
||||
scoreCredit: Yup.string().required('مبلغ اعتبار الزامی است'),
|
||||
birthdayScore: Yup.string().required('امتیاز تولد الزامی است'),
|
||||
registerScore: Yup.string().required('امتیاز ثبت نام الزامی است'),
|
||||
marriageDateScore: Yup.string().required('امتیاز سالگرد ازدواج الزامی است'),
|
||||
referrerScore: Yup.string().required('امتیاز معرف الزامی است'),
|
||||
}),
|
||||
validateOnMount: false,
|
||||
onSubmit: (values) => {
|
||||
const payload: UpdateRestaurantType = {
|
||||
score: {
|
||||
purchaseAmount: values.purchaseAmount,
|
||||
purchaseScore: values.purchaseScore,
|
||||
scoreAmount: values.scoreAmount,
|
||||
scoreCredit: values.scoreCredit,
|
||||
birthdayScore: values.birthdayScore,
|
||||
registerScore: values.registerScore,
|
||||
marriageDateScore: values.marriageDateScore,
|
||||
referrerScore: values.referrerScore,
|
||||
},
|
||||
}
|
||||
updateRestaurant(payload, {
|
||||
onSuccess: () => {
|
||||
toast.success('تنظیمات امتیاز با موفقیت بهروزرسانی شد')
|
||||
},
|
||||
onError: () => {
|
||||
toast.error('خطا در بهروزرسانی تنظیمات امتیاز')
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const getFieldError = (fieldName: string): string | undefined => {
|
||||
const meta = formik.getFieldMeta(fieldName)
|
||||
return meta.touched && meta.error ? meta.error : undefined
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (restaurant?.data?.score && !isInitialized) {
|
||||
const scorePrice = restaurant.data.score
|
||||
formik.setValues({
|
||||
purchaseAmount: scorePrice.purchaseAmount != null ? String(scorePrice.purchaseAmount) : '',
|
||||
purchaseScore: scorePrice.purchaseScore != null ? String(scorePrice.purchaseScore) : '',
|
||||
scoreAmount: scorePrice.scoreAmount != null ? String(scorePrice.scoreAmount) : '',
|
||||
scoreCredit: scorePrice.scoreCredit != null ? String(scorePrice.scoreCredit) : '',
|
||||
birthdayScore: scorePrice.birthdayScore != null ? String(scorePrice.birthdayScore) : '',
|
||||
registerScore: scorePrice.registerScore != null ? String(scorePrice.registerScore) : '',
|
||||
marriageDateScore: scorePrice.marriageDateScore != null ? String(scorePrice.marriageDateScore) : '',
|
||||
referrerScore: scorePrice.referrerScore != null ? String(scorePrice.referrerScore) : '',
|
||||
}, false)
|
||||
formik.setTouched({}, false)
|
||||
setIsInitialized(true)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [restaurant, isInitialized])
|
||||
|
||||
|
||||
return (
|
||||
<form onSubmit={formik.handleSubmit} className='bg-white rounded-2xl p-6'>
|
||||
{/* بخش امتیاز خرید */}
|
||||
<div className='mb-8'>
|
||||
<h2 className='text-base font-medium mb-6 text-right'>امتیاز خرید</h2>
|
||||
|
||||
{/* خط اول */}
|
||||
<div className='flex items-center gap-3 mb-4'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<span className='text-sm text-gray-700 whitespace-nowrap'>به ازای هر</span>
|
||||
<Input
|
||||
name='purchaseAmount'
|
||||
value={formik.values.purchaseAmount}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error_text={getFieldError('purchaseAmount')}
|
||||
placeholder='0'
|
||||
seprator
|
||||
className='w-[200px]'
|
||||
/>
|
||||
</div>
|
||||
<div className='flex items-center gap-2'>
|
||||
<span className='text-sm text-gray-700 whitespace-nowrap'>تومان خرید مقدار</span>
|
||||
<Input
|
||||
name='purchaseScore'
|
||||
value={formik.values.purchaseScore}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error_text={getFieldError('purchaseScore')}
|
||||
placeholder='0'
|
||||
seprator
|
||||
className='w-[200px]'
|
||||
/>
|
||||
</div>
|
||||
<span className='text-sm text-gray-700 whitespace-nowrap'>امتیاز به مشتری داده میشود.</span>
|
||||
</div>
|
||||
|
||||
{/* خط دوم */}
|
||||
<div className='flex items-center gap-3'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<span className='text-sm text-gray-700 whitespace-nowrap'>هر</span>
|
||||
<Input
|
||||
name='scoreAmount'
|
||||
value={formik.values.scoreAmount}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error_text={getFieldError('scoreAmount')}
|
||||
placeholder='0'
|
||||
seprator
|
||||
className='w-[200px]'
|
||||
/>
|
||||
</div>
|
||||
<div className='flex items-center gap-2'>
|
||||
<span className='text-sm text-gray-700 whitespace-nowrap'>امتیاز معادل</span>
|
||||
<Input
|
||||
name='scoreCredit'
|
||||
value={formik.values.scoreCredit}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error_text={getFieldError('scoreCredit')}
|
||||
placeholder='0'
|
||||
seprator
|
||||
className='w-[200px]'
|
||||
/>
|
||||
</div>
|
||||
<span className='text-sm text-gray-700 whitespace-nowrap'>تومان اعتبار خرید است.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* بخش امتیاز ثابت */}
|
||||
<div className='mb-8'>
|
||||
<h2 className='text-base font-medium mb-6 text-right'>امتیاز ثابت</h2>
|
||||
|
||||
<div className='grid grid-cols-1 md:grid-cols-2 gap-6 gap-x-8'>
|
||||
<div className='space-y-4'>
|
||||
<Input
|
||||
label='امتیاز ثبت نام'
|
||||
name='registerScore'
|
||||
value={formik.values.registerScore}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error_text={getFieldError('registerScore')}
|
||||
placeholder='0'
|
||||
seprator
|
||||
/>
|
||||
|
||||
<Input
|
||||
label='امتیاز تاریخ تولد'
|
||||
name='birthdayScore'
|
||||
value={formik.values.birthdayScore}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error_text={getFieldError('birthdayScore')}
|
||||
placeholder='0'
|
||||
seprator
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='space-y-4'>
|
||||
<Input
|
||||
label='امتیاز تاریخ ازدواج'
|
||||
name='marriageDateScore'
|
||||
value={formik.values.marriageDateScore}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error_text={getFieldError('marriageDateScore')}
|
||||
placeholder='0'
|
||||
seprator
|
||||
/>
|
||||
|
||||
<Input
|
||||
label='امتیاز دعوت'
|
||||
name='referrerScore'
|
||||
value={formik.values.referrerScore}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
error_text={getFieldError('referrerScore')}
|
||||
placeholder='0'
|
||||
seprator
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex justify-end'>
|
||||
<Button
|
||||
type='submit'
|
||||
isloading={isPending}
|
||||
className='w-full md:w-48'
|
||||
>
|
||||
ذخیره تغییرات
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default ScoreSetting
|
||||
@@ -8,16 +8,26 @@ export type GeoJSONPolygon = {
|
||||
};
|
||||
|
||||
export type UpdateRestaurantType = {
|
||||
name: string;
|
||||
menuColor: string;
|
||||
phone: string;
|
||||
instagram: string;
|
||||
address: string;
|
||||
name?: string;
|
||||
menuColor?: string;
|
||||
phone?: string;
|
||||
instagram?: string;
|
||||
address?: string;
|
||||
logo?: string;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
description: string;
|
||||
latitude?: number;
|
||||
longitude?: number;
|
||||
description?: string;
|
||||
serviceArea?: GeoJSONPolygon;
|
||||
score?: {
|
||||
purchaseAmount: string;
|
||||
purchaseScore: string;
|
||||
scoreAmount: string;
|
||||
scoreCredit: string;
|
||||
birthdayScore: string;
|
||||
registerScore: string;
|
||||
marriageDateScore: string;
|
||||
referrerScore: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type Restaurant = {
|
||||
@@ -27,25 +37,36 @@ export type Restaurant = {
|
||||
deletedAt: string | null;
|
||||
name: string;
|
||||
slug: string;
|
||||
logo: string;
|
||||
address: string;
|
||||
menuColor: string;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
logo: string | null;
|
||||
address: string | null;
|
||||
menuColor: string | null;
|
||||
latitude: number | null;
|
||||
longitude: number | null;
|
||||
serviceArea: GeoJSONPolygon;
|
||||
isActive: boolean;
|
||||
establishedYear: number | null;
|
||||
phoneNumber: string | null;
|
||||
phone: string;
|
||||
instagram: string;
|
||||
instagram: string | null;
|
||||
telegram: string | null;
|
||||
whatsapp: string | null;
|
||||
description: string;
|
||||
description: string | null;
|
||||
seoTitle: string | null;
|
||||
seoDescription: string | null;
|
||||
tagNames: unknown | null;
|
||||
images: unknown | null;
|
||||
vat: number;
|
||||
domain: string;
|
||||
score: {
|
||||
scoreAmount: string;
|
||||
scoreCredit: string;
|
||||
birthdayScore: string;
|
||||
purchaseScore: string;
|
||||
referrerScore: string;
|
||||
registerScore: string;
|
||||
purchaseAmount: string;
|
||||
marriageDateScore: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type GetRestaurantResponse = IResponse<Restaurant>;
|
||||
|
||||
Reference in New Issue
Block a user