update product
This commit is contained in:
@@ -128,5 +128,6 @@ export const Pages = {
|
|||||||
create: "/products/create",
|
create: "/products/create",
|
||||||
list: "/products/list",
|
list: "/products/list",
|
||||||
variants: "/products/variants/",
|
variants: "/products/variants/",
|
||||||
|
update: "/products/update/",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ body {
|
|||||||
overflow-x: hidden !important;
|
overflow-x: hidden !important;
|
||||||
background: #eceef6;
|
background: #eceef6;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
overflow: hidden;
|
overflow: hidden !important;
|
||||||
}
|
}
|
||||||
html,
|
html,
|
||||||
body,
|
body,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import PaginationUi from '../../components/PaginationUi';
|
|||||||
import StatusWithText from '../../components/StatusWithText';
|
import StatusWithText from '../../components/StatusWithText';
|
||||||
import Td from '../../components/Td';
|
import Td from '../../components/Td';
|
||||||
import TrashWithConfrim from '../../components/TrashWithConfrim';
|
import TrashWithConfrim from '../../components/TrashWithConfrim';
|
||||||
import { Edit, Eye } from 'iconsax-react';
|
import { Edit } from 'iconsax-react';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Pages } from '@/config/Pages';
|
import { Pages } from '@/config/Pages';
|
||||||
@@ -126,9 +126,11 @@ const List: FC = () => {
|
|||||||
<Td text={String(product.default_variant?.stock || 0)} />
|
<Td text={String(product.default_variant?.stock || 0)} />
|
||||||
<Td text="">
|
<Td text="">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Eye color='#8C90A3' size={19} />
|
{product.status === ProductStatus.Draft && (
|
||||||
|
<Link to={`${Pages.products.update}${product._id}`}>
|
||||||
<Edit color='#8C90A3' size={16} />
|
<Edit color='#8C90A3' size={16} className="cursor-pointer hover:text-blue-500" />
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
|
||||||
<TrashWithConfrim
|
<TrashWithConfrim
|
||||||
onDelete={() => {
|
onDelete={() => {
|
||||||
|
|||||||
@@ -0,0 +1,209 @@
|
|||||||
|
import { type FC, useState, useEffect } from 'react';
|
||||||
|
import { useParams, useNavigate } from 'react-router-dom';
|
||||||
|
import { useGetProductById } from './hooks/useProductData';
|
||||||
|
import { useUpdateProductDetail, useUpdateProductAttribute, useUpdateProduct } from './hooks/useProductData';
|
||||||
|
import { useGetBrands } from '../brand/hooks/useBrandData';
|
||||||
|
import { useGetCategories } from '../category/hooks/useCategoryData';
|
||||||
|
import { StepIndicator, Step1Form, Step2Form, Step3Form } from './components';
|
||||||
|
import { type CreateProductDetailRequestType, type CreateProductAttributeRequestType, type SaveProductRequestType } from './types/Types';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
import { Pages } from '@/config/Pages';
|
||||||
|
import { extractErrorMessage } from '@/helpers/utils';
|
||||||
|
|
||||||
|
const UpdateProduct: FC = () => {
|
||||||
|
const { id: productId } = useParams<{ id: string }>();
|
||||||
|
const productIdNum = parseInt(productId!, 10);
|
||||||
|
const [currentStep, setCurrentStep] = useState<1 | 2 | 3>(1);
|
||||||
|
const [productData, setProductData] = useState<Partial<CreateProductDetailRequestType & CreateProductAttributeRequestType & SaveProductRequestType>>({});
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// Fetch existing product data
|
||||||
|
const { data: productDetails, isLoading: productLoading, error: productError } = useGetProductById(productId!);
|
||||||
|
|
||||||
|
// API hooks
|
||||||
|
const updateProductDetailMutation = useUpdateProductDetail();
|
||||||
|
const updateProductAttributeMutation = useUpdateProductAttribute();
|
||||||
|
const updateProductMutation = useUpdateProduct();
|
||||||
|
const { data: brandsData } = useGetBrands();
|
||||||
|
const { data: categoriesData, isLoading: categoriesLoading } = useGetCategories();
|
||||||
|
|
||||||
|
// Initialize product data when product details are loaded
|
||||||
|
useEffect(() => {
|
||||||
|
if (productDetails?.results?.product) {
|
||||||
|
const product = productDetails.results.product;
|
||||||
|
setProductData({
|
||||||
|
productId: product._id,
|
||||||
|
category: product.category._id,
|
||||||
|
brand: product.brand._id,
|
||||||
|
model: product.model,
|
||||||
|
title_fa: product.title_fa,
|
||||||
|
title_en: product.title_en,
|
||||||
|
seoTitle: product.seoTitle || '',
|
||||||
|
source: product.source,
|
||||||
|
isFake: product.isFake,
|
||||||
|
attributes: product.specifications?.map(spec => ({
|
||||||
|
id: 0, // This might need to be adjusted based on API
|
||||||
|
values: spec.values.map(() => 0) // This might need to be adjusted based on API
|
||||||
|
})) || [],
|
||||||
|
description: product.description,
|
||||||
|
metaDescription: product.metaDescription,
|
||||||
|
tags: product.tags,
|
||||||
|
advantages: product.advantages,
|
||||||
|
disAdvantages: product.disAdvantages,
|
||||||
|
imagesList: product.imagesUrl?.list || [],
|
||||||
|
coverImage: product.imagesUrl?.cover || '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [productDetails]);
|
||||||
|
|
||||||
|
if (productLoading) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[400px]">
|
||||||
|
<div>در حال بارگذاری اطلاعات محصول...</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (productError) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[400px]">
|
||||||
|
<div className="text-red-500">خطا در بارگذاری اطلاعات محصول</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleStep1Submit = (data: CreateProductDetailRequestType) => {
|
||||||
|
const fullData = {
|
||||||
|
...data,
|
||||||
|
productId: productIdNum
|
||||||
|
};
|
||||||
|
|
||||||
|
updateProductDetailMutation.mutate(fullData, {
|
||||||
|
onSuccess: () => {
|
||||||
|
setProductData(prev => ({ ...prev, ...data }));
|
||||||
|
setCurrentStep(2);
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(extractErrorMessage(error));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleStep2Submit = (data: Omit<CreateProductAttributeRequestType, 'productId'>) => {
|
||||||
|
const fullData = {
|
||||||
|
...data,
|
||||||
|
productId: productIdNum
|
||||||
|
};
|
||||||
|
|
||||||
|
updateProductAttributeMutation.mutate(fullData, {
|
||||||
|
onSuccess: () => {
|
||||||
|
setProductData(prev => ({ ...prev, ...data }));
|
||||||
|
setCurrentStep(3);
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(extractErrorMessage(error));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleStep3Submit = (data: Omit<SaveProductRequestType, 'productId'>) => {
|
||||||
|
const fullData = {
|
||||||
|
...data,
|
||||||
|
productId: productIdNum
|
||||||
|
};
|
||||||
|
|
||||||
|
updateProductMutation.mutate(fullData, {
|
||||||
|
onSuccess: () => {
|
||||||
|
toast.success('محصول با موفقیت بروزرسانی شد');
|
||||||
|
navigate(Pages.products.list);
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(extractErrorMessage(error));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePreviousStep = () => {
|
||||||
|
if (currentStep > 1) {
|
||||||
|
setCurrentStep((prev) => (prev - 1) as 1 | 2 | 3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderStep1 = () => {
|
||||||
|
const categories = categoriesData?.results?.data || [];
|
||||||
|
const brands = brandsData?.results?.brands || [];
|
||||||
|
|
||||||
|
if (categoriesLoading) {
|
||||||
|
return <div>در حال بارگذاری دستهبندیها...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Step1Form
|
||||||
|
onSubmit={handleStep1Submit}
|
||||||
|
brands={brands}
|
||||||
|
categories={categories}
|
||||||
|
loading={updateProductDetailMutation.isPending}
|
||||||
|
initialData={{
|
||||||
|
category: productData.category,
|
||||||
|
brand: productData.brand,
|
||||||
|
model: productData.model,
|
||||||
|
title_fa: productData.title_fa,
|
||||||
|
title_en: productData.title_en,
|
||||||
|
seoTitle: productData.seoTitle,
|
||||||
|
source: productData.source,
|
||||||
|
isFake: productData.isFake,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderStep2 = () => (
|
||||||
|
<Step2Form
|
||||||
|
onSubmit={handleStep2Submit}
|
||||||
|
loading={updateProductAttributeMutation.isPending}
|
||||||
|
onPrevious={handlePreviousStep}
|
||||||
|
categoryId={productData.category}
|
||||||
|
initialData={{
|
||||||
|
attributes: productData.attributes,
|
||||||
|
description: productData.description,
|
||||||
|
metaDescription: productData.metaDescription,
|
||||||
|
tags: productData.tags,
|
||||||
|
advantages: productData.advantages,
|
||||||
|
disAdvantages: productData.disAdvantages,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderStep3 = () => (
|
||||||
|
<Step3Form
|
||||||
|
onSubmit={handleStep3Submit}
|
||||||
|
loading={updateProductMutation.isPending}
|
||||||
|
onPrevious={handlePreviousStep}
|
||||||
|
initialData={{
|
||||||
|
imagesList: productData.imagesList,
|
||||||
|
coverImage: productData.coverImage,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="mb-8">
|
||||||
|
<h1 className="text-2xl font-bold text-gray-900 mb-2">بروزرسانی محصول</h1>
|
||||||
|
<div className="flex items-center justify-center space-x-8">
|
||||||
|
<StepIndicator step={1} currentStep={currentStep} title="جزئیات محصول" />
|
||||||
|
<StepIndicator step={2} currentStep={currentStep} title="ویژگیها و توضیحات" />
|
||||||
|
<StepIndicator step={3} currentStep={currentStep} title="تصاویر و ذخیره" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex-1 text-sm bg-white py-8 xl:px-10 px-6 rounded-3xl'>
|
||||||
|
{currentStep === 1 && renderStep1()}
|
||||||
|
{currentStep === 2 && renderStep2()}
|
||||||
|
{currentStep === 3 && renderStep3()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UpdateProduct;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { type FC, useState, useMemo } from 'react';
|
import { type FC, useState, useMemo, useEffect } from 'react';
|
||||||
import Button from '../../../components/Button';
|
import Button from '../../../components/Button';
|
||||||
import Input from '../../../components/Input';
|
import Input from '../../../components/Input';
|
||||||
import Select from '../../../components/Select';
|
import Select from '../../../components/Select';
|
||||||
@@ -12,6 +12,7 @@ interface Step1FormProps {
|
|||||||
brands: { _id: string; title_fa: string }[];
|
brands: { _id: string; title_fa: string }[];
|
||||||
categories: CategoryTreeNode[];
|
categories: CategoryTreeNode[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
|
initialData?: Partial<CreateProductDetailRequestType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// تابع برای پیدا کردن همه دستهبندیهای leaf از تمام سطحها
|
// تابع برای پیدا کردن همه دستهبندیهای leaf از تمام سطحها
|
||||||
@@ -35,7 +36,7 @@ const findAllLeafCategories = (categories: CategoryTreeNode[]): CategoryTreeNode
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const Step1Form: FC<Step1FormProps> = ({ onSubmit, brands, categories, loading }) => {
|
const Step1Form: FC<Step1FormProps> = ({ onSubmit, brands, categories, loading, initialData }) => {
|
||||||
const [formData, setFormData] = useState<CreateProductDetailRequestType>({
|
const [formData, setFormData] = useState<CreateProductDetailRequestType>({
|
||||||
category: '',
|
category: '',
|
||||||
brand: '',
|
brand: '',
|
||||||
@@ -47,6 +48,12 @@ const Step1Form: FC<Step1FormProps> = ({ onSubmit, brands, categories, loading }
|
|||||||
isFake: false
|
isFake: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (initialData) {
|
||||||
|
setFormData(prev => ({ ...prev, ...initialData }));
|
||||||
|
}
|
||||||
|
}, [initialData]);
|
||||||
|
|
||||||
// پیدا کردن همه دستهبندیهای leaf
|
// پیدا کردن همه دستهبندیهای leaf
|
||||||
const leafCategories = useMemo(() => {
|
const leafCategories = useMemo(() => {
|
||||||
if (!categories || categories.length === 0) {
|
if (!categories || categories.length === 0) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { type FC, useState } from 'react';
|
import { type FC, useState, useEffect } from 'react';
|
||||||
import Button from '../../../components/Button';
|
import Button from '../../../components/Button';
|
||||||
import Input from '../../../components/Input';
|
import Input from '../../../components/Input';
|
||||||
import Textarea from '../../../components/Textarea';
|
import Textarea from '../../../components/Textarea';
|
||||||
@@ -66,6 +66,7 @@ interface Step2FormProps {
|
|||||||
loading: boolean;
|
loading: boolean;
|
||||||
onPrevious: () => void;
|
onPrevious: () => void;
|
||||||
categoryId?: string;
|
categoryId?: string;
|
||||||
|
initialData?: Partial<Omit<CreateProductAttributeRequestType, 'productId'>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// کامپوننت مدیریت تگها
|
// کامپوننت مدیریت تگها
|
||||||
@@ -197,7 +198,7 @@ const ListInput: FC<ListInputProps> = ({ items, onChange, placeholder, label })
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Step2Form: FC<Step2FormProps> = ({ onSubmit, loading, onPrevious, categoryId }) => {
|
const Step2Form: FC<Step2FormProps> = ({ onSubmit, loading, onPrevious, categoryId, initialData }) => {
|
||||||
const [formData, setFormData] = useState<Omit<CreateProductAttributeRequestType, 'productId'>>({
|
const [formData, setFormData] = useState<Omit<CreateProductAttributeRequestType, 'productId'>>({
|
||||||
attributes: [],
|
attributes: [],
|
||||||
description: '',
|
description: '',
|
||||||
@@ -207,6 +208,12 @@ const Step2Form: FC<Step2FormProps> = ({ onSubmit, loading, onPrevious, category
|
|||||||
disAdvantages: []
|
disAdvantages: []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (initialData) {
|
||||||
|
setFormData(prev => ({ ...prev, ...initialData }));
|
||||||
|
}
|
||||||
|
}, [initialData]);
|
||||||
|
|
||||||
const { data: categoryAttributesData } = useGetCategoryAttributes(categoryId || '');
|
const { data: categoryAttributesData } = useGetCategoryAttributes(categoryId || '');
|
||||||
|
|
||||||
const handleAttributeChange = (attributeId: number, values: number[]) => {
|
const handleAttributeChange = (attributeId: number, values: number[]) => {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { type FC, useState } from 'react';
|
import { type FC, useState, useEffect } from 'react';
|
||||||
import Button from '../../../components/Button';
|
import Button from '../../../components/Button';
|
||||||
import UploadBoxDraggble from '../../../components/UploadBoxDraggble';
|
import UploadBoxDraggble from '../../../components/UploadBoxDraggble';
|
||||||
import UploadBox from '../../../components/UploadBox';
|
import UploadBox from '../../../components/UploadBox';
|
||||||
@@ -9,15 +9,23 @@ interface Step3FormProps {
|
|||||||
onSubmit: (data: Omit<SaveProductRequestType, 'productId'>) => void;
|
onSubmit: (data: Omit<SaveProductRequestType, 'productId'>) => void;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
onPrevious: () => void;
|
onPrevious: () => void;
|
||||||
|
initialData?: Partial<Omit<SaveProductRequestType, 'productId'>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Step3Form: FC<Step3FormProps> = ({ onSubmit, loading, onPrevious }) => {
|
const Step3Form: FC<Step3FormProps> = ({ onSubmit, loading, onPrevious, initialData }) => {
|
||||||
|
|
||||||
const [uploadedImages, setUploadedImages] = useState<string[]>([]);
|
const [uploadedImages, setUploadedImages] = useState<string[]>([]);
|
||||||
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
|
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
|
||||||
const [coverImage, setCoverImage] = useState<string>('');
|
const [coverImage, setCoverImage] = useState<string>('');
|
||||||
const [selectedCoverFile, setSelectedCoverFile] = useState<File | null>(null);
|
const [selectedCoverFile, setSelectedCoverFile] = useState<File | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (initialData) {
|
||||||
|
setUploadedImages(initialData.imagesList || []);
|
||||||
|
setCoverImage(initialData.coverImage || '');
|
||||||
|
}
|
||||||
|
}, [initialData]);
|
||||||
|
|
||||||
const uploadMultipleMutation = useUploadMultiple();
|
const uploadMultipleMutation = useUploadMultiple();
|
||||||
|
|
||||||
const handleFileSelect = (files: File[]) => {
|
const handleFileSelect = (files: File[]) => {
|
||||||
@@ -149,7 +157,7 @@ const Step3Form: FC<Step3FormProps> = ({ onSubmit, loading, onPrevious }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-between">
|
<div className="flex gap-4 justify-between">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
@@ -162,7 +170,7 @@ const Step3Form: FC<Step3FormProps> = ({ onSubmit, loading, onPrevious }) => {
|
|||||||
isLoading={loading || uploadMultipleMutation.isPending}
|
isLoading={loading || uploadMultipleMutation.isPending}
|
||||||
disabled={selectedFiles.length === 0 && uploadedImages.length === 0 && !selectedCoverFile && !coverImage}
|
disabled={selectedFiles.length === 0 && uploadedImages.length === 0 && !selectedCoverFile && !coverImage}
|
||||||
>
|
>
|
||||||
ایجاد محصول
|
بروزرسانی محصول
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import {
|
|||||||
type CreateProductDetailRequestType,
|
type CreateProductDetailRequestType,
|
||||||
type CreateProductAttributeRequestType,
|
type CreateProductAttributeRequestType,
|
||||||
type SaveProductRequestType,
|
type SaveProductRequestType,
|
||||||
type UpdateVariantRequestType
|
type UpdateVariantRequestType,
|
||||||
|
type UpdateProductDetailRequestType,
|
||||||
|
type UpdateProductAttributeRequestType,
|
||||||
|
type UpdateProductRequestType
|
||||||
} from "../types/Types";
|
} from "../types/Types";
|
||||||
|
|
||||||
export const useCreateProductDetail = () => {
|
export const useCreateProductDetail = () => {
|
||||||
@@ -66,4 +69,22 @@ export const useGetVariantById = (productId: string, variantId: string) => {
|
|||||||
queryFn: () => api.getVariantById(productId, variantId),
|
queryFn: () => api.getVariantById(productId, variantId),
|
||||||
enabled: !!productId && !!variantId,
|
enabled: !!productId && !!variantId,
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUpdateProductDetail = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (variables: UpdateProductDetailRequestType) => api.updateProductDetail(variables),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUpdateProductAttribute = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (variables: UpdateProductAttributeRequestType) => api.updateProductAttribute(variables),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUpdateProduct = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (variables: UpdateProductRequestType) => api.updateProduct(variables),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
@@ -12,6 +12,12 @@ import {
|
|||||||
type GetProductByIdResponseType,
|
type GetProductByIdResponseType,
|
||||||
type UpdateVariantRequestType,
|
type UpdateVariantRequestType,
|
||||||
type GetVariantByIdResponseType,
|
type GetVariantByIdResponseType,
|
||||||
|
type UpdateProductDetailRequestType,
|
||||||
|
type UpdateProductDetailResponseType,
|
||||||
|
type UpdateProductAttributeRequestType,
|
||||||
|
type UpdateProductAttributeResponseType,
|
||||||
|
type UpdateProductRequestType,
|
||||||
|
type UpdateProductResponseType,
|
||||||
} from "../types/Types";
|
} from "../types/Types";
|
||||||
|
|
||||||
export const createProductDetail = async (params: CreateProductDetailRequestType): Promise<CreateProductDetailResponseType> => {
|
export const createProductDetail = async (params: CreateProductDetailRequestType): Promise<CreateProductDetailResponseType> => {
|
||||||
@@ -59,4 +65,19 @@ export const updateVariant = async (params: UpdateVariantRequestType) => {
|
|||||||
export const getVariantById = async (productId: string, variantId: string): Promise<GetVariantByIdResponseType> => {
|
export const getVariantById = async (productId: string, variantId: string): Promise<GetVariantByIdResponseType> => {
|
||||||
const { data } = await axios.get(`/admin/products/${productId}/variants/${variantId}`);
|
const { data } = await axios.get(`/admin/products/${productId}/variants/${variantId}`);
|
||||||
return data;
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateProductDetail = async (params: UpdateProductDetailRequestType): Promise<UpdateProductDetailResponseType> => {
|
||||||
|
const { data } = await axios.patch(`/admin/products/update/detail`, params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateProductAttribute = async (params: UpdateProductAttributeRequestType): Promise<UpdateProductAttributeResponseType> => {
|
||||||
|
const { data } = await axios.patch(`/admin/products/update/attribute`, params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateProduct = async (params: UpdateProductRequestType): Promise<UpdateProductResponseType> => {
|
||||||
|
const { data } = await axios.patch(`/admin/products/update/save`, params);
|
||||||
|
return data;
|
||||||
};
|
};
|
||||||
@@ -372,3 +372,48 @@ export type UpdateVariantRequestType = {
|
|||||||
specialSale_quantity: number;
|
specialSale_quantity: number;
|
||||||
specialSale_endDate: string;
|
specialSale_endDate: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// تایپهای مربوط به آپدیت محصول سه مرحلهای
|
||||||
|
|
||||||
|
// مرحله اول: آپدیت جزئیات محصول
|
||||||
|
export type UpdateProductDetailRequestType = {
|
||||||
|
productId: number;
|
||||||
|
} & Omit<CreateProductDetailRequestType, "category" | "brand"> & {
|
||||||
|
category?: string;
|
||||||
|
brand?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UpdateProductDetailResponseType = {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
message: string;
|
||||||
|
product: DraftProductType;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// مرحله دوم: آپدیت ویژگیها و توضیحات
|
||||||
|
export type UpdateProductAttributeRequestType = {
|
||||||
|
productId: number;
|
||||||
|
} & CreateProductAttributeRequestType;
|
||||||
|
|
||||||
|
export type UpdateProductAttributeResponseType = {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
success: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// مرحله سوم: آپدیت تصاویر و ذخیره نهایی
|
||||||
|
export type UpdateProductRequestType = {
|
||||||
|
productId: number;
|
||||||
|
} & SaveProductRequestType;
|
||||||
|
|
||||||
|
export type UpdateProductResponseType = {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
success: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import Variant from '../pages/category/Variant'
|
|||||||
import Attributes from '../pages/category/Attributes'
|
import Attributes from '../pages/category/Attributes'
|
||||||
import CreateProduct from '../pages/products/Create'
|
import CreateProduct from '../pages/products/Create'
|
||||||
import ListProduct from '../pages/products/List'
|
import ListProduct from '../pages/products/List'
|
||||||
|
import UpdateProduct from '../pages/products/Update'
|
||||||
import ProductVariant from '@/pages/products/ProductVariant'
|
import ProductVariant from '@/pages/products/ProductVariant'
|
||||||
|
|
||||||
const MainRouter: FC = () => {
|
const MainRouter: FC = () => {
|
||||||
@@ -39,6 +40,7 @@ const MainRouter: FC = () => {
|
|||||||
<Route path={`${Pages.category.attributes}:id`} element={<Attributes />} />
|
<Route path={`${Pages.category.attributes}:id`} element={<Attributes />} />
|
||||||
<Route path={Pages.products.create} element={<CreateProduct />} />
|
<Route path={Pages.products.create} element={<CreateProduct />} />
|
||||||
<Route path={Pages.products.list} element={<ListProduct />} />
|
<Route path={Pages.products.list} element={<ListProduct />} />
|
||||||
|
<Route path={`${Pages.products.update}:id`} element={<UpdateProduct />} />
|
||||||
<Route path={`${Pages.products.variants}:id`} element={<ProductVariant />} />
|
<Route path={`${Pages.products.variants}:id`} element={<ProductVariant />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user