feat(commerce): replace mock purchases with real API calls
CLN-02: getPurchases() now calls GET /marketplace/orders; requestRefund() calls POST /marketplace/orders/:id/refund. Removed MOCK_PURCHASES constant. MSW handler updated.
This commit is contained in:
parent
834fa1f979
commit
8e9431fe93
2 changed files with 95 additions and 46 deletions
|
|
@ -273,6 +273,7 @@ export const handlersMarketplace = [
|
|||
);
|
||||
}),
|
||||
|
||||
// GET /marketplace/orders — user's orders (commerceService.getPurchases)
|
||||
http.get('*/api/v1/marketplace/orders', () => {
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
|
|
@ -280,16 +281,33 @@ export const handlersMarketplace = [
|
|||
{
|
||||
id: 'order-1',
|
||||
status: 'completed',
|
||||
total_amount: 29.99,
|
||||
total: 29.99,
|
||||
created_at: '2024-01-01T00:00:00Z',
|
||||
items: [
|
||||
{
|
||||
id: 'item-1',
|
||||
product_id: 'prod-1',
|
||||
title: 'Cyberpunk Drum Kit',
|
||||
price: 29.99,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'order-2',
|
||||
status: 'completed',
|
||||
total_amount: 49.99,
|
||||
total: 49.99,
|
||||
created_at: '2024-01-15T00:00:00Z',
|
||||
items: [
|
||||
{
|
||||
id: 'item-2',
|
||||
product_id: 'prod-2',
|
||||
title: 'Ethereal Pads Vol. 1',
|
||||
price: 49.99,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,22 @@
|
|||
import { apiClient } from './api/client';
|
||||
import { apiClient } from '@/services/api/client';
|
||||
import { Purchase, Product } from '../types';
|
||||
|
||||
interface OrderItemApi {
|
||||
id?: string;
|
||||
product_id: string;
|
||||
price: number;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
interface OrderApi {
|
||||
id: string;
|
||||
status: string;
|
||||
total_amount?: number;
|
||||
total?: number;
|
||||
created_at: string;
|
||||
items?: OrderItemApi[];
|
||||
}
|
||||
|
||||
interface SellerSale {
|
||||
order_id: string;
|
||||
product_id: string;
|
||||
|
|
@ -36,51 +52,63 @@ function formatRelativeDate(dateStr: string): string {
|
|||
return d.toLocaleDateString();
|
||||
}
|
||||
|
||||
const MOCK_PURCHASES: Purchase[] = [
|
||||
{
|
||||
id: 'p1',
|
||||
orderId: 'ORD-9921',
|
||||
date: '2023-10-24',
|
||||
price: 29.99,
|
||||
status: 'completed',
|
||||
downloadUrl: '#',
|
||||
license: { id: 'l1', name: 'Standard', price: 29.99, features: [] },
|
||||
product: {
|
||||
id: 'prod1',
|
||||
title: 'Cyberpunk 2077 Drums',
|
||||
type: 'pack',
|
||||
price: 29.99,
|
||||
currency: 'USD',
|
||||
rating: 5,
|
||||
coverUrl: 'https://picsum.photos/id/120/100/100',
|
||||
author: 'Neon Audio',
|
||||
} as Partial<Product> as Product,
|
||||
},
|
||||
{
|
||||
id: 'p2',
|
||||
orderId: 'ORD-9850',
|
||||
date: '2023-10-15',
|
||||
price: 49.99,
|
||||
status: 'completed',
|
||||
downloadUrl: '#',
|
||||
license: { id: 'l2', name: 'Premium', price: 49.99, features: [] },
|
||||
product: {
|
||||
id: 'prod2',
|
||||
title: 'Ethereal Pads Vol. 1',
|
||||
type: 'pack',
|
||||
price: 49.99,
|
||||
currency: 'USD',
|
||||
rating: 4,
|
||||
coverUrl: 'https://picsum.photos/id/140/100/100',
|
||||
author: 'Soundscapes',
|
||||
} as Partial<Product> as Product,
|
||||
},
|
||||
];
|
||||
function mapOrderToPurchases(order: OrderApi): Purchase[] {
|
||||
const orderId = typeof order.id === 'string' ? order.id : String(order.id);
|
||||
const dateStr = order.created_at
|
||||
? new Date(order.created_at).toISOString().slice(0, 10)
|
||||
: '';
|
||||
const items = order.items ?? [];
|
||||
if (items.length === 0) {
|
||||
const total = order.total_amount ?? order.total ?? 0;
|
||||
return [
|
||||
{
|
||||
id: orderId,
|
||||
orderId,
|
||||
date: dateStr,
|
||||
price: total,
|
||||
status: order.status,
|
||||
downloadUrl: '#',
|
||||
license: { id: 'lic-default', name: 'Standard', price: total, features: [] },
|
||||
product: {
|
||||
id: 'unknown',
|
||||
title: 'Order',
|
||||
type: 'pack',
|
||||
price: total,
|
||||
currency: 'USD',
|
||||
coverUrl: '',
|
||||
} as Partial<Product> as Product,
|
||||
},
|
||||
];
|
||||
}
|
||||
return items.map((item, idx) => {
|
||||
const productId = item.product_id ?? 'unknown';
|
||||
const price = item.price ?? 0;
|
||||
const title = item.title ?? productId;
|
||||
return {
|
||||
id: `${orderId}-${item.id ?? idx}`,
|
||||
orderId,
|
||||
date: dateStr,
|
||||
price,
|
||||
status: order.status,
|
||||
downloadUrl: '#',
|
||||
license: { id: `lic-${productId}`, name: 'Standard', price, features: [] },
|
||||
product: {
|
||||
id: productId,
|
||||
title,
|
||||
type: 'pack',
|
||||
price,
|
||||
currency: 'USD',
|
||||
coverUrl: '',
|
||||
} as Partial<Product> as Product,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export const commerceService = {
|
||||
getPurchases: async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 600));
|
||||
return MOCK_PURCHASES;
|
||||
getPurchases: async (): Promise<Purchase[]> => {
|
||||
const response = await apiClient.get<OrderApi[]>('/marketplace/orders');
|
||||
const orders = Array.isArray(response.data) ? response.data : [];
|
||||
return orders.flatMap(mapOrderToPurchases);
|
||||
},
|
||||
|
||||
// v0.401 M3: Real API call to GET /sell/sales
|
||||
|
|
@ -128,8 +156,11 @@ export const commerceService = {
|
|||
return (data as { top_products?: TopProductStats[] })?.top_products ?? [];
|
||||
},
|
||||
|
||||
requestRefund: async (_orderId: string, _reason: string) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 800));
|
||||
requestRefund: async (orderId: string, reason: string) => {
|
||||
await apiClient.post(`/marketplace/orders/${orderId}/refund`, {
|
||||
reason: reason || 'Requested by customer',
|
||||
details: '',
|
||||
});
|
||||
return { success: true };
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue