- Added product browsing with pagination (page, limit, total_pages) - Added product filtering: search, product type, price range - Added cart functionality: add, remove, update quantity, checkout - Created cartStore with Zustand and persistence - Added Cart component with checkout functionality - Enhanced ProductCard with Add to Cart button - Added filter UI with collapsible filters panel - Added search bar for product search - Added pagination controls (Previous/Next) - Updated marketplaceService to support filters and pagination
134 lines
4.1 KiB
TypeScript
134 lines
4.1 KiB
TypeScript
import { apiClient } from './api/client';
|
|
import {
|
|
Product,
|
|
Order,
|
|
CreateProductRequest,
|
|
CreateOrderRequest,
|
|
ProductStatus,
|
|
} from '../types/marketplace';
|
|
|
|
/**
|
|
* Marketplace Service
|
|
* Implémente les endpoints marketplace selon le backend
|
|
* Endpoints:
|
|
* - GET /marketplace/products (public, avec query params: status, seller_id)
|
|
* - POST /marketplace/products (protected, nécessite content creator role)
|
|
* - POST /marketplace/orders (protected)
|
|
* - GET /marketplace/download/:product_id (protected)
|
|
*/
|
|
export const marketplaceService = {
|
|
/**
|
|
* Liste les produits de la marketplace
|
|
* @param filters Filtres optionnels (status, seller_id, product_type, min_price, max_price, search)
|
|
* @param pagination Pagination (page, limit)
|
|
* @returns Liste des produits avec pagination
|
|
*/
|
|
fetchProducts: async (
|
|
filters?: {
|
|
status?: ProductStatus;
|
|
seller_id?: string;
|
|
product_type?: string;
|
|
min_price?: number;
|
|
max_price?: number;
|
|
search?: string;
|
|
},
|
|
pagination?: {
|
|
page?: number;
|
|
limit?: number;
|
|
},
|
|
): Promise<{ products: Product[]; total: number; page: number; limit: number; total_pages: number }> => {
|
|
const params = new URLSearchParams();
|
|
if (filters?.status) {
|
|
params.append('status', filters.status);
|
|
}
|
|
if (filters?.seller_id) {
|
|
params.append('seller_id', filters.seller_id);
|
|
}
|
|
if (filters?.product_type) {
|
|
params.append('product_type', filters.product_type);
|
|
}
|
|
if (filters?.min_price !== undefined) {
|
|
params.append('min_price', filters.min_price.toString());
|
|
}
|
|
if (filters?.max_price !== undefined) {
|
|
params.append('max_price', filters.max_price.toString());
|
|
}
|
|
if (filters?.search) {
|
|
params.append('search', filters.search);
|
|
}
|
|
if (pagination?.page) {
|
|
params.append('page', pagination.page.toString());
|
|
}
|
|
if (pagination?.limit) {
|
|
params.append('limit', pagination.limit.toString());
|
|
}
|
|
const queryString = params.toString();
|
|
const url = `/marketplace/products${queryString ? `?${queryString}` : ''}`;
|
|
const response = await apiClient.get<{
|
|
products: Product[];
|
|
total: number;
|
|
page: number;
|
|
limit: number;
|
|
total_pages: number;
|
|
}>(url);
|
|
// Handle both old format (array) and new format (object with pagination)
|
|
if (Array.isArray(response.data)) {
|
|
return {
|
|
products: response.data,
|
|
total: response.data.length,
|
|
page: 1,
|
|
limit: response.data.length,
|
|
total_pages: 1,
|
|
};
|
|
}
|
|
return response.data;
|
|
},
|
|
|
|
/**
|
|
* Crée un nouveau produit
|
|
* Nécessite l'authentification et le rôle content creator
|
|
* @param data Données du produit à créer
|
|
* @returns Le produit créé
|
|
*/
|
|
createProduct: async (data: CreateProductRequest): Promise<Product> => {
|
|
const response = await apiClient.post<Product>(
|
|
'/marketplace/products',
|
|
data,
|
|
);
|
|
return response.data;
|
|
},
|
|
|
|
/**
|
|
* Crée une commande (achat de produits)
|
|
* Nécessite l'authentification
|
|
* @param items Liste des produits à acheter (peut contenir plusieurs produits)
|
|
* @returns La commande créée
|
|
*/
|
|
createOrder: async (items: { product_id: string }[]): Promise<Order> => {
|
|
const data: CreateOrderRequest = { items };
|
|
const response = await apiClient.post<Order>('/marketplace/orders', data);
|
|
return response.data;
|
|
},
|
|
|
|
/**
|
|
* Achète un seul produit (helper pour créer une commande avec un seul item)
|
|
* @param productId ID du produit à acheter
|
|
* @returns La commande créée
|
|
*/
|
|
purchaseProduct: async (productId: string): Promise<Order> => {
|
|
return marketplaceService.createOrder([{ product_id: productId }]);
|
|
},
|
|
|
|
/**
|
|
* Récupère l'URL de téléchargement pour un produit acheté
|
|
* Nécessite l'authentification et une licence valide pour le produit
|
|
* @param productId ID du produit
|
|
* @returns URL de téléchargement sécurisée
|
|
*/
|
|
getDownloadLink: async (productId: string): Promise<string> => {
|
|
const response = await apiClient.get<{ url: string }>(
|
|
`/marketplace/download/${productId}`,
|
|
);
|
|
return response.data.url;
|
|
},
|
|
};
|