update customer and update service category and ...
This commit is contained in:
@@ -87,6 +87,7 @@ export const Pages = {
|
|||||||
customer: {
|
customer: {
|
||||||
list: "/customers/list",
|
list: "/customers/list",
|
||||||
create: "/customers/create",
|
create: "/customers/create",
|
||||||
|
update: "/customers/update/",
|
||||||
},
|
},
|
||||||
cardBank: {
|
cardBank: {
|
||||||
list: "/card-bank/list",
|
list: "/card-bank/list",
|
||||||
|
|||||||
+4
-1
@@ -645,7 +645,10 @@
|
|||||||
"enter_company_name": "نام ثبتی شرکت را وارد کنید",
|
"enter_company_name": "نام ثبتی شرکت را وارد کنید",
|
||||||
"postal_code": "کد پستی",
|
"postal_code": "کد پستی",
|
||||||
"enter_postal_code": "کد پستی را وارد کنید",
|
"enter_postal_code": "کد پستی را وارد کنید",
|
||||||
"address": "آدرس"
|
"address": "آدرس",
|
||||||
|
"image_profile": "تصویر پروفایل",
|
||||||
|
"upload_image": "آپلود تصویر",
|
||||||
|
"new_password": "رمز عبور جدید"
|
||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
"messages_list": "لیست پیام ها",
|
"messages_list": "لیست پیام ها",
|
||||||
|
|||||||
@@ -54,10 +54,9 @@ const AddCustomer: FC = () => {
|
|||||||
nationalCode: '',
|
nationalCode: '',
|
||||||
password: '',
|
password: '',
|
||||||
economicCode: '',
|
economicCode: '',
|
||||||
companyRegisteredName: '',
|
registrationName: '',
|
||||||
registrationId: '',
|
registrationCode: '',
|
||||||
nationalId: '',
|
nationalIdentity: '',
|
||||||
number: '',
|
|
||||||
postalCode: '',
|
postalCode: '',
|
||||||
address: '',
|
address: '',
|
||||||
cityId: '',
|
cityId: '',
|
||||||
@@ -72,15 +71,15 @@ const AddCustomer: FC = () => {
|
|||||||
nationalCode: Yup.string().required(t('errors.required')),
|
nationalCode: Yup.string().required(t('errors.required')),
|
||||||
password: Yup.string().required(t('errors.required')),
|
password: Yup.string().required(t('errors.required')),
|
||||||
economicCode: Yup.string().required(t('errors.required')),
|
economicCode: Yup.string().required(t('errors.required')),
|
||||||
companyRegisteredName: Yup.string().required(t('errors.required')),
|
registrationName: Yup.string().required(t('errors.required')),
|
||||||
registrationId: Yup.string().required(t('errors.required')),
|
registrationCode: Yup.string().required(t('errors.required')),
|
||||||
nationalId: Yup.string().required(t('errors.required')),
|
nationalIdentity: Yup.string().required(t('errors.required')),
|
||||||
number: Yup.string().required(t('errors.required')),
|
|
||||||
postalCode: Yup.string().required(t('errors.required')),
|
postalCode: Yup.string().required(t('errors.required')),
|
||||||
address: Yup.string().required(t('errors.required')),
|
address: Yup.string().required(t('errors.required')),
|
||||||
cityId: Yup.string().required(t('errors.required')),
|
cityId: Yup.string().required(t('errors.required')),
|
||||||
}),
|
}),
|
||||||
onSubmit: async (values) => {
|
onSubmit: async (values) => {
|
||||||
|
values.cityId = +values.cityId
|
||||||
if (file) {
|
if (file) {
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', file)
|
formData.append('file', file)
|
||||||
@@ -185,15 +184,15 @@ const AddCustomer: FC = () => {
|
|||||||
<Input
|
<Input
|
||||||
label={t('customer.copany_name')}
|
label={t('customer.copany_name')}
|
||||||
placeholder={t('customer.enter_company_name')}
|
placeholder={t('customer.enter_company_name')}
|
||||||
{...formik.getFieldProps('companyRegisteredName')}
|
{...formik.getFieldProps('registrationName')}
|
||||||
error_text={formik.touched.companyRegisteredName && formik.errors.companyRegisteredName ? formik.errors.companyRegisteredName : ''}
|
error_text={formik.touched.registrationName && formik.errors.registrationName ? formik.errors.registrationName : ''}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
label={t('customer.id_national')}
|
label={t('customer.id_national')}
|
||||||
placeholder={t('customer.enter_id_nation')}
|
placeholder={t('customer.enter_id_nation')}
|
||||||
{...formik.getFieldProps('nationalId')}
|
{...formik.getFieldProps('nationalIdentity')}
|
||||||
error_text={formik.touched.nationalId && formik.errors.nationalId ? formik.errors.nationalId : ''}
|
error_text={formik.touched.nationalIdentity && formik.errors.nationalIdentity ? formik.errors.nationalIdentity : ''}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
@@ -222,16 +221,16 @@ const AddCustomer: FC = () => {
|
|||||||
<Input
|
<Input
|
||||||
label={t('customer.registeration_id')}
|
label={t('customer.registeration_id')}
|
||||||
placeholder={t('customer.enter_registeration_id')}
|
placeholder={t('customer.enter_registeration_id')}
|
||||||
{...formik.getFieldProps('registrationId')}
|
{...formik.getFieldProps('registrationCode')}
|
||||||
error_text={formik.touched.registrationId && formik.errors.registrationId ? formik.errors.registrationId : ''}
|
error_text={formik.touched.registrationCode && formik.errors.registrationCode ? formik.errors.registrationCode : ''}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Input
|
{/* <Input
|
||||||
label={t('customer.your_phone_fixed')}
|
label={t('customer.your_phone_fixed')}
|
||||||
placeholder={t('customer.enter_phone_fixed')}
|
placeholder={t('customer.enter_phone_fixed')}
|
||||||
{...formik.getFieldProps('number')}
|
{...formik.getFieldProps('phone')}
|
||||||
error_text={formik.touched.number && formik.errors.number ? formik.errors.number : ''}
|
error_text={formik.touched.phone && formik.errors.phone ? formik.errors.phone : ''}
|
||||||
/>
|
/> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='mt-8 rowTwoInput'>
|
<div className='mt-8 rowTwoInput'>
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ const CustomerList: FC = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
</Td>
|
</Td>
|
||||||
<Td text={''}>
|
<Td text={''}>
|
||||||
<Link to={Pages.ticket.detail + '1'}>
|
<Link to={Pages.customer.update + item.id}>
|
||||||
<Eye size={20} color='#8C90A3' />
|
<Eye size={20} color='#8C90A3' />
|
||||||
</Link>
|
</Link>
|
||||||
</Td>
|
</Td>
|
||||||
|
|||||||
@@ -0,0 +1,331 @@
|
|||||||
|
import { FC, useEffect, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Input from '../../components/Input'
|
||||||
|
import UploadBoxDraggble from '../../components/UploadBoxDraggble';
|
||||||
|
import Button from '../../components/Button';
|
||||||
|
import { TickCircle } from 'iconsax-react';
|
||||||
|
import DatePickerComponent from '../../components/DatePicker';
|
||||||
|
import Select from '../../components/Select';
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
import { useFormik } from 'formik';
|
||||||
|
import { CreateCustomerType, ProvinesItemType } from './types/CustomerTypes';
|
||||||
|
import { useCreateCustomer, useGetCities, useGetCustomerDetail, useGetProvines, useUpdateCustomer } from './hooks/useCustomerData';
|
||||||
|
import PageLoading from '../../components/PageLoading';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
import { ErrorType } from '../../helpers/types';
|
||||||
|
import { useSingleUpload } from '../service/hooks/useServiceData';
|
||||||
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
import { Pages } from '../../config/Pages';
|
||||||
|
import Textarea from '../../components/Textarea';
|
||||||
|
|
||||||
|
const UpdateCustomer: FC = () => {
|
||||||
|
|
||||||
|
const { id } = useParams()
|
||||||
|
const { t } = useTranslation('global')
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const [provinesId, setProvinesId] = useState<string>('')
|
||||||
|
const [file, setFile] = useState<File>()
|
||||||
|
const getProvines = useGetProvines()
|
||||||
|
const getCities = useGetCities(provinesId)
|
||||||
|
const singleUpload = useSingleUpload()
|
||||||
|
const createCustomer = useCreateCustomer()
|
||||||
|
const getDetailCustomer = useGetCustomerDetail(id)
|
||||||
|
const updateCustomer = useUpdateCustomer(id ? id : '')
|
||||||
|
|
||||||
|
const handleUpdateCustomer = (values: CreateCustomerType) => {
|
||||||
|
updateCustomer.mutate(values, {
|
||||||
|
onSuccess: () => {
|
||||||
|
toast.success(t('success'))
|
||||||
|
navigate(Pages.customer.list)
|
||||||
|
},
|
||||||
|
onError: (error: ErrorType) => {
|
||||||
|
toast.error(error.response?.data?.error.message[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const formik = useFormik<CreateCustomerType>({
|
||||||
|
initialValues: {
|
||||||
|
phone: '',
|
||||||
|
firstName: '',
|
||||||
|
lastName: '',
|
||||||
|
email: '',
|
||||||
|
birthDate: '',
|
||||||
|
nationalCode: '',
|
||||||
|
password: '',
|
||||||
|
economicCode: '',
|
||||||
|
registrationName: '',
|
||||||
|
registrationCode: '',
|
||||||
|
nationalIdentity: '',
|
||||||
|
postalCode: '',
|
||||||
|
address: '',
|
||||||
|
cityId: '',
|
||||||
|
profilePic: ''
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
phone: Yup.string().required(t('errors.required')),
|
||||||
|
firstName: Yup.string().required(t('errors.required')),
|
||||||
|
lastName: Yup.string().required(t('errors.required')),
|
||||||
|
email: Yup.string().email(t('errors.email')).required(t('errors.required')),
|
||||||
|
birthDate: Yup.string().required(t('errors.required')),
|
||||||
|
nationalCode: Yup.string().required(t('errors.required')),
|
||||||
|
economicCode: Yup.string().required(t('errors.required')),
|
||||||
|
registrationName: Yup.string().required(t('errors.required')),
|
||||||
|
registrationCode: Yup.string().required(t('errors.required')),
|
||||||
|
nationalIdentity: Yup.string().required(t('errors.required')),
|
||||||
|
postalCode: Yup.string().required(t('errors.required')),
|
||||||
|
address: Yup.string().required(t('errors.required')),
|
||||||
|
cityId: Yup.string().required(t('errors.required')),
|
||||||
|
}),
|
||||||
|
onSubmit: async (values) => {
|
||||||
|
values.cityId = +values.cityId
|
||||||
|
if (values.password === '') values.password = undefined
|
||||||
|
if (file) {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file)
|
||||||
|
await singleUpload.mutateAsync(formData, {
|
||||||
|
onSuccess: (data) => {
|
||||||
|
values.profilePic = data?.data?.url
|
||||||
|
},
|
||||||
|
onError: (error: ErrorType) => {
|
||||||
|
toast.error(error.response?.data?.error?.message[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
handleUpdateCustomer(values)
|
||||||
|
} else {
|
||||||
|
values.profilePic = undefined
|
||||||
|
handleUpdateCustomer(values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
if (getDetailCustomer.data) {
|
||||||
|
const data = getDetailCustomer.data.data?.customer
|
||||||
|
const legal = getDetailCustomer.data.data?.customer.legalUser
|
||||||
|
formik.setValues({
|
||||||
|
phone: data.phone || '',
|
||||||
|
firstName: data.firstName || '',
|
||||||
|
lastName: data.lastName || '',
|
||||||
|
email: data.email || '',
|
||||||
|
birthDate: data.birthDate || '',
|
||||||
|
nationalCode: data.nationalCode || '',
|
||||||
|
password: data.password || '',
|
||||||
|
economicCode: legal.economicCode || '',
|
||||||
|
registrationName: legal.registrationName || '',
|
||||||
|
registrationCode: legal.registrationCode || '',
|
||||||
|
nationalIdentity: legal.nationalIdentity || '',
|
||||||
|
postalCode: legal.address.postalCode || '',
|
||||||
|
address: legal.address?.fullAddress || '',
|
||||||
|
cityId: legal?.address?.city?.id,
|
||||||
|
profilePic: data.profilePic || ''
|
||||||
|
});
|
||||||
|
|
||||||
|
setProvinesId(legal?.address?.city.province?.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [getDetailCustomer.data])
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='w-full mt-4'>
|
||||||
|
<div className='flex w-full justify-between items-center'>
|
||||||
|
<div>
|
||||||
|
{t('customer.add_cutomer')}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
className='px-5'
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
isLoading={createCustomer.isPending || singleUpload.isPending}
|
||||||
|
>
|
||||||
|
<div className='flex gap-2'>
|
||||||
|
<TickCircle
|
||||||
|
className='size-5'
|
||||||
|
color='#fff'
|
||||||
|
/>
|
||||||
|
<div>{t('save')}</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
getProvines.isPending ?
|
||||||
|
<PageLoading />
|
||||||
|
:
|
||||||
|
<div className='flex gap-6'>
|
||||||
|
<div className='flex-1'>
|
||||||
|
|
||||||
|
<div className='flex-1 mt-10 bg-white py-8 xl:px-10 px-4 rounded-3xl'>
|
||||||
|
<div className='rowTwoInput'>
|
||||||
|
<Input
|
||||||
|
label={t('customer.name')}
|
||||||
|
{...formik.getFieldProps('firstName')}
|
||||||
|
error_text={formik.touched.firstName && formik.errors.firstName ? formik.errors.firstName : ''}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label={t('customer.family')}
|
||||||
|
{...formik.getFieldProps('lastName')}
|
||||||
|
error_text={formik.touched.lastName && formik.errors.lastName ? formik.errors.lastName : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-8 rowTwoInput'>
|
||||||
|
<DatePickerComponent
|
||||||
|
label={t('customer.dateofbirth')}
|
||||||
|
onChange={(value) => formik.setFieldValue('birthDate', value)}
|
||||||
|
error_text={formik.touched.birthDate && formik.errors.birthDate ? formik.errors.birthDate : ''}
|
||||||
|
placeholder=''
|
||||||
|
defaulValue={formik.values.birthDate}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
label={t('customer.national_code')}
|
||||||
|
placeholder={t('customer.enter_nation_code')}
|
||||||
|
{...formik.getFieldProps('nationalCode')}
|
||||||
|
error_text={formik.touched.nationalCode && formik.errors.nationalCode ? formik.errors.nationalCode : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-8 rowTwoInput'>
|
||||||
|
<Input
|
||||||
|
label={t('customer.email')}
|
||||||
|
placeholder={t('customer.enter_email')}
|
||||||
|
{...formik.getFieldProps('email')}
|
||||||
|
error_text={formik.touched.email && formik.errors.email ? formik.errors.email : ''}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label={t('customer.phone_number')}
|
||||||
|
placeholder={t('customer.enter_phone_number')}
|
||||||
|
{...formik.getFieldProps('phone')}
|
||||||
|
error_text={formik.touched.phone && formik.errors.phone ? formik.errors.phone : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-8'>
|
||||||
|
{t('customer.information_legal')}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-8 rowTwoInput'>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label={t('customer.copany_name')}
|
||||||
|
placeholder={t('customer.enter_company_name')}
|
||||||
|
{...formik.getFieldProps('registrationName')}
|
||||||
|
error_text={formik.touched.registrationName && formik.errors.registrationName ? formik.errors.registrationName : ''}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label={t('customer.id_national')}
|
||||||
|
placeholder={t('customer.enter_id_nation')}
|
||||||
|
{...formik.getFieldProps('nationalIdentity')}
|
||||||
|
error_text={formik.touched.nationalIdentity && formik.errors.nationalIdentity ? formik.errors.nationalIdentity : ''}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-8 rowTwoInput'>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label={t('customer.economic_code')}
|
||||||
|
placeholder={t('customer.enter_economic_code')}
|
||||||
|
{...formik.getFieldProps('economicCode')}
|
||||||
|
error_text={formik.touched.economicCode && formik.errors.economicCode ? formik.errors.economicCode : ''}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label={t('customer.postal_code')}
|
||||||
|
placeholder={t('customer.enter_postal_code')}
|
||||||
|
{...formik.getFieldProps('postalCode')}
|
||||||
|
error_text={formik.touched.postalCode && formik.errors.postalCode ? formik.errors.postalCode : ''}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-8 rowTwoInput'>
|
||||||
|
<Input
|
||||||
|
label={t('customer.registeration_id')}
|
||||||
|
placeholder={t('customer.enter_registeration_id')}
|
||||||
|
{...formik.getFieldProps('registrationCode')}
|
||||||
|
error_text={formik.touched.registrationCode && formik.errors.registrationCode ? formik.errors.registrationCode : ''}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* <Input
|
||||||
|
label={t('customer.your_phone_fixed')}
|
||||||
|
placeholder={t('customer.enter_phone_fixed')}
|
||||||
|
{...formik.getFieldProps('phone')}
|
||||||
|
error_text={formik.touched.phone && formik.errors.phone ? formik.errors.phone : ''}
|
||||||
|
/> */}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-8 rowTwoInput'>
|
||||||
|
<Select
|
||||||
|
label={t('customer.state')}
|
||||||
|
items={getProvines.data?.data?.provinces.map((item: ProvinesItemType) => ({ label: item.name, value: item.id }))}
|
||||||
|
onChange={(e) => setProvinesId(e.target.value)}
|
||||||
|
placeholder={t('select')}
|
||||||
|
value={provinesId}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
label={t('customer.city')}
|
||||||
|
items={getCities.data?.data?.cities ? getCities.data?.data?.cities.map((item: ProvinesItemType) => ({ label: item.name, value: item.id })) : []}
|
||||||
|
placeholder={t('select')}
|
||||||
|
{...formik.getFieldProps('cityId')}
|
||||||
|
error_text={formik.touched.cityId && formik.errors.cityId ? formik.errors.cityId : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-8 rowTwoInput'>
|
||||||
|
<Textarea
|
||||||
|
{...formik.getFieldProps('address')}
|
||||||
|
placeholder={t('customer.address')}
|
||||||
|
error_text={formik.touched.address && formik.errors.address ? formik.errors.address : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='bg-white mt-10 w-sidebar text-xs hidden 2xl:block h-fit px-5 py-7 rounded-3xl'>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Input
|
||||||
|
label={t('customer.new_password')}
|
||||||
|
type='password'
|
||||||
|
{...formik.getFieldProps('password')}
|
||||||
|
error_text={formik.touched.password && formik.errors.password ? formik.errors.password : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className='mt-5'>
|
||||||
|
<Input
|
||||||
|
label={t('customer.reapeat_password')}
|
||||||
|
type='password'
|
||||||
|
{...formik.getFieldProps('password')}
|
||||||
|
error_text={formik.touched.password && formik.errors.password ? formik.errors.password : ''}
|
||||||
|
/>
|
||||||
|
</div> */}
|
||||||
|
|
||||||
|
<div className='mt-8'>
|
||||||
|
<div>{t('customer.image_profile')}</div>
|
||||||
|
<div className='mt-2'>
|
||||||
|
<UploadBoxDraggble
|
||||||
|
label={t('customer.upload_image')}
|
||||||
|
onChange={(files) => setFile(files[0])}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UpdateCustomer
|
||||||
@@ -36,3 +36,24 @@ export const useCreateCustomer = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useGetCustomerDetail = (id?: string) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["customer-detail", id],
|
||||||
|
queryFn: () => api.getDetailCustomer(id ? id : ""),
|
||||||
|
enabled: !!id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUpdateCustomer = (id: string) => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (variables: CreateCustomerType) =>
|
||||||
|
api.updateCustomer(id, variables),
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: ["customers"],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -17,6 +17,19 @@ export const getCities = async (id: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const createCustomer = async (params: CreateCustomerType) => {
|
export const createCustomer = async (params: CreateCustomerType) => {
|
||||||
const { data } = await axios.post(`/users/customer`, params);
|
const { data } = await axios.post(`/users/customers`, params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getDetailCustomer = async (id: string) => {
|
||||||
|
const { data } = await axios.get(`/users/customers/${id}`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateCustomer = async (
|
||||||
|
id: string,
|
||||||
|
params: CreateCustomerType
|
||||||
|
) => {
|
||||||
|
const { data } = await axios.patch(`/users/customers/${id}`, params);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,18 +26,17 @@ export type CreateCustomerType = {
|
|||||||
phone: string;
|
phone: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
email: string | null;
|
email: string;
|
||||||
birthDate: string;
|
birthDate: string;
|
||||||
nationalCode: string;
|
nationalCode: string;
|
||||||
password: string;
|
password?: string;
|
||||||
economicCode: string;
|
economicCode: string;
|
||||||
companyRegisteredName: string;
|
registrationName: string;
|
||||||
registrationId: string;
|
registrationCode: string;
|
||||||
nationalId: string;
|
nationalIdentity: string;
|
||||||
number: string;
|
|
||||||
postalCode: string;
|
postalCode: string;
|
||||||
address: string;
|
address: string;
|
||||||
cityId: string;
|
cityId: string | number;
|
||||||
profilePic?: string;
|
profilePic?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { ServiceCategoryType } from './types/ServiceTypes'
|
|||||||
import { useGetAllCategory } from './hooks/useServiceData'
|
import { useGetAllCategory } from './hooks/useServiceData'
|
||||||
import StatusCategory from './components/StatusCategory'
|
import StatusCategory from './components/StatusCategory'
|
||||||
import Pagination from '../../components/Pagination'
|
import Pagination from '../../components/Pagination'
|
||||||
|
import UpdateCategory from './components/UpdateCategory'
|
||||||
|
|
||||||
|
|
||||||
const Category: FC = () => {
|
const Category: FC = () => {
|
||||||
@@ -87,7 +88,9 @@ const Category: FC = () => {
|
|||||||
id={item.id}
|
id={item.id}
|
||||||
/>
|
/>
|
||||||
</Td>
|
</Td>
|
||||||
<Td text={''} />
|
<Td text={''}>
|
||||||
|
<UpdateCategory refetch={() => getCategory.refetch()} id={item.id} />
|
||||||
|
</Td>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
import { Edit, TickCircle } from 'iconsax-react'
|
||||||
|
import { FC, useEffect, useState } from 'react'
|
||||||
|
import DefaulModal from '../../../components/DefaulModal'
|
||||||
|
import { useGetCategoryDetail, useGetCategoryParents, useSingleUpload, useUpdateCategory } from '../hooks/useServiceData'
|
||||||
|
import Input from '../../../components/Input'
|
||||||
|
import { CreateServiceCategoryType, ServiceCategoryType } from '../types/ServiceTypes'
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
import { useFormik } from 'formik'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { ErrorType } from '../../../helpers/types'
|
||||||
|
import Select from '../../../components/Select'
|
||||||
|
import UploadBox from '../../../components/UploadBox'
|
||||||
|
import Button from '../../../components/Button'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
id: string,
|
||||||
|
refetch: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const UpdateCategory: FC<Props> = (props) => {
|
||||||
|
|
||||||
|
const { t } = useTranslation('global')
|
||||||
|
const [showModal, setShowModal] = useState<boolean>(false)
|
||||||
|
const [file, setFile] = useState<File>()
|
||||||
|
const getCategoryDetail = useGetCategoryDetail(props.id, showModal)
|
||||||
|
const singleUpload = useSingleUpload()
|
||||||
|
const getCategory = useGetCategoryParents()
|
||||||
|
const updateCategory = useUpdateCategory(props.id)
|
||||||
|
|
||||||
|
const formik = useFormik<CreateServiceCategoryType>({
|
||||||
|
initialValues: {
|
||||||
|
title: '',
|
||||||
|
isActive: true,
|
||||||
|
parentId: ''
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
title: Yup.string().required(t('errors.required')),
|
||||||
|
}),
|
||||||
|
onSubmit: async (values) => {
|
||||||
|
if (file) {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file)
|
||||||
|
await singleUpload.mutateAsync(formData, {
|
||||||
|
onSuccess: (data) => {
|
||||||
|
values.icon = data?.data?.url
|
||||||
|
},
|
||||||
|
onError: (error: ErrorType) => {
|
||||||
|
toast.error(error.response?.data?.error?.message[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
...values,
|
||||||
|
parentId: values.parentId ? values.parentId : undefined
|
||||||
|
}
|
||||||
|
updateCategory.mutate(params, {
|
||||||
|
onSuccess: () => {
|
||||||
|
formik.resetForm()
|
||||||
|
getCategory.refetch()
|
||||||
|
toast.success(t('success'))
|
||||||
|
setShowModal(false)
|
||||||
|
props.refetch()
|
||||||
|
},
|
||||||
|
onError: (error: ErrorType) => {
|
||||||
|
toast.error(error?.response?.data?.error?.message[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
if (getCategoryDetail.data) {
|
||||||
|
const data = getCategoryDetail.data?.data?.category
|
||||||
|
formik.setValues({
|
||||||
|
title: data?.title,
|
||||||
|
parentId: data?.parentId,
|
||||||
|
isActive: data?.isActive
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [getCategoryDetail.data])
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Edit onClick={() => setShowModal(true)} size={20} color='#888888' />
|
||||||
|
|
||||||
|
<DefaulModal
|
||||||
|
open={showModal}
|
||||||
|
close={() => setShowModal(false)}
|
||||||
|
isHeader
|
||||||
|
title_header='ویرایش دسته بندی'
|
||||||
|
>
|
||||||
|
<div className='mt-5'>
|
||||||
|
<Input
|
||||||
|
label={t('service.title_category')}
|
||||||
|
value={formik.values.title}
|
||||||
|
name='title'
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
error_text={formik.touched.title && formik.errors.title ? formik.errors.title : ''}
|
||||||
|
className='bg-white bg-opacity-40'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{
|
||||||
|
getCategory.data &&
|
||||||
|
<div className='mt-5'>
|
||||||
|
<Select
|
||||||
|
className='bg-white bg-opacity-40'
|
||||||
|
label={t('service.category_parent_2')}
|
||||||
|
items={getCategory.data?.data?.categories?.map((item: ServiceCategoryType) => {
|
||||||
|
return {
|
||||||
|
label: item.title,
|
||||||
|
value: item.id
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
placeholder={t('select')}
|
||||||
|
name='parentId'
|
||||||
|
value={formik.values.parentId}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
error_text={formik.touched.parentId && formik.errors.parentId ? formik.errors.parentId : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className='mt-5'>
|
||||||
|
<UploadBox
|
||||||
|
label='آیکون جدید'
|
||||||
|
onChange={(file) => setFile(file[0])}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-10 border-t border-border pt-5 flex justify-end'>
|
||||||
|
<div className='flex gap-5 items-center'>
|
||||||
|
<Button
|
||||||
|
className='w-[150px] bg-white bg-opacity-15 text-description'
|
||||||
|
label={t('plan.cancel')}
|
||||||
|
onClick={() => setShowModal(false)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
>
|
||||||
|
<div className='flex gap-2'>
|
||||||
|
<TickCircle
|
||||||
|
size={20}
|
||||||
|
color='white'
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
{t('save')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</DefaulModal>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UpdateCategory
|
||||||
@@ -161,3 +161,18 @@ export const useUpdateService = (id: string) => {
|
|||||||
api.updateService(id, variables),
|
api.updateService(id, variables),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useGetCategoryDetail = (id: string, enabled: boolean) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["category-detail", id],
|
||||||
|
queryFn: () => api.getCategoryDetail(id),
|
||||||
|
enabled: enabled,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUpdateCategory = (id: string) => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (variables: CreateServiceCategoryType) =>
|
||||||
|
api.updateCategory(id, variables),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -140,3 +140,19 @@ export const updateService = async (id: string, params: CreateServiceType) => {
|
|||||||
const { data } = await axios.patch(`/danak-services/${id}`, params);
|
const { data } = await axios.patch(`/danak-services/${id}`, params);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getCategoryDetail = async (id: string) => {
|
||||||
|
const { data } = await axios.get(`/danak-services/categories/${id}`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateCategory = async (
|
||||||
|
id: string,
|
||||||
|
params: CreateServiceCategoryType
|
||||||
|
) => {
|
||||||
|
const { data } = await axios.patch(
|
||||||
|
`/danak-services/categories/${id}`,
|
||||||
|
params
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import GroupList from '../pages/users/GroupList'
|
|||||||
import Reviews from '../pages/service/Reviews'
|
import Reviews from '../pages/service/Reviews'
|
||||||
import UpdateAds from '../pages/ads/Update'
|
import UpdateAds from '../pages/ads/Update'
|
||||||
import UpdateService from '../pages/service/UpdateService'
|
import UpdateService from '../pages/service/UpdateService'
|
||||||
|
import UpdateCustomer from '../pages/customer/Update'
|
||||||
|
|
||||||
const MainRouter: FC = () => {
|
const MainRouter: FC = () => {
|
||||||
|
|
||||||
@@ -114,6 +115,7 @@ const MainRouter: FC = () => {
|
|||||||
<Route path={Pages.profile} element={<Profile />} />
|
<Route path={Pages.profile} element={<Profile />} />
|
||||||
<Route path={Pages.customer.list} element={<CustomerList />} />
|
<Route path={Pages.customer.list} element={<CustomerList />} />
|
||||||
<Route path={Pages.customer.create} element={<CreateCustomer />} />
|
<Route path={Pages.customer.create} element={<CreateCustomer />} />
|
||||||
|
<Route path={Pages.customer.update + ':id'} element={<UpdateCustomer />} />
|
||||||
<Route path={Pages.messages.list} element={<MessagesList />} />
|
<Route path={Pages.messages.list} element={<MessagesList />} />
|
||||||
<Route path={Pages.messages.detail + ':id'} element={<MessageDetail />} />
|
<Route path={Pages.messages.detail + ':id'} element={<MessageDetail />} />
|
||||||
<Route path={Pages.users.list} element={<UsersList />} />
|
<Route path={Pages.users.list} element={<UsersList />} />
|
||||||
|
|||||||
Reference in New Issue
Block a user