// Cotizador interactivo — STFLOW const { useState, useEffect, useMemo } = React; const PRODUCTS = [ { id: 'remera', name: 'Remera', ico: '👕', base: 180, desc: 'Algodón peinado 24/1' }, { id: 'gorra', name: 'Gorra', ico: '🧢', base: 260, desc: 'Trucker, snapback o cerrada' }, { id: 'buzo', name: 'Buzo', ico: '🧥', base: 480, desc: 'Canguro o redondo' }, { id: 'polo', name: 'Polo', ico: '👔', base: 320, desc: 'Piqué algodón corporativo' }, { id: 'tote', name: 'Tote bag', ico: '👜', base: 140, desc: 'Crudo 100% algodón' }, { id: 'taza', name: 'Taza', ico: '☕', base: 110, desc: 'Cerámica sublimable' }, ]; const TECHNIQUES = { remera: [ { id: 'dtf', name: 'DTF', note: 'Full color, todo tipo de tela', cost: 150 }, { id: 'sub', name: 'Sublimación', note: 'Poliéster claro', cost: 110 }, { id: 'seri', name: 'Serigrafía', note: '30+ unidades', cost: 70 }, { id: 'vin', name: 'Vinilo', note: 'Texto / números', cost: 60 }, ], gorra: [ { id: 'bord', name: 'Bordado', note: 'Premium · recomendado', cost: 240 }, { id: 'dtf', name: 'DTF', note: 'Full color', cost: 140 }, { id: 'sub', name: 'Sublimación', note: 'Gorras claras', cost: 120 }, ], buzo: [ { id: 'dtf', name: 'DTF', note: 'Full color', cost: 220 }, { id: 'bord', name: 'Bordado', note: 'Logo pequeño', cost: 280 }, { id: 'seri', name: 'Serigrafía', note: '30+ unidades', cost: 110 }, ], polo: [ { id: 'bord', name: 'Bordado', note: 'Recomendado corporativo', cost: 260 }, { id: 'dtf', name: 'DTF', note: 'Full color', cost: 160 }, ], tote: [ { id: 'dtf', name: 'DTF', note: 'Full color', cost: 130 }, { id: 'seri', name: 'Serigrafía', note: '30+ unidades', cost: 70 }, { id: 'vin', name: 'Vinilo', note: 'Texto plano', cost: 60 }, ], taza: [ { id: 'sub', name: 'Sublimación', note: 'Full color', cost: 90 }, ], }; const ADDONS = [ { id: 'packaging', name: 'Packaging kraft + tarjeta', desc: 'Bolsita kraft, sticker y tarjeta de agradecimiento', price: 40 }, { id: 'etiqueta', name: 'Etiqueta con tu marca', desc: 'Etiqueta cosida interna con tu logo', price: 60 }, { id: 'back', name: 'Estampa en la espalda', desc: 'Segunda posición de estampado', price: 120 }, { id: 'urgente', name: 'Producción express', desc: 'Entrega en 5 días hábiles (vs 10-15)', price: 150 }, ]; function volumeDiscount(qty) { if (qty >= 100) return 0.20; if (qty >= 50) return 0.15; if (qty >= 20) return 0.10; return 0; } function fmt(n) { return '$' + Math.round(n).toLocaleString('es-MX'); } function Quoter() { const [step, setStep] = useState(0); const [productId, setProductId] = useState(null); const [techId, setTechId] = useState(null); const [qty, setQty] = useState(10); const [addons, setAddons] = useState({}); const product = PRODUCTS.find(p => p.id === productId); const techniques = productId ? TECHNIQUES[productId] : []; const technique = techniques.find(t => t.id === techId); // Reset technique when product changes useEffect(() => { if (productId && techId && !TECHNIQUES[productId].some(t => t.id === techId)) { setTechId(null); } }, [productId]); const calc = useMemo(() => { if (!product || !technique) return null; const addonPrice = Object.entries(addons) .filter(([, on]) => on) .reduce((s, [id]) => s + (ADDONS.find(a => a.id === id)?.price || 0), 0); const unitCost = product.base + technique.cost + addonPrice + 50; // 50 = packaging base + control const margin = 2.4; const rawUnitPrice = unitCost * margin; const discount = volumeDiscount(qty); const unitPrice = rawUnitPrice * (1 - discount); const subtotal = unitPrice * qty; const profit = (unitPrice - unitCost) * qty; return { unitCost, rawUnitPrice, unitPrice, subtotal, profit, discount, addonPrice, }; }, [product, technique, qty, addons]); const canNext = (step === 0 && productId) || (step === 1 && techId) || step === 2 || step === 3; const goNext = () => setStep(s => Math.min(s + 1, 3)); const goBack = () => setStep(s => Math.max(s - 1, 0)); const sendWhatsApp = () => { if (!product || !technique || !calc) return; const activeAddons = Object.entries(addons) .filter(([, on]) => on) .map(([id]) => ADDONS.find(a => a.id === id).name) .join(', ') || 'ninguno'; const msg = `Hola STFLOW! Quiero cotizar: • Producto: ${product.name} • Técnica: ${technique.name} • Cantidad: ${qty} • Adicionales: ${activeAddons} • Estimado: ${fmt(calc.subtotal)} MX ¿Me pasan detalles?`; window.open(`https://wa.me/525572888676?text=${encodeURIComponent(msg)}`, '_blank'); }; const steps = [ { label: 'Producto' }, { label: 'Técnica' }, { label: 'Cantidad' }, { label: 'Extras' }, ]; return (
Elegí la prenda o artículo base. Después elegimos la técnica de estampado.
Para {product.name} estas son las opciones disponibles.
A partir de 20 unidades aplicamos descuentos automáticos por volumen.
Adicionales opcionales. Podés saltarlos si no te hacen falta.