"implement product CRUD API endpoints and frontend integration"

This commit is contained in:
louiscklaw
2025-06-15 02:47:25 +08:00
parent 48e90bca1b
commit f53cf9d932
30 changed files with 623 additions and 342 deletions

View File

@@ -1,9 +1,11 @@
//
// src/actions/product.ts
//
import { useMemo } from 'react';
import axiosInstance, { endpoints, fetcher } from 'src/lib/axios';
import type { IProductItem } from 'src/types/product';
import type { SWRConfiguration } from 'swr';
import useSWR from 'swr';
import useSWR, { mutate } from 'swr';
// ----------------------------------------------------------------------
@@ -22,11 +24,7 @@ type ProductsData = {
export function useGetProducts() {
const url = endpoints.product.list;
const { data, isLoading, error, isValidating, mutate } = useSWR<ProductsData>(
url,
fetcher,
swrOptions
);
const { data, isLoading, error, isValidating } = useSWR<ProductsData>(url, fetcher, swrOptions);
const memoizedValue = useMemo(
() => ({
@@ -35,9 +33,8 @@ export function useGetProducts() {
productsError: error,
productsValidating: isValidating,
productsEmpty: !isLoading && !isValidating && !data?.products.length,
mutate,
}),
[data?.products, error, isLoading, isValidating, mutate]
[data?.products, error, isLoading, isValidating]
);
return memoizedValue;
@@ -56,10 +53,11 @@ export function useGetProduct(productId: string) {
const memoizedValue = useMemo(
() => ({
currentProduct: data?.product,
product: data?.product,
productLoading: isLoading,
productError: error,
productValidating: isValidating,
mutate,
}),
[data?.product, error, isLoading, isValidating]
);
@@ -97,140 +95,80 @@ export function useSearchProducts(query: string) {
// ----------------------------------------------------------------------
type SaveProductData = {
// id: string;
export async function createProduct(productData: IProductItem) {
/**
* Work on server
*/
const data = { productData };
await axiosInstance.post(endpoints.product.create, data);
sku: string;
name: string;
code: string;
price: number | null;
taxes: number | null;
tags: string[];
sizes: string[];
// publish: string;
gender: string[];
// coverUrl: string;
images: (string | File)[];
colors: string[];
quantity: number | null;
category: string;
// available: number;
// totalSold: number;
description: string;
// totalRatings: number;
// totalReviews: number;
// inventoryType: string;
subDescription: string;
priceSale: number | null;
newLabel: {
content: string;
enabled: boolean;
};
saleLabel: {
content: string;
enabled: boolean;
};
// ratings: {
// name: string;
// starCount: number;
// reviewCount: number;
// }[];
};
/**
* Work in local
*/
mutate(
endpoints.product.list,
(currentData: any) => {
const currentProducts: IProductItem[] = currentData?.products;
export async function saveProduct(productId: string, saveProductData: SaveProductData) {
console.log('save product ?');
// const url = productId ? [endpoints.product.details, { params: { productId } }] : '';
const products = [...currentProducts, productData];
const res = await axiosInstance.post('http://localhost:7272/api/product/saveProduct', {
data: saveProductData,
});
return res;
}
export async function uploadProductImage(saveProductData: SaveProductData) {
console.log('save product ?');
// const url = productId ? [endpoints.product.details, { params: { productId } }] : '';
const res = await axiosInstance.get('http://localhost:7272/api/product/helloworld');
return res;
return { ...currentData, products };
},
false
);
}
// ----------------------------------------------------------------------
type CreateProductData = {
// id: string;
sku: string;
name: string;
code: string;
price: number | null;
taxes: number | null;
tags: string[];
sizes: string[];
publish: string;
gender: string[];
coverUrl: string;
images: (string | File)[];
colors: string[];
quantity: number | null;
category: string;
available: number;
totalSold: number;
description: string;
totalRatings: number;
totalReviews: number;
inventoryType: string;
subDescription: string;
priceSale: number | null;
newLabel: {
content: string;
enabled: boolean;
};
saleLabel: {
content: string;
enabled: boolean;
};
// ratings: {
// name: string;
// starCount: number;
// reviewCount: number;
// }[];
};
export async function updateProduct(productData: Partial<IProductItem>) {
/**
* Work on server
*/
const data = { productData };
await axiosInstance.put(endpoints.product.update, data);
export async function createProduct(createProductData: CreateProductData) {
console.log('create product ?');
// const url = productId ? [endpoints.product.details, { params: { productId } }] : '';
/**
* Work in local
*/
const res = await axiosInstance.post('http://localhost:7272/api/product/createProduct', {
data: createProductData,
});
mutate(
endpoints.product.list,
(currentData: any) => {
const currentProducts: IProductItem[] = currentData?.products;
return res;
const products = currentProducts.map((product) =>
product.id === productData.id ? { ...product, ...productData } : product
);
return { ...currentData, products };
},
false
);
}
// ----------------------------------------------------------------------
type DeleteProductResponse = {
success: boolean;
message?: string;
};
export async function deleteProduct(productId: string) {
/**
* Work on server
*/
const data = { productId };
await axiosInstance.patch(endpoints.product.delete, data);
export async function deleteProduct(productId: string): Promise<DeleteProductResponse> {
const url = `http://localhost:7272/api/product/deleteProduct?productId=${productId}`;
/**
* Work in local
*/
try {
const res = await axiosInstance.delete(url);
console.log({ res });
mutate(
endpoints.product.list,
(currentData: any) => {
console.log({ currentData });
const currentProducts: IProductItem[] = currentData?.products;
return {
success: true,
message: 'Product deleted successfully',
};
} catch (error) {
return {
success: false,
message: error instanceof Error ? error.message : 'Failed to delete product',
};
}
const products = currentProducts.filter((product) => product.id !== productId);
return { ...currentData, products };
},
false
);
}