// Notifications.jsx — header bell + notifications page.
// Plus Reviews modal flow for delivered orders.
const { useState: useNotifState } = React;
const NOTIFICATIONS = [
{ id: "n1", type: "order", icon: "local_shipping", color: "var(--primary)", fg: "var(--primary-soft)", title: "Tu pedido #AL-711981 va en camino", sub: "Llega hoy entre 10:00 y 18:00", t: "hace 12 min", unread: true, href: ["order", { id: "AL-711981" }] },
{ id: "n2", type: "promo", icon: "favorite", color: "#B691FF", fg: "rgba(182,145,255,.16)",title: "Tenis Running UltraBoost ahora −24%", sub: "El producto de tu lista bajó a $1,899",t: "hace 1 h", unread: true, href: ["pdp", { id: "p005" }] },
{ id: "n3", type: "review",icon: "star", color: "var(--star)", fg: "rgba(247,207,82,.18)", title: "Reseña tu compra de Crema hidratante", sub: "¿Cómo te fue con el producto?", t: "hace 3 h", unread: true, action: "review", productId: "p003" },
{ id: "n4", type: "order", icon: "check_circle", color: "var(--success)", fg: "var(--success-bg)", title: "Pedido #AL-712304 entregado", sub: "Te dejamos PIN 8432 con el repartidor",t: "hace 1 d", unread: false, href: ["order", { id: "AL-712304" }] },
{ id: "n5", type: "system",icon: "verified", color: "var(--primary)", fg: "var(--primary-soft)", title: "Tu cuenta es ahora Allen Prime gratis", sub: "30 días con envío en 24 h y cashback 3%", t: "hace 2 d", unread: false, href: ["prime"] },
{ id: "n6", type: "promo", icon: "credit_card", color: "var(--primary)", fg: "var(--primary-soft)", title: "Tu tarjeta •••• 4242 fue cargada con $1,560",sub: "Pedido #AL-712802 confirmado", t: "hace 4 d", unread: false },
{ id: "n7", type: "order", icon: "support_agent", color: "#8A6500", fg: "var(--warning-bg)", title: "Disputa #D-2835 abierta", sub: "Allen Ops está revisando tu caso", t: "hace 5 d", unread: false },
];
// =====================================================================
// NotificationBell — header trigger with unread badge + dropdown panel.
const NotificationBell = ({ onNav, onReview }) => {
const [open, setOpen] = useNotifState(false);
const [items, setItems] = useNotifState(NOTIFICATIONS);
const unread = items.filter(n => n.unread).length;
const markRead = (id) => setItems(arr => arr.map(n => n.id === id ? { ...n, unread: false } : n));
const markAllRead = () => setItems(arr => arr.map(n => ({ ...n, unread: false })));
const onClick = (n) => {
markRead(n.id);
setOpen(false);
if (n.action === "review") onReview?.(n.productId);
else if (n.href) onNav(...n.href);
};
return (
{open && (
<>
setOpen(false)} style={{ position: "fixed", inset: 0, zIndex: 90 }} />
Notificaciones
{items.slice(0, 5).map(n => )}
>
)}
);
};
const NotifRow = ({ n, onClick }) => (
);
const BellIcon = ({ size = 22 }) => (
);
// =====================================================================
// NotificationsPage — full inbox view (linked from "Ver todas")
const NotificationsPage = ({ onNav, onReview }) => {
const [filter, setFilter] = useNotifState("all");
const [items, setItems] = useNotifState(NOTIFICATIONS);
const filtered = filter === "all" ? items : filter === "unread" ? items.filter(n => n.unread) : items.filter(n => n.type === filter);
const markRead = (id) => setItems(arr => arr.map(n => n.id === id ? { ...n, unread: false } : n));
return (
Notificaciones
{items.filter(n => n.unread).length} sin leer · {items.length} en total
{[
{ id: "all", l: "Todas" },
{ id: "unread", l: `Sin leer (${items.filter(n => n.unread).length})` },
{ id: "order", l: "Pedidos" },
{ id: "promo", l: "Promos" },
{ id: "review", l: "Reseñas" },
{ id: "system", l: "Sistema" },
].map(f => (
))}
{filtered.length === 0 ? (
Nada por aquí
Te avisamos cuando algo pase con tus pedidos o tus favoritos.
) : (
filtered.map(n => (
{ markRead(x.id); if (x.action === "review") onReview?.(x.productId); else if (x.href) onNav(...x.href); }} />
))
)}
);
};
// =====================================================================
// ReviewModal — post-delivery "Califica tu compra" flow.
const ReviewModal = ({ productId, onClose }) => {
const [stars, setStars] = useNotifState(0);
const [hover, setHover] = useNotifState(0);
const [text, setText] = useNotifState("");
const [tags, setTags] = useNotifState(new Set());
const [done, setDone] = useNotifState(false);
const toast = useToast();
const product = CATALOG.find(p => p.id === productId) || CATALOG[0];
const tagPool = stars >= 4
? ["Calidad excelente", "Llegó rapidísimo", "Empaque cuidado", "Tal cual la foto", "Lo recomiendo"]
: stars > 0
? ["Calidad baja", "Llegó tarde", "Empaque dañado", "No es como la foto", "Caro para lo que es"]
: [];
const toggleTag = (t) => {
const next = new Set(tags);
next.has(t) ? next.delete(t) : next.add(t);
setTags(next);
};
const submit = () => {
setDone(true);
setTimeout(() => { onClose(); toast("Reseña publicada · gracias por ayudar"); }, 1400);
};
return (
e.stopPropagation()} style={{ background: "var(--bg-elev-1)", borderRadius: "var(--radius-xl)", maxWidth: 540, width: "100%", padding: 32, boxShadow: "var(--elev-pop)" }}>
{!done ? (
<>
Califica tu compra
¿Cómo te fue?
{product.name}
{product.brand}
{/* Star rating */}
{[1,2,3,4,5].map(i => (
))}
{stars > 0 && (
{["", "Muy mala", "Mala", "Aceptable", "Buena", "Excelente"][stars]}
)}
{/* Tags */}
{stars > 0 && (
¿Qué te llamó la atención?
{tagPool.map(t => (
))}
)}
{/* Free text */}
{/* Photo upload (decorative) */}
>
) : (
¡Gracias por tu reseña!
Ayuda a otros compradores a decidir.
)}
);
};
window.NotificationBell = NotificationBell;
window.NotificationsPage = NotificationsPage;
window.ReviewModal = ReviewModal;