veza/apps/web/src/services/marketplaceService.ts
senke 0dd54d1476 [FE-PAGE-006] fe-page: Complete Marketplace page implementation
- 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
2025-12-24 12:54:20 +01:00

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;
},
};