import { defineRouteConfig } from "@medusajs/admin-sdk"; import { Star } from "@medusajs/icons"; import { Badge, Button, Container, Heading, Text, toast } from "@medusajs/ui"; import { useCallback, useEffect, useState } from "react"; import { sdk } from "../../lib/sdk"; // Moderacion de reseñas: todas nacen "pendiente" (solo compradores // verificados pueden dejarlas, ver src/api/store/reviews/route.ts) y // recien se publican en la tienda cuando se aprueban aca. type Status = "pending" | "approved" | "rejected"; type Review = { id: string; product_title: string; author_name: string; rating: number; title: string | null; content: string; status: Status; order_id: string; created_at: string; }; const TABS: { status: Status; label: string }[] = [ { status: "pending", label: "Pendientes" }, { status: "approved", label: "Publicadas" }, { status: "rejected", label: "Rechazadas" }, ]; const BADGE: Record = { pending: "orange", approved: "green", rejected: "red" }; const STATUS_LABEL: Record = { pending: "Pendiente", approved: "Publicada", rejected: "Rechazada" }; function stars(rating: number): string { return "★".repeat(rating) + "☆".repeat(5 - rating); } const ReviewsPage = () => { const [tab, setTab] = useState("pending"); const [reviews, setReviews] = useState([]); const [loading, setLoading] = useState(true); const [busyId, setBusyId] = useState(null); const load = useCallback(async (status: Status) => { setLoading(true); const data = await sdk.client.fetch<{ reviews: Review[] }>(`/admin/reviews?status=${status}`); setReviews(data.reviews); setLoading(false); }, []); useEffect(() => { load(tab); }, [load, tab]); async function setStatus(review: Review, status: Status) { setBusyId(review.id); try { await sdk.client.fetch(`/admin/reviews/${review.id}`, { method: "post", body: { status } }); toast.success(status === "approved" ? "Reseña publicada en la tienda" : status === "rejected" ? "Reseña rechazada" : "Reseña devuelta a pendientes"); await load(tab); } catch (error) { toast.error((error as Error).message); } finally { setBusyId(null); } } async function remove(review: Review) { if (!window.confirm(`¿Borrar la reseña de ${review.author_name}? No se puede deshacer.`)) return; setBusyId(review.id); try { await sdk.client.fetch(`/admin/reviews/${review.id}`, { method: "delete" }); toast.success("Reseña borrada"); await load(tab); } catch (error) { toast.error((error as Error).message); } finally { setBusyId(null); } } return (
Reseñas Solo compradores verificados pueden reseñar. Nada se publica sin tu aprobación.
{TABS.map((item) => ( ))}
{loading ? (
Cargando…
) : reviews.length === 0 ? (
No hay reseñas en esta pestaña.
) : ( reviews.map((review) => (
{review.product_title} {STATUS_LABEL[review.status]}
{stars(review.rating)} {review.title && {review.title}} {review.content} {review.author_name} · {new Date(review.created_at).toLocaleDateString("es-CO")} · pedido {review.order_id}
{review.status !== "approved" && ( )} {review.status !== "rejected" && ( )}
)) )}
); }; export const config = defineRouteConfig({ label: "Reseñas", icon: Star, }); export default ReviewsPage;