diff --git a/src/pages/setting/SiteSetting.tsx b/src/pages/setting/SiteSetting.tsx index b43e53d..c628c8b 100644 --- a/src/pages/setting/SiteSetting.tsx +++ b/src/pages/setting/SiteSetting.tsx @@ -52,9 +52,9 @@ const SiteSetting: FC = () => { const { data: shopData, isLoading: isShopLoading } = useGetShop() const updateSiteSetting = useUpdateSiteSetting() const [isDataLoaded, setIsDataLoaded] = useState(false) - const [uploadingIndexes, setUploadingIndexes] = useState>(new Set()) - const [pendingFiles, setPendingFiles] = useState<{ [key: string]: File }>({}) const singleUpload = useSingleUpload() + const [logoFile, setLogoFile] = useState([]) + const [postalCodeFile, setPostalCodeFile] = useState([]) @@ -73,34 +73,31 @@ const SiteSetting: FC = () => { validateOnChange: false, validateOnBlur: false, onSubmit: async (values) => { - let finalDownloadAppDetails = values.downloadAppDetails - let finalSocialMediaLinks = values.socialMediaLinks + let siteLogo = values.siteLogo + let shopPostalCode = values.shopPostalCode - // اول همه فایل‌های pending رو آپلود کن - if (Object.keys(pendingFiles).length > 0) { - const uploadedData = await uploadAllPendingFiles() - // بروزرسانی downloadAppDetails با URL های واقعی - finalDownloadAppDetails = values.downloadAppDetails.map(item => { - const uploadedUrl = uploadedData[item.id] - return uploadedUrl ? { ...item, pic: uploadedUrl } : item - }) - // بروزرسانی socialMediaLinks با URL های واقعی - finalSocialMediaLinks = values.socialMediaLinks.map(item => { - const uploadedUrl = uploadedData[item.id] - return uploadedUrl ? { ...item, icon: uploadedUrl } : item - }) - // پاک کردن pending files بعد از آپلود موفق - setPendingFiles({}) + // آپلود لوگو سایت اگر فایل جدید انتخاب شده + if (logoFile.length > 0) { + const logoResponse = await singleUpload.mutateAsync(logoFile[0]) + siteLogo = logoResponse.results?.url?.url || undefined + } + + // آپلود کد پستی فروشگاه اگر فایل جدید انتخاب شده + if (postalCodeFile.length > 0) { + const postalResponse = await singleUpload.mutateAsync(postalCodeFile[0]) + shopPostalCode = postalResponse.results?.url?.url || undefined } // transform data برای ارسال به API (حذف id) const transformedValues = { ...values, - downloadAppDetails: finalDownloadAppDetails.map((item) => ({ + siteLogo, + shopPostalCode, + downloadAppDetails: values.downloadAppDetails.map((item) => ({ pic: item.pic, url: item.url })), - socialMediaLinks: finalSocialMediaLinks.map((item) => ({ + socialMediaLinks: values.socialMediaLinks.map((item) => ({ icon: item.icon, url: item.url })) @@ -110,8 +107,8 @@ const SiteSetting: FC = () => { updateSiteSetting.mutate(transformedValues, { onSuccess: () => { toast.success('تنظیمات سایت با موفقیت بروزرسانی شد') - // پاک کردن pending files بعد از submit موفق - setPendingFiles({}) + setLogoFile([]) + setPostalCodeFile([]) }, onError: (error) => { toast.error(extractErrorMessage(error)) @@ -151,64 +148,6 @@ const SiteSetting: FC = () => { }, [data, shopData, isLoading, isShopLoading]) - const uploadAllPendingFiles = async (): Promise<{ [key: string]: string }> => { - const uploadedUrls: { [key: string]: string } = {} - - for (const [id, file] of Object.entries(pendingFiles)) { - // پیدا کردن index آیتم در downloadAppDetails - let index = formik.values.downloadAppDetails?.findIndex(item => item.id === id) - let isDownloadApp = true - - if (index === undefined || index === -1) { - // اگر در downloadAppDetails نبود، در socialMediaLinks جستجو کن - index = formik.values.socialMediaLinks?.findIndex(item => item.id === id) - isDownloadApp = false - } - - if (index === undefined || index === -1) continue - - try { - setUploadingIndexes(prev => new Set(prev).add(index)) - - const uploadResponse = await singleUpload.mutateAsync(file) - const imageUrl = uploadResponse.results.url.url - - uploadedUrls[id] = imageUrl - - // بروزرسانی formik - if (isDownloadApp) { - const currentDetails = formik.values.downloadAppDetails || [] - const updatedDetails = currentDetails.map((item, i) => - i === index ? { ...item, pic: imageUrl } : item - ) - formik.setFieldValue('downloadAppDetails', updatedDetails) - } else { - const currentLinks = formik.values.socialMediaLinks || [] - const updatedLinks = currentLinks.map((item, i) => - i === index ? { ...item, icon: imageUrl } : item - ) - formik.setFieldValue('socialMediaLinks', updatedLinks) - } - - } catch (error) { - const itemType = isDownloadApp ? 'تصویر دانلود اپ' : 'آیکون رسانه اجتماعی' - toast.error(`خطا در آپلود ${itemType} آیتم ${index + 1}`) - throw error - } finally { - setUploadingIndexes(prev => { - const newSet = new Set(prev) - newSet.delete(index) - return newSet - }) - } - } - - return uploadedUrls - } - - - - if (isLoading || isShopLoading) { return
در حال بارگذاری...
} @@ -237,24 +176,18 @@ const SiteSetting: FC = () => {
- +
- + - + ) } diff --git a/src/pages/setting/components/DownloadAppSection.tsx b/src/pages/setting/components/DownloadAppSection.tsx index 9cf1d69..901cac6 100644 --- a/src/pages/setting/components/DownloadAppSection.tsx +++ b/src/pages/setting/components/DownloadAppSection.tsx @@ -1,9 +1,11 @@ -import { type FC } from 'react' +import { type FC, useState } from 'react' import type { FormikProps } from 'formik' import { Add, Trash } from 'iconsax-react' import Button from '../../../components/Button' import Input from '../../../components/Input' import UploadBox from '../../../components/UploadBox' +import { useSingleUpload } from '../../category/hooks/useCategoryData' +import { toast } from 'react-toastify' type DownloadAppDetail = { id: string @@ -30,17 +32,13 @@ type FormValues = { type Props = { formik: FormikProps - pendingFiles: { [key: string]: File } - setPendingFiles: React.Dispatch> - uploadingIndexes: Set - setUploadingIndexes: React.Dispatch>> } const DownloadAppSection: FC = ({ formik, - setPendingFiles, - uploadingIndexes, }) => { + const singleUpload = useSingleUpload() + const [uploadingIndexes, setUploadingIndexes] = useState>(new Set()) const addDownloadAppDetail = () => { const currentDetails = formik.values.downloadAppDetails || [] const newId = Date.now().toString() @@ -49,18 +47,7 @@ const DownloadAppSection: FC = ({ const removeDownloadAppDetail = (index: number) => { const currentDetails = formik.values.downloadAppDetails || [] - const itemToRemove = currentDetails[index] - formik.setFieldValue('downloadAppDetails', currentDetails.filter((_, i) => i !== index)) - - // پاک کردن pending file مربوطه - if (itemToRemove) { - setPendingFiles(prev => { - const newPending = { ...prev } - delete newPending[itemToRemove.id] - return newPending - }) - } } const updateDownloadAppDetail = (index: number, field: 'pic' | 'url', value: string) => { @@ -71,20 +58,26 @@ const DownloadAppSection: FC = ({ formik.setFieldValue('downloadAppDetails', updatedDetails) } - const handleDownloadAppImageUpload = (index: number, files: File[]) => { + const handleDownloadAppImageUpload = async (index: number, files: File[]) => { if (files.length === 0) return - const item = formik.values.downloadAppDetails?.[index] - if (!item) return + try { + setUploadingIndexes(prev => new Set(prev).add(index)) - // ذخیره فایل برای آپلود بعدی - setPendingFiles(prev => ({ - ...prev, - [item.id]: files[0] - })) + const uploadResponse = await singleUpload.mutateAsync(files[0]) + const imageUrl = uploadResponse.results.url.url - // نمایش preview - updateDownloadAppDetail(index, 'pic', URL.createObjectURL(files[0])) + updateDownloadAppDetail(index, 'pic', imageUrl) + toast.success('تصویر با موفقیت آپلود شد') + } catch { + toast.error('خطا در آپلود تصویر') + } finally { + setUploadingIndexes(prev => { + const newSet = new Set(prev) + newSet.delete(index) + return newSet + }) + } } return ( diff --git a/src/pages/setting/components/FilesSection.tsx b/src/pages/setting/components/FilesSection.tsx index 14c8fe1..a81d30c 100644 --- a/src/pages/setting/components/FilesSection.tsx +++ b/src/pages/setting/components/FilesSection.tsx @@ -21,9 +21,19 @@ type FormValues = { type Props = { formik: FormikProps + logoFile: File[] + setLogoFile: React.Dispatch> + postalCodeFile: File[] + setPostalCodeFile: React.Dispatch> } -const FilesSection: FC = ({ formik }) => { +const FilesSection: FC = ({ + formik, + logoFile, + setLogoFile, + postalCodeFile, + setPostalCodeFile +}) => { return (
@@ -35,14 +45,14 @@ const FilesSection: FC = ({ formik }) => { { - if (files.length > 0) { - formik.setFieldValue('siteLogo', URL.createObjectURL(files[0])) - } - }} + onChange={(files) => setLogoFile(files)} /> - {formik.values.siteLogo && ( - لوگو سایت + {(logoFile.length > 0 || formik.values.siteLogo) && ( + 0 ? URL.createObjectURL(logoFile[0]) : formik.values.siteLogo} + alt="لوگو سایت" + className="mt-2 w-20 h-20 object-contain rounded" + /> )}
@@ -51,14 +61,14 @@ const FilesSection: FC = ({ formik }) => { { - if (files.length > 0) { - formik.setFieldValue('shopPostalCode', URL.createObjectURL(files[0])) - } - }} + onChange={(files) => setPostalCodeFile(files)} /> - {formik.values.shopPostalCode && ( - کد پستی فروشگاه + {(postalCodeFile.length > 0 || formik.values.shopPostalCode) && ( + 0 ? URL.createObjectURL(postalCodeFile[0]) : formik.values.shopPostalCode} + alt="کد پستی فروشگاه" + className="mt-2 w-20 h-20 object-contain rounded" + /> )}
diff --git a/src/pages/setting/components/SocialMediaSection.tsx b/src/pages/setting/components/SocialMediaSection.tsx index 05dd344..bc94067 100644 --- a/src/pages/setting/components/SocialMediaSection.tsx +++ b/src/pages/setting/components/SocialMediaSection.tsx @@ -1,9 +1,11 @@ -import { type FC } from 'react' +import { type FC, useState } from 'react' import type { FormikProps } from 'formik' import { Add, Trash } from 'iconsax-react' import Button from '../../../components/Button' import Input from '../../../components/Input' import UploadBox from '../../../components/UploadBox' +import { useSingleUpload } from '../../category/hooks/useCategoryData' +import { toast } from 'react-toastify' type SocialMediaLink = { id: string @@ -24,17 +26,13 @@ type FormValues = { type Props = { formik: FormikProps - pendingFiles: { [key: string]: File } - setPendingFiles: React.Dispatch> - uploadingIndexes: Set - setUploadingIndexes: React.Dispatch>> } const SocialMediaSection: FC = ({ formik, - setPendingFiles, - uploadingIndexes, }) => { + const singleUpload = useSingleUpload() + const [uploadingIndexes, setUploadingIndexes] = useState>(new Set()) const addSocialMediaLink = () => { const currentLinks = formik.values.socialMediaLinks || [] const newId = Date.now().toString() @@ -43,18 +41,7 @@ const SocialMediaSection: FC = ({ const removeSocialMediaLink = (index: number) => { const currentLinks = formik.values.socialMediaLinks || [] - const itemToRemove = currentLinks[index] - formik.setFieldValue('socialMediaLinks', currentLinks.filter((_, i) => i !== index)) - - // پاک کردن pending file مربوطه - if (itemToRemove) { - setPendingFiles(prev => { - const newPending = { ...prev } - delete newPending[itemToRemove.id] - return newPending - }) - } } const updateSocialMediaLink = (index: number, field: 'url', value: string) => { @@ -65,20 +52,26 @@ const SocialMediaSection: FC = ({ formik.setFieldValue('socialMediaLinks', updatedLinks) } - const handleSocialMediaIconUpload = (index: number, files: File[]) => { + const handleSocialMediaIconUpload = async (index: number, files: File[]) => { if (files.length === 0) return - const item = formik.values.socialMediaLinks?.[index] - if (!item) return + try { + setUploadingIndexes(prev => new Set(prev).add(index)) - // ذخیره فایل برای آپلود بعدی - setPendingFiles(prev => ({ - ...prev, - [item.id]: files[0] - })) + const uploadResponse = await singleUpload.mutateAsync(files[0]) + const imageUrl = uploadResponse.results.url.url - // نمایش preview - updateSocialMediaLinkIcon(index, URL.createObjectURL(files[0])) + updateSocialMediaLinkIcon(index, imageUrl) + toast.success('آیکون با موفقیت آپلود شد') + } catch { + toast.error('خطا در آپلود آیکون') + } finally { + setUploadingIndexes(prev => { + const newSet = new Set(prev) + newSet.delete(index) + return newSet + }) + } } const updateSocialMediaLinkIcon = (index: number, iconUrl: string) => {