Files
project_it207_client/hooks/useProducts.ts
2025-11-12 16:03:57 +07:00

113 lines
2.9 KiB
TypeScript

import { useState, useEffect, useCallback } from 'react';
import productService, { ProductResponse, ProductListResponse } from '../services/product';
interface UseProductsOptions {
page?: number;
size?: number;
sortBy?: string;
sortDir?: 'asc' | 'desc';
categoryId?: number;
keyword?: string;
availableOnly?: boolean;
}
export const useProducts = (options: UseProductsOptions = {}) => {
const [data, setData] = useState<ProductListResponse | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [refreshing, setRefreshing] = useState(false);
const {
page = 0,
size = 10,
sortBy = 'productId',
sortDir = 'asc',
categoryId,
keyword,
availableOnly = false,
} = options;
const fetchProducts = useCallback(async () => {
try {
setLoading(true);
setError(null);
let result: ProductListResponse;
if (keyword) {
result = await productService.searchProducts(keyword, page, size, sortBy, sortDir);
} else if (categoryId) {
result = await productService.getProductsByCategory(categoryId, page, size, sortBy, sortDir);
} else if (availableOnly) {
result = await productService.getAvailableProducts(page, size, sortBy, sortDir);
} else {
result = await productService.getAllProducts(page, size, sortBy, sortDir);
}
setData(result);
} catch (err) {
setError(err instanceof Error ? err.message : 'An error occurred');
} finally {
setLoading(false);
}
}, [page, size, sortBy, sortDir, categoryId, keyword, availableOnly]);
const refresh = useCallback(async () => {
setRefreshing(true);
await fetchProducts();
setRefreshing(false);
}, [fetchProducts]);
useEffect(() => {
fetchProducts();
}, [fetchProducts]);
return {
products: data?.products || [],
currentPage: data?.currentPage || 0,
totalItems: data?.totalItems || 0,
totalPages: data?.totalPages || 0,
hasNext: data?.hasNext || false,
hasPrevious: data?.hasPrevious || false,
loading,
error,
refreshing,
refresh,
refetch: fetchProducts,
};
};
export const useProduct = (productId: number | null) => {
const [data, setData] = useState<ProductResponse | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchProduct = useCallback(async () => {
if (!productId) {
setLoading(false);
return;
}
try {
setLoading(true);
setError(null);
const result = await productService.getProductById(productId);
setData(result);
} catch (err) {
setError(err instanceof Error ? err.message : 'An error occurred');
} finally {
setLoading(false);
}
}, [productId]);
useEffect(() => {
fetchProduct();
}, [fetchProduct]);
return {
product: data,
loading,
error,
refetch: fetchProduct,
};
};