Files
dzone-admin/src/pages/company/Update.tsx
T
hamid zarghami 46b7cc1c07 slider
2025-05-31 16:50:47 +03:30

378 lines
17 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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