`;
} else {
const faltante = (LIMITE_ENVIO_GRATIS - totalCart) / 100;
const porcentaje = (totalCart / LIMITE_ENVIO_GRATIS) * 100;
container.innerHTML = `
📦 Te faltan solo $${faltante.toFixed(2)} MXN para alcanzar tu Envío Gratis
`;
}
} catch (e) {
console.error('Error actualizando barra de envío:', e);
}
}
// --- URGENCIA EN FICHA DE PRODUCTO ---
function inyectarUrgenciaProducto() {
if (!window.location.pathname.includes('/products/')) return;
const btnAgregar = document.querySelector('button[name="add"], .product-form__submit, [class*="add-to-cart"]');
if (!btnAgregar || document.querySelector('.urgency-badge-premium')) return;
const mensajes = [
`⚡ Últimas 3 piezas disponibles de este modelo en tu talla seleccionada.`,
`📦 Alta demanda: Pídelo en las próximas 2 horas para que sea enviado hoy mismo.`,
`🔥 Compra Inteligente: 14 personas tienen este artículo en su carrito ahora mismo.`
];
const mensajeElegido = mensajes[Math.floor(Math.random() * mensajes.length)];
const badge = document.createElement('div');
badge.className = 'urgency-badge-premium';
badge.innerHTML = `
${mensajeElegido}
`;
btnAgregar.parentNode.insertBefore(badge, btnAgregar.nextSibling);
}
// --- LÓGICA DE ALERTA DE TALLA ÚNICA Y AUTORIZACIÓN ---
async function verificarMayoreoCarrito() {
if (!window.location.pathname.includes('/cart')) return;
try {
const response = await fetch('/cart.js');
const cart = await response.json();
let tallas = new Set();
cart.items.forEach(item => {
if (item.variant_options) {
tallas.add(item.variant_options[item.variant_options.length - 1] || 'sin-talla');
}
});
if (cart.item_count >= 6 && tallas.size === 1) {
let warning = document.getElementById('wholesale-warning');
if (!warning) {
warning = document.createElement('div');
warning.id = 'wholesale-warning';
warning.className = 'wholesale-warning alert';
warning.style.cssText = "background: #FFF9E6; border-left: 4px solid #C5A059; color: #5C4308; padding: 15px; margin: 15px 0;";
warning.innerHTML = `
⚠️ DETECTAMOS RIESGO:
Estás ordenando solo una talla. Los distribuidores exitosos siempre inician con curva completa de tallas.
Recomendación: Diversifica con tallas S, M, L, XL para asegurar tu venta rápida (+300% de éxito).
`;
document.querySelector('form[action*="cart"]')?.prepend(warning) || document.body.prepend(warning);
}
}
if (cart.item_count >= 12) {
const btn = document.querySelector('[name="checkout"]');
if (btn && !btn.dataset.modified) {
btn.dataset.modified = 'true';
btn.innerHTML = '🏆 SOLICITAR AUTORIZACIÓN DE DISTRIBUIDOR';
btn.onclick = (e) => {
e.preventDefault();
alert('✅ Solicitud enviada. Alexis Román la revisará en 24h.');
window.location.href = '/pages/solicitud-distribuidor';
};
}
}
} catch(e) {}
}
// Monitor de cambios de recursos (añadir al carrito)
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
if (entry.name.includes('/cart/add') || entry.name.includes('/cart/change') || entry.name.includes('/cart/update')) {
setTimeout(() => {
actualizarBarraEnvio();
verificarMayoreoCarrito();
}, 600);
}
});
});
try { observer.observe({ entryTypes: ['resource'] }); } catch(e) {}
// Inicialización
window.addEventListener('DOMContentLoaded', () => {
actualizarBarraEnvio();
inyectarUrgenciaProducto();
verificarMayoreoCarrito();
});
setTimeout(() => {
actualizarBarraEnvio();
inyectarUrgenciaProducto();
verificarMayoreoCarrito();
}, 1000);
})();
})();
// ══════════════════════════════════════════════════════════════════════════════
// SISTEMA DE RESEÑAS MOON & RAIN — Carrusel + Formulario + Estrellas Doradas
// ══════════════════════════════════════════════════════════════════════════════
(function() {
'use strict';
// ─── Estilos ──────────────────────────────────────────────────────────────
const estilos = document.createElement('style');
estilos.textContent = `
/* Contenedor principal de reseñas */
.mr-reviews-section {
width: 100%;
max-width: 1200px;
margin: 40px auto;
padding: 0 20px;
font-family: 'Georgia', 'Helvetica Neue', sans-serif;
}
.mr-reviews-header {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 16px;
margin-bottom: 28px;
border-bottom: 1px solid rgba(197, 160, 89, 0.2);
padding-bottom: 16px;
}
.mr-reviews-title {
font-size: 22px;
font-weight: 700;
color: #121212;
letter-spacing: 1.5px;
text-transform: uppercase;
margin: 0;
}
.mr-reviews-summary {
display: flex;
align-items: center;
gap: 12px;
color: #555;
font-size: 14px;
}
.mr-stars-display {
display: flex;
gap: 3px;
}
.mr-star {
color: #C5A059;
font-size: 20px;
line-height: 1;
}
.mr-star.empty {
color: #ddd;
}
.mr-star.half {
position: relative;
display: inline-block;
color: #ddd;
}
.mr-star.half::before {
content: '★';
position: absolute;
left: 0;
width: 50%;
overflow: hidden;
color: #C5A059;
}
/* Carrusel */
/* Lista de reseñas — estática, natural */
.mr-reviews-list .mr-review-card {
padding: 20px 0;
border-bottom: 1px solid #f0f0f0;
}
.mr-reviews-list .mr-review-card:last-child {
border-bottom: none;
}
.mr-review-card {
padding: 20px 0;
border-bottom: 1px solid #f0f0f0;
}
.mr-review-card:last-child {
border-bottom: none;
}
.mr-review-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background: #C5A059;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 14px;
flex-shrink: 0;
}
.mr-review-author {
font-weight: 600;
font-size: 14px;
color: #121212;
}
.mr-review-badge {
font-size: 11px;
color: #23A559;
font-weight: 600;
}
.mr-review-stars {
display: flex;
gap: 2px;
}
.mr-review-stars .mr-star {
font-size: 16px;
}
.mr-review-stars .mr-star.half {
color: #C5A059;
}
.mr-review-stars .mr-star.empty {
color: #ddd;
}
.mr-star {
color: #C5A059;
}
.mr-review-text {
font-size: 14px;
line-height: 1.6;
color: #444;
margin: 0;
}
/* Botón de agregar reseña */
.mr-btn-review {
background: #121212;
color: #C5A059;
border: 1px solid #C5A059;
padding: 10px 24px;
font-size: 12px;
letter-spacing: 1.5px;
text-transform: uppercase;
cursor: pointer;
transition: all 0.3s;
font-weight: 600;
}
.mr-btn-review:hover {
background: #C5A059;
color: #121212;
}
/* Formulario de reseña */
.mr-review-form-overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(255,255,255,0.85);
z-index: 99999;
align-items: center;
justify-content: center;
padding: 20px;
backdrop-filter: blur(3px);
}
.mr-review-form-overlay.open { display: flex; }
.mr-review-form {
background: #fff;
max-width: 480px;
width: 100%;
padding: 32px;
border-radius: 4px;
position: relative;
max-height: 90vh;
overflow-y: auto;
}
.mr-review-form h3 {
font-size: 18px;
color: #121212;
margin: 0 0 20px 0;
letter-spacing: 1px;
text-transform: uppercase;
}
.mr-review-form label {
display: block;
font-size: 12px;
color: #666;
margin-bottom: 4px;
letter-spacing: 0.5px;
text-transform: uppercase;
}
.mr-review-form input,
.mr-review-form textarea,
.mr-review-form select {
width: 100%;
padding: 10px 12px;
border: 1px solid #ddd;
font-size: 14px;
margin-bottom: 16px;
box-sizing: border-box;
font-family: inherit;
}
.mr-review-form textarea {
min-height: 100px;
resize: vertical;
}
.mr-review-form .star-select {
display: flex;
gap: 4px;
margin-bottom: 16px;
font-size: 28px;
cursor: pointer;
}
.mr-review-form .star-select span {
color: #ddd;
transition: color 0.2s;
}
.mr-review-form .star-select span.active,
.mr-review-form .star-select span:hover,
.mr-review-form .star-select span:hover ~ span {
color: #C5A059;
}
.mr-form-close {
position: absolute;
top: 16px;
right: 16px;
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #999;
}
.mr-form-submit {
width: 100%;
padding: 14px;
background: #121212;
color: #C5A059;
border: none;
font-size: 13px;
letter-spacing: 2px;
text-transform: uppercase;
cursor: pointer;
font-weight: 600;
transition: all 0.3s;
}
.mr-form-submit:hover { background: #C5A059; color: #121212; }
.mr-form-success {
display: none;
text-align: center;
padding: 30px;
color: #23A559;
font-size: 16px;
}
/* Sin reseñas */
.mr-no-reviews {
text-align: center;
padding: 40px;
color: #999;
border: 1px dashed #ddd;
border-radius: 4px;
}
.mr-no-reviews p { margin: 0 0 16px 0; font-size: 14px; }
@media (max-width: 768px) {
.mr-carousel-btn { display: none; }
.mr-reviews-header { flex-direction: column; align-items: flex-start; }
}
`;
document.head.appendChild(estilos);
// ─── Lógica ──────────────────────────────────────────────────────────────
function initReviews(reviewsData) {
const section = document.querySelector('.mr-reviews-section');
if (!section) return;
if (!reviewsData || reviewsData.length === 0) {
section.innerHTML = `
💬 Sé el primero en opinar sobre este producto.
DEJA TU RESEÑA
`;
return;
}
const total = reviewsData.length;
const avg = (reviewsData.reduce((s, r) => s + r.rating, 0) / total).toFixed(1);
function renderStars(rating, size = 16) {
let html = '';
for (let i = 1; i <= 5; i++) {
if (i <= rating) {
html += '★ ';
} else if (i - 0.5 <= rating) {
html += '★ ';
} else {
html += '★ ';
}
}
return html;
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// Generar la lista completa de reseñas
const reviewsList = reviewsData.map((r, idx) => {
const initials = r.author.split(' ').map(w => w[0]).join('').slice(0, 2).toUpperCase();
const hasPhoto = r.photos && r.photos.length > 0;
const photoHtml = hasPhoto ? '' + r.photos.map(function(p) { return '
'; }).join('') + '
' : '';
return `
${initials}
${escapeHtml(r.author)}
${r.verified ? '✅ Compra verificada' : ''}
${renderStars(r.rating)}
${photoHtml}
${escapeHtml(r.text)}
`;
}).join('');
// Construir el HTML completo — SIN carrusel, SOLO lista estática
section.innerHTML = `
${reviewsList}
`;
}
// ─── Inicializar en páginas de producto ──────────────────────────────────
if (window.location.pathname.includes('/products/')) {
// Esperar a que el DOM cargue los metafields
setTimeout(() => {
const dataEl = document.getElementById('mr-reviews-data');
if (dataEl) {
try {
const reviews = JSON.parse(dataEl.textContent);
initReviews(reviews);
} catch(e) {
console.log('MR Reviews: sin datos');
}
}
}, 500);
}
// ─── Formulario de envío ────────────────────────────────────────────────
const formOverlay = document.createElement('div');
formOverlay.id = 'mr-form-overlay';
formOverlay.className = 'mr-review-form-overlay';
formOverlay.innerHTML = `
`;
document.body.appendChild(formOverlay);
// Manejar selección de estrellas
document.addEventListener('click', function(e) {
const star = e.target.closest('#mr-star-select span');
if (star) {
const val = parseInt(star.dataset.val);
document.getElementById('mr-review-rating').value = val;
document.querySelectorAll('#mr-star-select span').forEach((s, i) => {
s.classList.toggle('active', i < val);
});
}
});
// Cerrar al hacer clic fuera
formOverlay.addEventListener('click', function() {
this.classList.remove('open');
});
window.submitReview = function() {
const name = document.getElementById('mr-review-name').value.trim();
const rating = parseInt(document.getElementById('mr-review-rating').value);
const text = document.getElementById('mr-review-text').value.trim();
const handle = (document.getElementById('mr-product-handle') || {}).content || '';
const productId = (document.getElementById('mr-product-id') || {}).content || '';
const email = document.getElementById('mr-review-email') ? document.getElementById('mr-review-email').value.trim() : '';
if (!name || !text) {
alert('Por favor completa tu nombre y opinión.');
return;
}
// Mostrar estado "enviando..."
const btn = document.querySelector('.mr-form-submit');
const originalText = btn ? btn.textContent : 'ENVIAR RESEÑA';
if (btn) { btn.textContent = 'ENVIANDO...'; btn.disabled = true; }
// Preparar datos
const payload = {
author: name,
rating: rating,
text: text,
photo: selectedReviewPhotos.length > 0 ? selectedReviewPhotos[0] : '',
photos: selectedReviewPhotos,
email: email,
product_id: productId ? parseInt(productId) : null,
handle: handle
};
// Intentar enviar al servidor (si está corriendo)
const endpoint = window.MR_API_URL || 'https://tiendasplatino.com.mx/api/submit-review';
// Usar fetch con timeout
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);
// Intentar endpoint local del webhook, o endpoint externo
// Primero probar si el webhook local está disponible
const servers = [
'http://localhost:8080/api/submit-review',
endpoint // fallback
];
function trySend(serverIndex) {
if (serverIndex >= servers.length) {
// Todos los servidores fallaron → guardar localmente
saveReviewLocally(payload);
return;
}
fetch(servers[serverIndex], {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(payload),
signal: controller.signal
})
.then(function(r) { return r.json(); })
.then(function(data) {
clearTimeout(timeout);
showReviewSuccess(data.puntos_luna || 25);
})
.catch(function() {
// Intentar siguiente servidor
trySend(serverIndex + 1);
});
}
trySend(0);
};
function saveReviewLocally(payload) {
// Guardar en localStorage como fallback
var queue = JSON.parse(localStorage.getItem('mr_review_queue') || '[]');
queue.push(payload);
localStorage.setItem('mr_review_queue', JSON.stringify(queue));
console.log('📝 Reseña guardada localmente (cola:', queue.length, ')');
showReviewSuccess(25);
}
// ─── Gestión de fotos en reseñas ───
let selectedReviewPhotos = [];
const MAX_REVIEW_PHOTOS = 3;
setTimeout(function() {
const photoInput = document.getElementById('mr-photo-input');
const photoPreviews = document.getElementById('mr-photo-previews');
const photoCount = document.getElementById('mr-photo-count');
if (photoInput) {
photoInput.addEventListener('change', function(e) {
const files = Array.from(e.target.files);
const remaining = MAX_REVIEW_PHOTOS - selectedReviewPhotos.length;
files.slice(0, remaining).forEach(function(file) {
if (file.size > 5 * 1024 * 1024) {
alert('Cada foto debe pesar menos de 5MB');
return;
}
selectedReviewPhotos.push(file);
const reader = new FileReader();
reader.onload = function(ev) {
renderPhotoPreviews();
};
reader.readAsDataURL(file);
});
if (photoCount) photoCount.textContent = selectedReviewPhotos.length + '/' + MAX_REVIEW_PHOTOS;
this.value = '';
});
}
function renderPhotoPreviews() {
if (!photoPreviews) return;
photoPreviews.innerHTML = '';
selectedReviewPhotos.forEach(function(file, idx) {
const reader = new FileReader();
reader.onload = function(ev) {
const wrapper = document.createElement('div');
wrapper.className = 'mr-preview-wrapper';
wrapper.innerHTML = ' ' +
'× ';
wrapper.querySelector('.mr-preview-remove').onclick = function() {
selectedReviewPhotos.splice(idx, 1);
renderPhotoPreviews();
if (photoCount) photoCount.textContent = selectedReviewPhotos.length + '/' + MAX_REVIEW_PHOTOS;
};
photoPreviews.appendChild(wrapper);
};
reader.readAsDataURL(file);
});
}
}, 500);
// ─── Lightbox para fotos de reseñas ───
function openReviewLightbox(src) {
var existing = document.querySelector('.mr-lightbox-overlay');
if (existing) {
existing.querySelector('img').src = src;
existing.classList.add('open');
return;
}
var lb = document.createElement('div');
lb.className = 'mr-lightbox-overlay';
lb.innerHTML = '× ';
lb.onclick = function() { this.classList.remove('open'); };
lb.querySelector('.mr-lightbox-close').onclick = function() {
lb.classList.remove('open');
};
document.body.appendChild(lb);
}
function showReviewSuccess(puntos) {
document.getElementById('mr-form-content').style.display = 'none';
var successEl = document.getElementById('mr-form-success');
successEl.style.display = 'block';
successEl.innerHTML = [
'✅
',
'¡Gracias por tu reseña! ',
'Has ganado ' + (puntos || 25) + ' Puntos Luna 🌙
',
'Tu reseña será publicada después de verificación.
'
].join('');
setTimeout(function() {
document.getElementById('mr-form-overlay').classList.remove('open');
document.getElementById('mr-form-content').style.display = 'block';
document.getElementById('mr-form-success').style.display = 'none';
document.getElementById('mr-review-name').value = '';
document.getElementById('mr-review-text').value = '';
var btn = document.querySelector('.mr-form-submit');
if (btn) { btn.textContent = 'ENVIAR RESEÑA'; btn.disabled = false; }
}, 4000);
}
})();
Ir directamente al contenido
Buscar
👔 ¿Qué talla soy?
✕
Guía de Tallas
Descubre tu talla perfecta en segundos
📐 Calculadora
📊 Tabla de medidas
Ingresa tu peso y altura, te decimos qué talla te queda mejor.
Te recomendamos:
M
Talla 36 (M)
📏 Pecho: 94-100 cm
⚡ Peso: 65-78 kg
📐 Altura: 168-178 cm
* La talla puede variar según el ajuste deseado.
Si tienes dudas, escríbenos por WhatsApp.
Mide tu pecho, cintura y largo y compáralos con la tabla.
Talla
Pecho
Cintura
Largo
Manga
Peso
S
88-94
76-81
68-70
60-62
50-65
M
94-100
81-87
71-73
63-65
65-78
L
100-106
87-93
74-76
66-68
78-90
XL
106-112
93-99
77-79
68-70
90-102
XXL
112-118
99-105
79-81
70-72
102-115
3XL
118-124
105-111
81-83
72-74
115-130
📏 ¿Cómo medirse?
Pecho: Mide alrededor de la parte más ancha del pecho, justo debajo de las axilas
Cintura: Mide alrededor de la parte más angosta del torso
Largo: Desde el hombro (costura) hasta el dobladillo
Manga: Desde el hombro hasta la muñeca, con el brazo ligeramente flexionado