378 lines
17 KiB
TypeScript
378 lines
17 KiB
TypeScript
import { FC, useEffect } from 'react'
|
||
import Button from '../../components/Button'
|
||
import { TickCircle } from 'iconsax-react'
|
||
import Input from '../../components/Input'
|
||
import { useTranslation } from 'react-i18next'
|
||
import { useFormik } from 'formik'
|
||
import * as Yup from 'yup'
|
||
import { CreateCompanyType } from './types/CompanyTypes'
|
||
import { useState } from 'react'
|
||
import { useMultiUpload, useSingleUpload } from '../service/hooks/useServiceData'
|
||
import { useGetCompanyDetail, useUpdateCompany } from './hooks/useCompanyData'
|
||
import { toast } from 'react-toastify'
|
||
import { ErrorType } from '../../helpers/types'
|
||
import { Pages } from '../../config/Pages'
|
||
import { useNavigate, useParams } from 'react-router-dom'
|
||
import CompanyServices from './components/CompanyServices'
|
||
import CompanyProducts from './components/CompanyProducts'
|
||
import DatePickerComponent from '../../components/DatePicker'
|
||
import moment from 'moment-jalaali'
|
||
import UpdateSidebar from './components/UpdateSideBar'
|
||
|
||
type ServiceType = {
|
||
id: string;
|
||
title: string;
|
||
imageUrl: string;
|
||
company: string;
|
||
}
|
||
|
||
type ProductType = {
|
||
id: string;
|
||
title: string;
|
||
imageUrl: string;
|
||
company: string;
|
||
}
|
||
|
||
const UpdateCompany: FC = () => {
|
||
const navigate = useNavigate()
|
||
const { id } = useParams()
|
||
const { t } = useTranslation('global')
|
||
const [profileImage, setProfileImage] = useState<File | null>(null)
|
||
const [coverImage, setCoverImage] = useState<File | null>(null)
|
||
const multiUpload = useMultiUpload()
|
||
const singleUpload = useSingleUpload()
|
||
const updateCompany = useUpdateCompany()
|
||
const { data: companyDetail } = useGetCompanyDetail(id)
|
||
|
||
const formik = useFormik<CreateCompanyType>({
|
||
initialValues: {
|
||
phone: '',
|
||
firstName: '',
|
||
lastName: '',
|
||
nationalCode: '',
|
||
password: '',
|
||
name: '',
|
||
email: '',
|
||
identificationNumber: '',
|
||
dateOfEstablishment: '',
|
||
address: '',
|
||
mapAddressLink: '',
|
||
description: '',
|
||
websiteUrl: '',
|
||
profileImageUrl: '',
|
||
coverImageUrl: '',
|
||
isActive: true,
|
||
industryId: '',
|
||
products: [],
|
||
services: [],
|
||
},
|
||
validationSchema: Yup.object({
|
||
phone: Yup.string().required(t('errors.required')),
|
||
firstName: Yup.string().required(t('errors.required')),
|
||
lastName: Yup.string().required(t('errors.required')),
|
||
nationalCode: Yup.string().required(t('errors.required')),
|
||
name: Yup.string().required(t('errors.required')),
|
||
email: Yup.string().email(t('errors.invalid_email')).required(t('errors.required')),
|
||
identificationNumber: Yup.string().required(t('errors.required')),
|
||
dateOfEstablishment: Yup.string().required(t('errors.required')),
|
||
address: Yup.string().required(t('errors.required')),
|
||
mapAddressLink: Yup.string().url(t('errors.invalid_url')),
|
||
description: Yup.string().required(t('errors.required')),
|
||
websiteUrl: Yup.string().url(t('errors.invalid_url')).required(t('errors.required')),
|
||
isActive: Yup.boolean().required(t('errors.required')),
|
||
industryId: Yup.string().required(t('errors.required')),
|
||
// products and services validation can be added if needed
|
||
}),
|
||
onSubmit: async (values) => {
|
||
// آپلود تصاویر خدمات
|
||
let serviceImages: string[] = []
|
||
const serviceImageIndices: number[] = []
|
||
if (services.length > 0) {
|
||
const formDataServices = new FormData()
|
||
services.forEach((s, index) => {
|
||
if (s.image) {
|
||
formDataServices.append('files', s.image)
|
||
serviceImageIndices.push(index)
|
||
}
|
||
})
|
||
|
||
// فقط تصاویر جدید را آپلود کن
|
||
if (formDataServices.getAll('files').length > 0) {
|
||
const serviceUploadRes = await multiUpload.mutateAsync(formDataServices)
|
||
serviceImages = serviceUploadRes.data.map((item: { url: string }) => item?.url)
|
||
}
|
||
}
|
||
|
||
// آپلود تصاویر محصولات
|
||
let productImages: string[] = []
|
||
const productImageIndices: number[] = []
|
||
if (products.length > 0) {
|
||
const formDataProducts = new FormData()
|
||
products.forEach((p, index) => {
|
||
if (p.image) {
|
||
formDataProducts.append('files', p.image)
|
||
productImageIndices.push(index)
|
||
}
|
||
})
|
||
|
||
// فقط تصاویر جدید را آپلود کن
|
||
if (formDataProducts.getAll('files').length > 0) {
|
||
const productUploadRes = await multiUpload.mutateAsync(formDataProducts)
|
||
productImages = productUploadRes.data.map((item: { url: string }) => item?.url)
|
||
}
|
||
}
|
||
|
||
// مقداردهی به values
|
||
values.services = services.map((s, idx) => {
|
||
if (s.existingImageUrl) {
|
||
return {
|
||
title: s.title,
|
||
imageUrl: s.existingImageUrl
|
||
}
|
||
}
|
||
|
||
if (s.image) {
|
||
const imageIndex = serviceImageIndices.indexOf(idx)
|
||
if (imageIndex !== -1 && serviceImages[imageIndex]) {
|
||
return {
|
||
title: s.title,
|
||
imageUrl: serviceImages[imageIndex]
|
||
}
|
||
}
|
||
}
|
||
|
||
return {
|
||
title: s.title,
|
||
imageUrl: ''
|
||
}
|
||
})
|
||
|
||
values.products = products.map((p, idx) => {
|
||
if (p.existingImageUrl) {
|
||
return {
|
||
title: p.title,
|
||
imageUrl: p.existingImageUrl
|
||
}
|
||
}
|
||
|
||
if (p.image) {
|
||
const imageIndex = productImageIndices.indexOf(idx)
|
||
if (imageIndex !== -1 && productImages[imageIndex]) {
|
||
return {
|
||
title: p.title,
|
||
imageUrl: productImages[imageIndex]
|
||
}
|
||
}
|
||
}
|
||
|
||
return {
|
||
title: p.title,
|
||
imageUrl: ''
|
||
}
|
||
})
|
||
|
||
if (profileImage) {
|
||
const formDataProfile = new FormData()
|
||
formDataProfile.append('file', profileImage)
|
||
const profileUploadRes = await singleUpload.mutateAsync(formDataProfile)
|
||
values.profileImageUrl = profileUploadRes.data.url
|
||
}
|
||
|
||
if (coverImage) {
|
||
const formDataCover = new FormData()
|
||
formDataCover.append('file', coverImage)
|
||
const coverUploadRes = await singleUpload.mutateAsync(formDataCover)
|
||
values.coverImageUrl = coverUploadRes.data.url
|
||
}
|
||
|
||
await updateCompany.mutateAsync({ id: id || '', params: values }, {
|
||
onSuccess: () => {
|
||
toast.success('شرکت با موفقیت ثبت شد')
|
||
navigate(Pages.company.list)
|
||
},
|
||
onError: (error: ErrorType) => {
|
||
toast.error(error.response?.data?.error?.message[0])
|
||
}
|
||
})
|
||
}
|
||
})
|
||
|
||
useEffect(() => {
|
||
if (companyDetail) {
|
||
formik.setValues(companyDetail?.data?.company)
|
||
formik.setFieldValue('dateOfEstablishment', moment(companyDetail?.data?.company?.dateOfEstablishment).format('YYYY-MM-DD'))
|
||
formik.setFieldValue('firstName', companyDetail?.data?.company?.user?.firstName)
|
||
formik.setFieldValue('lastName', companyDetail?.data?.company?.user?.lastName)
|
||
formik.setFieldValue('nationalCode', companyDetail?.data?.company?.user?.nationalCode)
|
||
formik.setFieldValue('phone', companyDetail?.data?.company?.user?.phone)
|
||
formik.setFieldValue('email', companyDetail?.data?.company?.user?.email)
|
||
formik.setFieldValue('address', companyDetail?.data?.company?.address)
|
||
formik.setFieldValue("industryId", companyDetail?.data?.company?.industry?.id)
|
||
|
||
// ذخیره سرویسها با URL تصاویر موجود
|
||
setServices(companyDetail?.data?.company?.services?.map((s: ServiceType) => ({
|
||
title: s.title,
|
||
existingImageUrl: s.imageUrl
|
||
})) || [])
|
||
|
||
// ذخیره محصولات با URL تصاویر موجود
|
||
setProducts(companyDetail?.data?.company?.products?.map((p: ProductType) => ({
|
||
title: p.title,
|
||
existingImageUrl: p.imageUrl
|
||
})) || [])
|
||
}
|
||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||
}, [companyDetail])
|
||
|
||
const [services, setServices] = useState<{ title: string; image?: File; existingImageUrl?: string }[]>([])
|
||
const [products, setProducts] = useState<{ title: string; image?: File; existingImageUrl?: string }[]>([])
|
||
|
||
console.log(formik.errors);
|
||
|
||
|
||
return (
|
||
<div className='mt-4'>
|
||
<div className='flex justify-between items-center'>
|
||
<div>
|
||
ویرایش شرکت
|
||
</div>
|
||
|
||
<Button
|
||
className='w-fit px-4'
|
||
onClick={() => formik.handleSubmit()}
|
||
isLoading={updateCompany.isPending || singleUpload.isPending || multiUpload.isPending}
|
||
>
|
||
<div className='flex items-center gap-2'>
|
||
<TickCircle size={20} color='white' />
|
||
<div>بروزرسانی شرکت</div>
|
||
</div>
|
||
</Button>
|
||
</div>
|
||
|
||
<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>اطلاعات شرکت</div>
|
||
|
||
<div className='mt-6'>
|
||
<Input
|
||
label='نام شرکت'
|
||
name='name'
|
||
value={formik.values.name}
|
||
onChange={formik.handleChange}
|
||
error_text={formik.touched.name && formik.errors.name ? formik.errors.name : ''}
|
||
/>
|
||
</div>
|
||
|
||
<div className='rowTwoInput mt-6'>
|
||
<Input
|
||
label='نام'
|
||
name='firstName'
|
||
value={formik.values.firstName}
|
||
onChange={formik.handleChange}
|
||
error_text={formik.touched.firstName && formik.errors.firstName ? formik.errors.firstName : ''}
|
||
/>
|
||
<Input
|
||
label='نام خانوادگی'
|
||
name='lastName'
|
||
value={formik.values.lastName}
|
||
onChange={formik.handleChange}
|
||
error_text={formik.touched.lastName && formik.errors.lastName ? formik.errors.lastName : ''}
|
||
/>
|
||
</div>
|
||
<div className='rowTwoInput mt-6'>
|
||
<Input
|
||
label='کد ملی'
|
||
name='nationalCode'
|
||
value={formik.values.nationalCode}
|
||
onChange={formik.handleChange}
|
||
error_text={formik.touched.nationalCode && formik.errors.nationalCode ? formik.errors.nationalCode : ''}
|
||
/>
|
||
<Input
|
||
label='رمز عبور'
|
||
name='password'
|
||
type='password'
|
||
value={formik.values.password}
|
||
onChange={formik.handleChange}
|
||
error_text={formik.touched.password && formik.errors.password ? formik.errors.password : ''}
|
||
/>
|
||
</div>
|
||
<div className='rowTwoInput mt-6'>
|
||
<Input
|
||
label={t('company.phone_number')}
|
||
name='phone'
|
||
value={formik.values.phone}
|
||
onChange={formik.handleChange}
|
||
error_text={formik.touched.phone && formik.errors.phone ? formik.errors.phone : ''}
|
||
/>
|
||
<Input
|
||
label={t('company.email')}
|
||
name='email'
|
||
value={formik.values.email}
|
||
onChange={formik.handleChange}
|
||
error_text={formik.touched.email && formik.errors.email ? formik.errors.email : ''}
|
||
/>
|
||
</div>
|
||
|
||
<div className='rowTwoInput mt-6'>
|
||
<Input
|
||
label={t('company.national_id')}
|
||
name='identificationNumber'
|
||
value={formik.values.identificationNumber}
|
||
onChange={formik.handleChange}
|
||
error_text={formik.touched.identificationNumber && formik.errors.identificationNumber ? formik.errors.identificationNumber : ''}
|
||
/>
|
||
|
||
<DatePickerComponent
|
||
label={t('company.establishment_date')}
|
||
placeholder='تاریخ تاسیس'
|
||
onChange={(date) => formik.setFieldValue('dateOfEstablishment', moment(date).format('YYYY-MM-DD'))}
|
||
error_text={formik.touched.dateOfEstablishment && formik.errors.dateOfEstablishment ? formik.errors.dateOfEstablishment : ''}
|
||
defaulValue={formik.values.dateOfEstablishment}
|
||
/>
|
||
</div>
|
||
|
||
<div className='rowTwoInput mt-6'>
|
||
<Input
|
||
label={t('company.map_link')}
|
||
name='mapAddressLink'
|
||
value={formik.values.mapAddressLink}
|
||
onChange={formik.handleChange}
|
||
error_text={formik.touched.mapAddressLink && formik.errors.mapAddressLink ? formik.errors.mapAddressLink : ''}
|
||
/>
|
||
</div>
|
||
|
||
<div className='mt-6'>
|
||
<Input
|
||
label={t('company.address')}
|
||
name='address'
|
||
value={formik.values.address}
|
||
onChange={formik.handleChange}
|
||
error_text={formik.touched.address && formik.errors.address ? formik.errors.address : ''}
|
||
/>
|
||
</div>
|
||
|
||
<div className='mt-6'>
|
||
<Input
|
||
label={t('company.short_description')}
|
||
name='description'
|
||
value={formik.values.description}
|
||
onChange={formik.handleChange}
|
||
error_text={formik.touched.description && formik.errors.description ? formik.errors.description : ''}
|
||
/>
|
||
</div>
|
||
|
||
<CompanyServices value={services} onChange={setServices} />
|
||
<CompanyProducts value={products} onChange={setProducts} />
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
<UpdateSidebar formik={formik} setProfileImage={setProfileImage} setCoverImage={setCoverImage} />
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default UpdateCompany |