// Reseñas de productos + pedidos del cliente (Store API de Medusa, modulo // propio commerce-backend/src/modules/product-review). Server-side y sin // cache: las reseñas cambian al aprobarse en el admin y los pedidos son // estado de sesion. function backendUrl(): string { const value = process.env.MEDUSA_BACKEND_URL; if (!value) throw new Error("MEDUSA_BACKEND_URL no está configurado."); return value.replace(/\/$/, ""); } async function medusaFetch(path: string, init?: { method?: string; body?: unknown; token?: string }): Promise { const publishableKey = process.env.MEDUSA_PUBLISHABLE_KEY; const response = await fetch(`${backendUrl()}${path}`, { method: init?.method ?? "GET", headers: { "Content-Type": "application/json", ...(publishableKey ? { "x-publishable-api-key": publishableKey } : {}), ...(init?.token ? { Authorization: `Bearer ${init.token}` } : {}), }, body: init?.body ? JSON.stringify(init.body) : undefined, cache: "no-store", }); const data = await response.json().catch(() => ({})); if (!response.ok) { const message = typeof data.message === "string" ? data.message : `Error ${response.status}`; throw Object.assign(new Error(message), { status: response.status }); } return data as T; } export interface PublicReview { id: string; author_name: string; rating: number; title: string | null; content: string; created_at: string; verified_purchase: boolean; } export interface ReviewSummary { average: number; count: number; } export interface MyReview { id: string; product_id: string; order_id: string; rating: number; status: "pending" | "approved" | "rejected"; } export interface CustomerOrder { id: string; displayId: number | null; createdAt: string; status: string; total: number | null; currency: string; items: { productId: string; title: string; thumbnail: string | null; handle: string | null; quantity: number }[]; } export function getProductReviews(productId: string) { return medusaFetch<{ reviews: PublicReview[]; average: number; count: number }>(`/store/reviews?product_id=${encodeURIComponent(productId)}`); } export async function getReviewSummary(): Promise> { return (await medusaFetch<{ summary: Record }>("/store/reviews/summary")).summary; } export async function getMyReviews(token: string): Promise { return (await medusaFetch<{ reviews: MyReview[] }>("/store/reviews/me", { token })).reviews; } export function createReview(token: string, body: { product_id: string; order_id: string; rating: number; title?: string; content: string }) { return medusaFetch<{ review: { id: string; status: string } }>("/store/reviews", { method: "POST", body, token }); } type MedusaOrder = { id: string; display_id?: number | null; created_at: string; status: string; total?: number | null; currency_code?: string | null; items?: { product_id?: string | null; product_title?: string | null; title?: string | null; thumbnail?: string | null; product_handle?: string | null; quantity?: number }[]; }; export async function getMyOrders(token: string): Promise { const fields = "id,display_id,created_at,status,total,currency_code,*items"; const data = await medusaFetch<{ orders: MedusaOrder[] }>(`/store/orders?limit=50&order=-created_at&fields=${encodeURIComponent(fields)}`, { token }); return data.orders.map((order) => ({ id: order.id, displayId: order.display_id ?? null, createdAt: order.created_at, status: order.status, total: typeof order.total === "number" ? order.total : null, currency: (order.currency_code ?? "cop").toUpperCase(), items: (order.items ?? []) .filter((item) => item.product_id) .map((item) => ({ productId: item.product_id as string, title: item.product_title || item.title || "Producto", thumbnail: item.thumbnail ?? null, handle: item.product_handle ?? null, quantity: item.quantity ?? 1, })), })); }