From 30f1e4768a171d247fb6ff82f7b838ee69c83191 Mon Sep 17 00:00:00 2001 From: hosseintaromi Date: Fri, 19 Dec 2025 23:40:01 +0330 Subject: [PATCH] fix --- src/constant/routes.ts | 3 +- src/hooks/useFileUpload.ts | 17 +- src/pages/products/core/_requests.ts | 3 +- .../products/product-form/ProductFormPage.tsx | 198 +++++++++--------- 4 files changed, 110 insertions(+), 111 deletions(-) diff --git a/src/constant/routes.ts b/src/constant/routes.ts index e5ebc55..fee4f6e 100644 --- a/src/constant/routes.ts +++ b/src/constant/routes.ts @@ -55,7 +55,7 @@ export const API_ROUTES = { GET_PRODUCTS: "api/v1/products", GET_PRODUCT: (id: string) => `api/v1/products/${id}`, CREATE_PRODUCT: "api/v1/products", - UPDATE_PRODUCT: (id: string) => `api/v1/products/${id}`, + UPDATE_PRODUCT: (id: string) => `products/${id}`, DELETE_PRODUCT: (id: string) => `api/v1/products/${id}`, GET_PRODUCT_VARIANTS: (id: string) => `api/v1/products/${id}/variants`, CREATE_PRODUCT_VARIANT: (id: string) => `api/v1/products/${id}/variants`, @@ -67,6 +67,7 @@ export const API_ROUTES = { // Files APIs GET_FILES: "files", UPLOAD_FILE: "files", + UPLOAD_USER_FILE: "api/v1/users/files", GET_FILE: (id: string) => `files/${id}`, UPDATE_FILE: (id: string) => `files/${id}`, DELETE_FILE: (id: string) => `files/${id}`, diff --git a/src/hooks/useFileUpload.ts b/src/hooks/useFileUpload.ts index 23e52d8..9fb4e23 100644 --- a/src/hooks/useFileUpload.ts +++ b/src/hooks/useFileUpload.ts @@ -21,20 +21,13 @@ interface UploadResponse { export const useFileUpload = () => { return useMutation({ mutationFn: async (file: File): Promise<{ id: string; url: string; mimeType?: string }> => { - const formData = new FormData(); - formData.append("file", file); - formData.append("name", "uploaded-file"); - - console.log("Uploading file:", file.name); + const contentType = + file.type && file.type.startsWith("video") ? "video/mp4" : "image/png"; const response = await httpPostRequest( - APIUrlGenerator(API_ROUTES.UPLOAD_FILE), - formData, - { - headers: { - "Content-Type": "multipart/form-data", - }, - } + APIUrlGenerator(API_ROUTES.UPLOAD_USER_FILE, undefined, undefined, false), + file, + { headers: { "Content-Type": contentType, Accept: "application/json" } } ); console.log("Upload response:", response); diff --git a/src/pages/products/core/_requests.ts b/src/pages/products/core/_requests.ts index 22d9a89..5a2db4b 100644 --- a/src/pages/products/core/_requests.ts +++ b/src/pages/products/core/_requests.ts @@ -105,8 +105,7 @@ export const updateProduct = async (data: UpdateProductRequest) => { APIUrlGenerator( API_ROUTES.UPDATE_PRODUCT(data.id.toString()), undefined, - undefined, - false + undefined ), data ); diff --git a/src/pages/products/product-form/ProductFormPage.tsx b/src/pages/products/product-form/ProductFormPage.tsx index 83f7f66..fbc58e5 100644 --- a/src/pages/products/product-form/ProductFormPage.tsx +++ b/src/pages/products/product-form/ProductFormPage.tsx @@ -40,116 +40,122 @@ const productSchema = yup.object({ }); const toPublicUrl = (img: any): ProductImage => { - const rawUrl: string = img?.url || img?.file_url || img?.fileUrl || ''; - const serveKey: string | undefined = img?.serve_key || img?.serveKey; - const url = serveKey - ? `${API_GATE_WAY}/${API_ROUTES.DOWNLOAD_FILE(serveKey)}` - : rawUrl?.startsWith('http') - ? rawUrl - : rawUrl - ? `${API_GATE_WAY}${rawUrl.startsWith('/') ? '' : '/'}${rawUrl}` - : ''; - return { - id: (img?.id ?? img?.file_id ?? img?.FileID ?? img).toString(), - url, - alt: img?.alt || img?.original_name || '', - order: img?.order ?? 0, - type: img?.mime_type || img?.type || img?.file_type, - mime_type: img?.mime_type || img?.file_type, - size: img?.size, - }; + const rawUrl: string = img?.url || img?.file_url || img?.fileUrl || ''; + const serveKey: string | undefined = img?.serve_key || img?.serveKey; + const url = serveKey + ? `${API_GATE_WAY}/${API_ROUTES.DOWNLOAD_FILE(serveKey)}` + : rawUrl?.startsWith('http') + ? rawUrl + : rawUrl + ? `${API_GATE_WAY}${rawUrl.startsWith('/') ? '' : '/'}${rawUrl}` + : ''; + return { + id: (img?.id ?? img?.file_id ?? img?.FileID ?? img).toString(), + url, + alt: img?.alt || img?.original_name || '', + order: img?.order ?? 0, + type: img?.mime_type || img?.type || img?.file_type, + mime_type: img?.mime_type || img?.file_type, + size: img?.size, + }; }; const IMAGE_MAX_SIZE = 2 * 1024 * 1024; -const VIDEO_MAX_SIZE = 25 * 1024 * 1024; +const VIDEO_MAX_SIZE = 50 * 1024 * 1024; const isImageFile = (file: File) => file.type?.startsWith('image/'); const isVideoFile = (file: File) => file.type?.startsWith('video/'); const ensureSquareImage = (file: File) => - new Promise((resolve, reject) => { - const url = URL.createObjectURL(file); - const img = new Image(); - img.onload = () => { - URL.revokeObjectURL(url); - if (img.width === img.height) { - resolve(); - } else { - reject(new Error('ابعاد تصویر Explorer باید ۱ در ۱ باشد')); - } - }; - img.onerror = () => { - URL.revokeObjectURL(url); - reject(new Error('امکان بررسی ابعاد تصویر وجود ندارد')); - }; - img.src = url; - }); + new Promise((resolve, reject) => { + const url = URL.createObjectURL(file); + const img = new Image(); + img.onload = () => { + URL.revokeObjectURL(url); + if (img.width === img.height) { + resolve(); + } else { + reject(new Error('ابعاد تصویر Explorer باید ۱ در ۱ باشد')); + } + }; + img.onerror = () => { + URL.revokeObjectURL(url); + reject(new Error('امکان بررسی ابعاد تصویر وجود ندارد')); + }; + img.src = url; + }); const validateMediaFile = async (file: File, options?: { requireSquare?: boolean }) => { - if (isImageFile(file)) { - if (file.size > IMAGE_MAX_SIZE) { - throw new Error('حجم تصویر نباید بیشتر از ۲ مگابایت باشد'); + if (isImageFile(file)) { + if (file.size > IMAGE_MAX_SIZE) { + throw new Error('حجم تصویر نباید بیشتر از ۲ مگابایت باشد'); + } + if (options?.requireSquare) { + await ensureSquareImage(file); + } + } else if (isVideoFile(file)) { + if (file.size > VIDEO_MAX_SIZE) { + throw new Error('حجم ویدیو نباید بیشتر از ۲۵ مگابایت باشد'); + } + } else { + throw new Error('فقط تصاویر یا ویدیو مجاز است'); } - if (options?.requireSquare) { - await ensureSquareImage(file); - } - } else if (isVideoFile(file)) { - if (file.size > VIDEO_MAX_SIZE) { - throw new Error('حجم ویدیو نباید بیشتر از ۲۵ مگابایت باشد'); - } - } else { - throw new Error('فقط تصاویر یا ویدیو مجاز است'); - } }; const validateExplorerFile = async (file: File) => { - if (isImageFile(file)) { - await ensureSquareImage(file); - return; - } - if (isVideoFile(file)) { - return; - } - throw new Error('فقط تصاویر یا ویدیو مجاز است'); + if (isImageFile(file)) { + if (file.size > IMAGE_MAX_SIZE) { + throw new Error('حجم تصویر نباید بیشتر از ۲ مگابایت باشد'); + } + await ensureSquareImage(file); + return; + } + if (isVideoFile(file)) { + if (file.size > VIDEO_MAX_SIZE) { + throw new Error('حجم ویدیو نباید بیشتر از ۵۰ مگابایت باشد'); + } + return; + } + throw new Error('فقط تصاویر یا ویدیو مجاز است'); }; const mapExplorerFiles = (entries: any[]): ProductImage[] => { - if (!entries || !Array.isArray(entries)) { - return []; - } - return entries.map((entry, index) => { - if (entry?.file) { - const media = toPublicUrl(entry.file); - return { ...media, order: index }; + if (!entries || !Array.isArray(entries)) { + return []; } - if (entry?.file_id) { - const normalized = toPublicUrl({ - ...entry, - id: entry.file_id, - url: entry.file_url || entry.url, - file_url: entry.file_url || entry.url, - mime_type: entry.mime_type || entry.file_type, - type: entry.file_type || entry.type, - original_name: entry.name || entry.original_name, - }); - return { ...normalized, order: index }; - } - if (entry?.FileID) { - const normalized = toPublicUrl({ - ...entry, - id: entry.FileID, - url: entry.file_url || entry.url, - file_url: entry.file_url || entry.url, - }); - return { ...normalized, order: index }; - } - if (typeof entry === 'number' || typeof entry === 'string') { - const normalized = toPublicUrl(entry); - return { ...normalized, order: index }; - } - const normalized = toPublicUrl(entry); - return { ...normalized, order: index }; - }); + return entries.map((entry, index) => { + if (entry?.file) { + const media = toPublicUrl(entry.file); + return { ...media, order: index }; + } + if (entry?.file_id) { + const normalized = toPublicUrl({ + ...entry, + id: entry.file_id, + url: entry.file_url || entry.url, + file_url: entry.file_url || entry.url, + mime_type: entry.mime_type || entry.file_type, + type: entry.file_type || entry.type, + original_name: entry.name || entry.original_name, + }); + return { ...normalized, order: index }; + } + if (entry?.FileID) { + const normalized = toPublicUrl({ + ...entry, + id: entry.FileID, + url: entry.file_url || entry.url, + file_url: entry.file_url || entry.url, + }); + return { ...normalized, order: index }; + } + if (typeof entry === 'number' || typeof entry === 'string') { + const normalized = toPublicUrl(entry); + return { ...normalized, order: index }; + } + const normalized = toPublicUrl(entry); + return { ...normalized, order: index }; + }); }; const ProductFormPage = () => { @@ -606,11 +612,11 @@ const ProductFormPage = () => { onUpload={handleFileUpload} onRemove={handleFileRemove} acceptedTypes={['image/*', 'video/*']} - maxFileSize={25 * 1024 * 1024} + maxFileSize={50 * 1024 * 1024} maxFiles={10} mode="multi" label="" - description="تصاویر یا ویدیوهای محصول را آپلود کنید (حداکثر ۲ مگ برای تصویر و ۲۵ مگ برای ویدیو)" + description="تصاویر یا ویدیوهای محصول را آپلود کنید (حداکثر ۲ مگ برای تصویر و ۵۰ مگ برای ویدیو)" onUploadStart={() => setIsUploading(true)} onUploadComplete={() => setIsUploading(false)} /> @@ -667,11 +673,11 @@ const ProductFormPage = () => { onUpload={handleExplorerUpload} onRemove={handleExplorerRemove} acceptedTypes={['image/*', 'video/*']} - maxFileSize={0} + maxFileSize={50 * 1024 * 1024} maxFiles={5} mode="multi" label="" - description="فایل‌های Explorer را آپلود کنید (تصاویر باید مربعی باشند)" + description="فایل‌های Explorer را آپلود کنید (تصویر: ۲ مگ، ویدیو: ۵۰ مگ، تصاویر باید مربعی باشند)" onUploadStart={() => setIsExplorerUploading(true)} onUploadComplete={() => setIsExplorerUploading(false)} />