refactor: replace images with file_ids in product management components
This commit is contained in:
parent
4f4ef51ccc
commit
a228605ba0
|
|
@ -40,11 +40,11 @@ const VariantForm: React.FC<VariantFormProps> = ({ variant, onSave, onCancel, is
|
||||||
product_option_id: undefined,
|
product_option_id: undefined,
|
||||||
attributes: {},
|
attributes: {},
|
||||||
meta: {},
|
meta: {},
|
||||||
images: []
|
file_ids: []
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const [uploadedImages, setUploadedImages] = useState<ProductImage[]>(variant?.images || []);
|
const [uploadedImages, setUploadedImages] = useState<ProductImage[]>(variant?.file_ids || []);
|
||||||
const [attributes, setAttributes] = useState<Record<string, any>>(variant?.attributes || {});
|
const [attributes, setAttributes] = useState<Record<string, any>>(variant?.attributes || {});
|
||||||
const [meta, setMeta] = useState<Record<string, any>>(variant?.meta || {});
|
const [meta, setMeta] = useState<Record<string, any>>(variant?.meta || {});
|
||||||
const [newAttributeKey, setNewAttributeKey] = useState('');
|
const [newAttributeKey, setNewAttributeKey] = useState('');
|
||||||
|
|
@ -129,7 +129,7 @@ const VariantForm: React.FC<VariantFormProps> = ({ variant, onSave, onCancel, is
|
||||||
...formData,
|
...formData,
|
||||||
attributes,
|
attributes,
|
||||||
meta,
|
meta,
|
||||||
images: uploadedImages
|
file_ids: uploadedImages
|
||||||
});
|
});
|
||||||
|
|
||||||
onSave(convertedData);
|
onSave(convertedData);
|
||||||
|
|
@ -547,9 +547,9 @@ export const VariantManager: React.FC<VariantManagerProps> = ({ variants, onChan
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{variant.images && variant.images.length > 0 && (
|
{variant.file_ids && variant.file_ids.length > 0 && (
|
||||||
<div className="flex gap-2 mt-3">
|
<div className="flex gap-2 mt-3">
|
||||||
{variant.images.slice(0, 3).map((image, imgIndex) => (
|
{variant.file_ids.slice(0, 3).map((image, imgIndex) => (
|
||||||
<img
|
<img
|
||||||
key={image.id}
|
key={image.id}
|
||||||
src={image.url}
|
src={image.url}
|
||||||
|
|
@ -557,9 +557,9 @@ export const VariantManager: React.FC<VariantManagerProps> = ({ variants, onChan
|
||||||
className="w-12 h-12 object-cover rounded border"
|
className="w-12 h-12 object-cover rounded border"
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{variant.images.length > 3 && (
|
{variant.file_ids.length > 3 && (
|
||||||
<div className="w-12 h-12 bg-gray-100 dark:bg-gray-600 rounded border flex items-center justify-center text-xs">
|
<div className="w-12 h-12 bg-gray-100 dark:bg-gray-600 rounded border flex items-center justify-center text-xs">
|
||||||
+{variant.images.length - 3}
|
+{variant.file_ids.length - 3}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ export interface ProductVariant {
|
||||||
product_option_id?: number;
|
product_option_id?: number;
|
||||||
attributes?: Record<string, any>;
|
attributes?: Record<string, any>;
|
||||||
meta?: Record<string, any>;
|
meta?: Record<string, any>;
|
||||||
images?: ProductImage[];
|
file_ids?: ProductImage[];
|
||||||
created_at?: string;
|
created_at?: string;
|
||||||
updated_at?: string;
|
updated_at?: string;
|
||||||
}
|
}
|
||||||
|
|
@ -44,7 +44,7 @@ export interface Product {
|
||||||
price?: number;
|
price?: number;
|
||||||
status?: string;
|
status?: string;
|
||||||
attributes?: Record<string, any>;
|
attributes?: Record<string, any>;
|
||||||
images: ProductImage[];
|
file_ids: ProductImage[];
|
||||||
variants?: ProductVariant[];
|
variants?: ProductVariant[];
|
||||||
product_variants?: ProductVariant[];
|
product_variants?: ProductVariant[];
|
||||||
created_at: string;
|
created_at: string;
|
||||||
|
|
@ -61,7 +61,7 @@ export interface ProductFormData {
|
||||||
total_sold: number;
|
total_sold: number;
|
||||||
type: number;
|
type: number;
|
||||||
attributes: Record<string, any>;
|
attributes: Record<string, any>;
|
||||||
images: ProductImage[];
|
file_ids: ProductImage[];
|
||||||
variants: ProductVariantFormData[];
|
variants: ProductVariantFormData[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ export interface ProductVariantFormData {
|
||||||
product_option_id?: number;
|
product_option_id?: number;
|
||||||
attributes: Record<string, any>;
|
attributes: Record<string, any>;
|
||||||
meta: Record<string, any>;
|
meta: Record<string, any>;
|
||||||
images: ProductImage[];
|
file_ids: ProductImage[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProductFilters {
|
export interface ProductFilters {
|
||||||
|
|
@ -100,7 +100,7 @@ export interface CreateProductRequest {
|
||||||
total_sold: number;
|
total_sold: number;
|
||||||
type: number;
|
type: number;
|
||||||
attributes?: Record<string, any>;
|
attributes?: Record<string, any>;
|
||||||
images?: number[];
|
file_ids?: number[];
|
||||||
variants?: CreateVariantRequest[];
|
variants?: CreateVariantRequest[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,7 +115,7 @@ export interface UpdateProductRequest {
|
||||||
total_sold: number;
|
total_sold: number;
|
||||||
type: number;
|
type: number;
|
||||||
attributes?: Record<string, any>;
|
attributes?: Record<string, any>;
|
||||||
images?: number[];
|
file_ids?: number[];
|
||||||
variants?: UpdateVariantRequest[];
|
variants?: UpdateVariantRequest[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,6 +130,7 @@ export interface CreateVariantRequest {
|
||||||
weight: number;
|
weight: number;
|
||||||
attributes?: Record<string, any>;
|
attributes?: Record<string, any>;
|
||||||
meta?: Record<string, any>;
|
meta?: Record<string, any>;
|
||||||
|
file_ids?: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateVariantRequest {
|
export interface UpdateVariantRequest {
|
||||||
|
|
@ -143,6 +144,7 @@ export interface UpdateVariantRequest {
|
||||||
weight: number;
|
weight: number;
|
||||||
attributes?: Record<string, any>;
|
attributes?: Record<string, any>;
|
||||||
meta?: Record<string, any>;
|
meta?: Record<string, any>;
|
||||||
|
file_ids?: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProductsResponse {
|
export interface ProductsResponse {
|
||||||
|
|
|
||||||
|
|
@ -184,14 +184,14 @@ const ProductDetailPage = () => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* تصاویر محصول */}
|
{/* تصاویر محصول */}
|
||||||
{product.images && product.images.length > 0 && (
|
{product.file_ids && product.file_ids.length > 0 && (
|
||||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6">
|
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6">
|
||||||
<SectionTitle className="flex items-center gap-2 mb-4">
|
<SectionTitle className="flex items-center gap-2 mb-4">
|
||||||
<Image className="h-5 w-5" />
|
<Image className="h-5 w-5" />
|
||||||
تصاویر محصول
|
تصاویر محصول
|
||||||
</SectionTitle>
|
</SectionTitle>
|
||||||
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||||
{product.images.map((image, index) => (
|
{product.file_ids.map((image, index) => (
|
||||||
<div key={image.id || index} className="relative group">
|
<div key={image.id || index} className="relative group">
|
||||||
<img
|
<img
|
||||||
src={image.url}
|
src={image.url}
|
||||||
|
|
@ -321,13 +321,13 @@ const ProductDetailPage = () => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* تصاویر نسخه */}
|
{/* تصاویر نسخه */}
|
||||||
{variant.images && variant.images.length > 0 && (
|
{variant.file_ids && variant.file_ids.length > 0 && (
|
||||||
<div>
|
<div>
|
||||||
<h5 className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
<h5 className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||||
تصاویر نسخه
|
تصاویر نسخه
|
||||||
</h5>
|
</h5>
|
||||||
<div className="grid grid-cols-4 gap-2">
|
<div className="grid grid-cols-4 gap-2">
|
||||||
{variant.images.map((image, imgIndex) => (
|
{variant.file_ids.map((image, imgIndex) => (
|
||||||
<img
|
<img
|
||||||
key={image.id || imgIndex}
|
key={image.id || imgIndex}
|
||||||
src={image.url}
|
src={image.url}
|
||||||
|
|
@ -392,7 +392,7 @@ const ProductDetailPage = () => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{product.images && (
|
{product.file_ids && (
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Image className="h-4 w-4 text-purple-500" />
|
<Image className="h-4 w-4 text-purple-500" />
|
||||||
|
|
@ -401,7 +401,7 @@ const ProductDetailPage = () => {
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span className="font-semibold text-gray-900 dark:text-gray-100">
|
<span className="font-semibold text-gray-900 dark:text-gray-100">
|
||||||
{formatNumber(product.images.length)}
|
{formatNumber(product.file_ids.length)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ const productSchema = yup.object({
|
||||||
category_ids: yup.array().of(yup.number()).default([]),
|
category_ids: yup.array().of(yup.number()).default([]),
|
||||||
product_option_id: yup.number().transform(createOptionalNumberTransform()).nullable(),
|
product_option_id: yup.number().transform(createOptionalNumberTransform()).nullable(),
|
||||||
attributes: yup.object().default({}),
|
attributes: yup.object().default({}),
|
||||||
images: yup.array().of(yup.object()).default([]),
|
file_ids: yup.array().of(yup.object()).default([]),
|
||||||
variants: yup.array().default([]),
|
variants: yup.array().default([]),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ const ProductFormPage = () => {
|
||||||
category_ids: [],
|
category_ids: [],
|
||||||
product_option_id: undefined,
|
product_option_id: undefined,
|
||||||
attributes: {},
|
attributes: {},
|
||||||
images: [],
|
file_ids: [],
|
||||||
variants: []
|
variants: []
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -113,7 +113,7 @@ const ProductFormPage = () => {
|
||||||
product_option_id: variant.product_option_id || undefined,
|
product_option_id: variant.product_option_id || undefined,
|
||||||
attributes: variant.attributes || {},
|
attributes: variant.attributes || {},
|
||||||
meta: variant.meta || {},
|
meta: variant.meta || {},
|
||||||
images: variant.images || []
|
file_ids: variant.file_ids || []
|
||||||
}));
|
}));
|
||||||
|
|
||||||
console.log('✅ Successfully processed variants:', formVariants.length);
|
console.log('✅ Successfully processed variants:', formVariants.length);
|
||||||
|
|
@ -128,10 +128,10 @@ const ProductFormPage = () => {
|
||||||
category_ids: categoryIds,
|
category_ids: categoryIds,
|
||||||
product_option_id: product.product_option_id || undefined,
|
product_option_id: product.product_option_id || undefined,
|
||||||
attributes: product.attributes || {},
|
attributes: product.attributes || {},
|
||||||
images: product.images || [],
|
file_ids: product.file_ids || [],
|
||||||
variants: formVariants
|
variants: formVariants
|
||||||
});
|
});
|
||||||
setUploadedImages(product.images || []);
|
setUploadedImages(product.file_ids || []);
|
||||||
setAttributes(product.attributes || {});
|
setAttributes(product.attributes || {});
|
||||||
}
|
}
|
||||||
}, [isEdit, product, reset]);
|
}, [isEdit, product, reset]);
|
||||||
|
|
@ -148,7 +148,7 @@ const ProductFormPage = () => {
|
||||||
|
|
||||||
const updatedImages = [...uploadedImages, newImage];
|
const updatedImages = [...uploadedImages, newImage];
|
||||||
setUploadedImages(updatedImages);
|
setUploadedImages(updatedImages);
|
||||||
setValue('images', updatedImages, { shouldValidate: true, shouldDirty: true });
|
setValue('file_ids', updatedImages, { shouldValidate: true, shouldDirty: true });
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -160,7 +160,7 @@ const ProductFormPage = () => {
|
||||||
const handleFileRemove = (fileId: string) => {
|
const handleFileRemove = (fileId: string) => {
|
||||||
const updatedImages = uploadedImages.filter(img => img.id !== fileId);
|
const updatedImages = uploadedImages.filter(img => img.id !== fileId);
|
||||||
setUploadedImages(updatedImages);
|
setUploadedImages(updatedImages);
|
||||||
setValue('images', updatedImages, { shouldValidate: true, shouldDirty: true });
|
setValue('file_ids', updatedImages, { shouldValidate: true, shouldDirty: true });
|
||||||
deleteFile(fileId);
|
deleteFile(fileId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -204,7 +204,7 @@ const ProductFormPage = () => {
|
||||||
attributes: convertPersianNumbersInObject(attributes),
|
attributes: convertPersianNumbersInObject(attributes),
|
||||||
category_ids: convertedData.category_ids.length > 0 ? convertedData.category_ids : [],
|
category_ids: convertedData.category_ids.length > 0 ? convertedData.category_ids : [],
|
||||||
product_option_id: convertedData.product_option_id || null,
|
product_option_id: convertedData.product_option_id || null,
|
||||||
images: validImageIds
|
file_ids: validImageIds
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('Submitting product data:', baseSubmitData);
|
console.log('Submitting product data:', baseSubmitData);
|
||||||
|
|
@ -223,6 +223,7 @@ const ProductFormPage = () => {
|
||||||
stock_number: variant.stock_number,
|
stock_number: variant.stock_number,
|
||||||
weight: variant.weight,
|
weight: variant.weight,
|
||||||
product_option_id: variant.product_option_id || null,
|
product_option_id: variant.product_option_id || null,
|
||||||
|
file_ids: (variant.file_ids || []).map((img: any) => Number(img.id)).filter((id: number) => !isNaN(id)),
|
||||||
attributes: variant.attributes && Object.keys(variant.attributes).length > 0 ? variant.attributes : {},
|
attributes: variant.attributes && Object.keys(variant.attributes).length > 0 ? variant.attributes : {},
|
||||||
meta: variant.meta && Object.keys(variant.meta).length > 0 ? variant.meta : {}
|
meta: variant.meta && Object.keys(variant.meta).length > 0 ? variant.meta : {}
|
||||||
})) || [];
|
})) || [];
|
||||||
|
|
@ -247,6 +248,7 @@ const ProductFormPage = () => {
|
||||||
stock_number: variant.stock_number,
|
stock_number: variant.stock_number,
|
||||||
weight: variant.weight,
|
weight: variant.weight,
|
||||||
product_option_id: variant.product_option_id || null,
|
product_option_id: variant.product_option_id || null,
|
||||||
|
file_ids: (variant.file_ids || []).map((img: any) => Number(img.id)).filter((id: number) => !isNaN(id)),
|
||||||
attributes: variant.attributes && Object.keys(variant.attributes).length > 0 ? variant.attributes : {},
|
attributes: variant.attributes && Object.keys(variant.attributes).length > 0 ? variant.attributes : {},
|
||||||
meta: variant.meta && Object.keys(variant.meta).length > 0 ? variant.meta : {}
|
meta: variant.meta && Object.keys(variant.meta).length > 0 ? variant.meta : {}
|
||||||
})) || [];
|
})) || [];
|
||||||
|
|
|
||||||
|
|
@ -281,9 +281,9 @@ const ProductsListPage = () => {
|
||||||
<td className="px-6 py-4 whitespace-nowrap">
|
<td className="px-6 py-4 whitespace-nowrap">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0">
|
||||||
{product.images && product.images.length > 0 ? (
|
{product.file_ids && product.file_ids.length > 0 ? (
|
||||||
<img
|
<img
|
||||||
src={product.images[0].url}
|
src={product.file_ids[0].url}
|
||||||
alt={product.name}
|
alt={product.name}
|
||||||
className="w-10 h-10 object-cover rounded"
|
className="w-10 h-10 object-cover rounded"
|
||||||
/>
|
/>
|
||||||
|
|
@ -352,9 +352,9 @@ const ProductsListPage = () => {
|
||||||
<div key={product.id} className="border border-gray-200 dark:border-gray-700 rounded-lg p-4">
|
<div key={product.id} className="border border-gray-200 dark:border-gray-700 rounded-lg p-4">
|
||||||
<div className="flex gap-3 mb-3">
|
<div className="flex gap-3 mb-3">
|
||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0">
|
||||||
{product.images && product.images.length > 0 ? (
|
{product.file_ids && product.file_ids.length > 0 ? (
|
||||||
<img
|
<img
|
||||||
src={product.images[0].url}
|
src={product.file_ids[0].url}
|
||||||
alt={product.name}
|
alt={product.name}
|
||||||
className="w-12 h-12 object-cover rounded"
|
className="w-12 h-12 object-cover rounded"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue