/* global React, Placeholder, SectionHead, StarRow, SkylineGlyph */ // ───────────── BOUTIQUE ───────────── const PRODUCTS = [ { id: 'p1', name: 'Red One Bright White Wax', cat: 'Estilizado', price: 13000, desc: 'Aqua Hair Wax Maximum Control. Acabado brillante, fijación firme. 150ml.', benefits: ['Full Force', 'Brillo alto'], img: 'uploads/redone-bright-white-wax.jpg' }, { id: 'p2', name: 'Red One Silver Cologne', cat: 'Estilizado', price: 13000, desc: 'Cologne Body Splash Silver. Fragancia fresca y amaderada, sin alcohol. 400ml.', benefits: ['Sin alcohol', 'Silver 400ml'], img: 'uploads/redone-silver-cologne.jpg' }, { id: 'p3', name: 'Red One After Shave Fresh', cat: 'Barba', price: 13000, desc: 'Crema colonia post-afeitado. Face Fresh, aroma mentolado fresco. 400ml.', benefits: ['Sin irritación', 'Fresh 400ml'], img: 'uploads/redone-aftershave-fresh.jpg' }, { id: 'p4', name: 'Red One Black Wax', cat: 'Estilizado', price: 13000, desc: 'Aqua Hair Gel Wax Maximum Control. Full Force, 150ml.', benefits: ['Control 10/10', 'Full Force'], img: 'uploads/redone-black-wax.jpg' }, { id: 'p5', name: 'Red One Violetta Wax', cat: 'Estilizado', price: 13000, desc: 'Aqua Hair Gel Wax Maximum Control. Fijación potente con aroma Violetta. 150ml.', benefits: ['Full Force', 'Violetta 150ml'], img: 'uploads/redone-violetta-wax.jpg' }, { id: 'p6', name: 'Red One Spider Spray', cat: 'Cabello', price: 13000, desc: 'Spider Hair Styling Spray Full Force 06. Super Firm, solo profesionales. Efecto araña.', benefits: ['Super Firm', 'Spray 400ml'], img: 'uploads/redone-spider-spray.jpg' }, { id: 'p7', name: 'Red One Gold Cologne', cat: 'Estilizado', price: 13000, desc: 'Cologne Body Splash Gold. Fragancia dorada, sin alcohol. Apta todo tipo de piel.', benefits: ['Sin alcohol', 'Gold · 400ml'], img: 'uploads/redone-gold-cologne.jpg' }, { id: 'p8', name: 'Red One Orange Wax', cat: 'Estilizado', price: 13000, desc: 'Aqua Hair Gel Wax Maximum Control. Fijación extrema con aroma cítrico naranja. 150ml.', benefits: ['Full Force', 'Orange 150ml'], img: 'uploads/redone-orange-wax.jpg' }, ]; const Boutique = () => { const [filter, setFilter] = React.useState('Todos'); const [cart, setCart] = React.useState({}); // { [productId]: qty } const [nombre, setNombre] = React.useState(''); const [telefono, setTelefono] = React.useState(''); const [enviando, setEnviando] = React.useState(false); const [error, setError] = React.useState(''); const [enviado, setEnviado] = React.useState(false); const cats = ['Todos', 'Cabello', 'Barba', 'Estilizado', 'Tratamientos']; const items = PRODUCTS.filter(p => filter === 'Todos' || p.cat === filter); const addToCart = (id) => { setEnviado(false); setCart(prev => ({ ...prev, [id]: (prev[id] || 0) + 1 })); }; const removeFromCart = (id) => { setCart(prev => { const next = { ...prev }; if (next[id] <= 1) { delete next[id]; } else { next[id] -= 1; } return next; }); }; const cartEntries = Object.entries(cart) .map(([id, qty]) => ({ product: PRODUCTS.find(p => p.id === id), qty })) .filter(e => e.product); const cartCount = cartEntries.reduce((sum, e) => sum + e.qty, 0); const cartTotal = cartEntries.reduce((sum, e) => sum + e.qty * e.product.price, 0); const confirmarPedido = async () => { setError(''); if (cartEntries.length === 0) { setError('Agrega al menos un producto.'); return; } if (!nombre.trim() || !telefono.trim()) { setError('Completa tu nombre y teléfono para el pedido.'); return; } const itemsPayload = cartEntries.map(e => ({ name: e.product.name, qty: e.qty, price: e.product.price })); setEnviando(true); try { await fetch('/guardar-pedido.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ cliente_nombre: nombre.trim(), cliente_telefono: telefono.trim(), items: itemsPayload, total: cartTotal, }), }); } catch (e) { // Si falla el guardado igual dejamos que el cliente confirme por WhatsApp. } setEnviando(false); setEnviado(true); const lineas = cartEntries.map(e => `• ${e.qty}x ${e.product.name} — $${(e.qty * e.product.price).toLocaleString('es-CL')}`).join('\n'); const texto = `Hola! Quiero pedir:\n${lineas}\n\nTotal: $${cartTotal.toLocaleString('es-CL')}\nNombre: ${nombre.trim()}`; window.open(`https://wa.me/56984740024?text=${encodeURIComponent(texto)}`, '_blank', 'noreferrer'); setCart({}); }; const pagarPedidoConTarjeta = async () => { setError(''); if (cartEntries.length === 0) { setError('Agrega al menos un producto.'); return; } if (!nombre.trim() || !telefono.trim()) { setError('Completa tu nombre y teléfono para el pedido.'); return; } const itemsPayload = cartEntries.map(e => ({ name: e.product.name, qty: e.qty, price: e.product.price })); setEnviando(true); try { const res = await fetch('/guardar-pedido.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ cliente_nombre: nombre.trim(), cliente_telefono: telefono.trim(), items: itemsPayload, total: cartTotal, }), }); const data = await res.json(); if (!data || !data.id) throw new Error('sin id'); const form = document.createElement('form'); form.method = 'POST'; form.action = '/pago/iniciar.php'; form.style.display = 'none'; form.innerHTML = '' + ''; document.body.appendChild(form); form.submit(); } catch (e) { setEnviando(false); setError('No se pudo iniciar el pago con tarjeta. Intenta de nuevo o confirma por WhatsApp.'); } }; return (
{/* Category rail */}
{cats.map(c => ( ))}
{/* Product grid */}
{items.map(p => ( addToCart(p.id)} /> ))}
{items.length} de {PRODUCTS.length} piezas · más en camino
{/* Carrito / pedido */} {cartEntries.length > 0 && (
— TU PEDIDO ({cartCount}) —
{cartEntries.map(e => (
{e.product.name} {e.qty} ${(e.qty * e.product.price).toLocaleString('es-CL')}
))}
Total ${cartTotal.toLocaleString('es-CL')}
setNombre(e.target.value)} style={{ padding: '12px 14px', border: '1px solid rgba(250,248,243,0.2)', background: 'rgba(250,248,243,0.05)', color: 'var(--bg)', fontFamily: 'Inter, sans-serif', fontSize: 14 }} /> setTelefono(e.target.value)} style={{ padding: '12px 14px', border: '1px solid rgba(250,248,243,0.2)', background: 'rgba(250,248,243,0.05)', color: 'var(--bg)', fontFamily: 'Inter, sans-serif', fontSize: 14 }} />
{error &&
{error}
} {enviado && !error &&
¡Pedido enviado! Te contactaremos por WhatsApp.
}
)}
); }; const ProductCard = ({ product, qty, onAdd }) => (
{product.img ? {product.name} : }
{product.cat}
{product.name}
{product.desc}
{product.benefits.map(b => ( {b} ))}
${product.price.toLocaleString('es-CL')}
); // ───────────── GALERÍA ───────────── const GaleriaTile = ({ img, label, tall, dark }) => ( img ? {label} : ); const Galeria = () => { const tiles = [ { label: 'Local · Fachada', tall: true }, { label: 'Estación 01' }, { img: 'uploads/galeria-fade-barba.jpg', label: 'Fade + barba' }, { label: 'Antes / Después', dark: true }, { img: 'uploads/galeria-fade-taper.jpg', label: 'Fade taper', tall: true }, { label: 'Detalle navaja' }, { label: 'Boutique · Estante' }, ]; return (
{tiles.map((t, i) => ( ))}
); }; // ───────────── TESTIMONIOS ───────────── const TESTIMONIES = [ { name: 'Tomás V.', role: 'Cliente · 2 años', text: 'La atención al detalle es otra liga. Salí no solo con un corte impecable, sino con un ritual.', stars: 5 }, { name: 'Diego A.', role: 'Cliente nuevo', text: 'Me atendió Matías. Conversación, café y el mejor fade de Coquimbo. Volveré sin duda.', stars: 5 }, { name: 'Javier M.', role: 'Cliente · 1 año', text: 'Compré la pomada mate después del corte y se nota la diferencia. Boutique con criterio.', stars: 5 }, ]; const Testimonios = () => (
{TESTIMONIES.map((t, i) => (
"

{t.text}

{t.name}
{t.role}
))}
{/* Video testimonial placeholder */}
— Video destacado —
); Object.assign(window, { Boutique, Galeria, Testimonios, PRODUCTS, TESTIMONIES });