/* ===================================================================== js/escenarios.js — Escenarios de arranque por industria (editor, C). Objetos JS planos (sin fetch: funciona por file://). Cada escenario devuelve un estado que se pasa por WAM.normalizar antes de usarse. Todos los negocios, personas, direcciones y cifras son FICTICIOS y de ejemplo: el equipo debe revisar los textos antes de usarlos con un cliente. No toca el DOM al cargar. ===================================================================== */ (function () { "use strict"; window.WAM = window.WAM || {}; function escXml(s) { return String(s).replace(/[&<>"']/g, function (c) { return { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c]; }); } // Ilustración SVG ligera en línea (sin red): fondo + círculo + rótulo function ilus(texto, fondo, acento, simbolo) { var svg = '' + '' + '' + '' + escXml(simbolo || "") + "" + '' + escXml(texto || "") + "" + ""; return "data:image/svg+xml," + encodeURIComponent(svg); } function avatar(letra, color) { var svg = '' + '' + '' + escXml(letra) + "" + ""; return "data:image/svg+xml," + encodeURIComponent(svg); } // Atajos de construcción function t(dir, hora, texto, extra) { var m = { dir: dir, tipo: "text", hora: hora, texto: texto }; if (extra) Object.keys(extra).forEach(function (k) { m[k] = extra[k]; }); return m; } function r(texto) { return { dir: "in", tipo: "text", hora: "", texto: texto }; } function msg(dir, tipo, hora, campos) { var m = { dir: dir, tipo: tipo, hora: hora, estado: dir === "out" ? "read" : "sent" }; Object.keys(campos || {}).forEach(function (k) { m[k] = campos[k]; }); return m; } function estado(cuenta, mensajes) { return { version: 1, tema: "claro", cuenta: cuenta, mensajes: mensajes }; } var ESCENARIOS = [ { id: "blanco", nombre: "En blanco", descripcion: "Solo la cuenta, sin mensajes. Para construir desde cero.", datos: function () { return estado({ nombre: "Mi negocio", avatar: "", subtitulo: "en línea", verificado: false }, []); } }, { id: "restaurante", nombre: "Restaurante · reservas", descripcion: "Reserva de mesa con plantilla de confirmación, menú en lista y ubicación.", datos: function () { return estado({ nombre: "La Terraza del Puerto", avatar: avatar("T", "#b5523b"), subtitulo: "en línea", verificado: true }, [ t("out", "13:02", "Hola, ¿tienen mesa para este sábado?"), msg("in", "buttons", "13:02", { body: "¡Hola! 👋 Con gusto te ayudo con tu reserva. ¿Para cuántas personas sería?", footer: "La Terraza del Puerto", botones: [ { texto: "2 personas", respuestas: [r("Perfecto, mesa para 2. ¿Prefieres comida (14:00) o cena (21:00)?")] }, { texto: "3 a 5 personas", respuestas: [r("Genial. Para grupos de 3 a 5 tenemos terraza o salón. Te comparto el menú mientras eliges.")] }, { texto: "Más de 5", respuestas: [r("Para grupos grandes te atiende nuestro equipo de eventos. Te escriben en unos minutos.")] } ] }), t("out", "13:03", "Somos 2, para cenar"), msg("in", "template", "13:03", { headerTipo: "imagen", headerMedia: ilus("Tu mesa está lista", "#f6e7df", "#b5523b", "✓"), body: "Hola Ana, tu mesa para *2 personas* quedó reservada el sábado a las *21:00*. ¿Confirmas la reserva?", footer: "Tolerancia de 15 minutos", botones: [ { texto: "Confirmar", respuestas: [r("¡Listo! Reserva confirmada ✨ Te esperamos el sábado a las 21:00.")] }, { texto: "Cambiar horario", respuestas: [r("Claro. ¿A qué hora te acomoda mejor? Tenemos 20:00, 21:30 y 22:00.")] } ] }), msg("in", "list", "13:04", { header: "Menú de la casa", body: "Mientras tanto, ¿quieres ver alguna sección del menú?", footer: "Precios con impuestos incluidos", boton: "Ver menú", secciones: [ { titulo: "Entradas", filas: [ { titulo: "Ceviche del día", descripcion: "Pesca local con cítricos", respuestas: [r("El ceviche del día cambia según la pesca. Te lo recomendamos 🐟")] }, { titulo: "Pan de la casa", descripcion: "Masa madre y mantequilla", respuestas: [r("Nuestro pan se hornea cada tarde 🥖")] } ] }, { titulo: "Platos fuertes", filas: [ { titulo: "Pescado a la talla", descripcion: "Para compartir", respuestas: [r("Buena elección para 2 personas. Se prepara en unos 25 minutos.")] }, { titulo: "Pasta de mariscos", descripcion: "Receta de la casa", respuestas: [r("La pasta de mariscos es de las más pedidas 🍝")] } ] } ] }), msg("in", "location", "13:05", { latitud: "19.4326", longitud: "-99.1332", nombre: "La Terraza del Puerto", direccion: "Av. del Malecón 120, Centro" }) ]); } }, { id: "ecommerce", nombre: "E-commerce · pedido", descripcion: "Confirmación y seguimiento de pedido, catálogo en carrusel y enlace de rastreo.", datos: function () { return estado({ nombre: "Tienda Brisa", avatar: avatar("B", "#2f6fb5"), subtitulo: "Cuenta de empresa", verificado: true }, [ msg("in", "template", "09:15", { headerTipo: "texto", headerTexto: "Pedido #10482 confirmado", body: "¡Gracias por tu compra, Carlos! 🎉 Tu pedido ya está en preparación. Te avisaremos por aquí cuando salga a reparto.", footer: "Tienda Brisa · Atención a clientes", botones: [ { texto: "Ver detalle", respuestas: [r("Tu pedido incluye: 1 × Sudadera Brisa (M) y 1 × Gorra clásica. Total: $1,250.")] }, { texto: "Cambiar dirección", respuestas: [r("Sin problema. Envíame la nueva dirección completa con código postal.")] } ] }), t("out", "09:20", "¿Cuándo llega?"), msg("in", "cta_url", "09:20", { headerMedia: ilus("En camino", "#e3eef9", "#2f6fb5", "➜"), body: "Tu pedido salió a reparto 🚚 La entrega estimada es *mañana entre 10:00 y 14:00*.", footer: "Actualizado hace 5 minutos", textoBoton: "Rastrear pedido", url: "https://example.com/rastreo" }), msg("in", "carousel", "09:21", { body: "Mientras llega, esto combina con tu compra:", cards: [ { media: ilus("Chamarra ligera", "#e8f0f7", "#2f6fb5", "1"), texto: "Chamarra ligera · impermeable y plegable.", textoBoton: "Me interesa", url: "", respuestas: [r("¡Buena elección! Te aparto una en talla M por 24 h.")] }, { media: ilus("Mochila urbana", "#eef3ea", "#4f8a3c", "2"), texto: "Mochila urbana · 20 L con compartimento para laptop.", textoBoton: "Me interesa", url: "", respuestas: [r("La mochila tiene 10 % de descuento esta semana.")] }, { media: ilus("Termo 750 ml", "#f7efe3", "#c07a2c", "3"), texto: "Termo de acero · 750 ml, frío 24 h.", textoBoton: "Me interesa", url: "", respuestas: [r("El termo viene en 4 colores. ¿Cuál prefieres?")] } ] }), msg("in", "buttons", "09:22", { body: "¿Hay algo más en lo que te pueda ayudar?", botones: [ { texto: "Devoluciones", respuestas: [r("Tienes 30 días para devoluciones sin costo. Solo responde con tu número de pedido.")] }, { texto: "Hablar con alguien", respuestas: [r("Te conecto con una persona del equipo. Tiempo de espera aproximado: 3 minutos.")] }, { texto: "No, gracias", respuestas: [r("¡Gracias a ti! Que disfrutes tu compra 💙")] } ] }) ]); } }, { id: "clinica", nombre: "Clínica · citas", descripcion: "Agenda de citas por especialidad, recordatorio con plantilla y documento de indicaciones.", datos: function () { return estado({ nombre: "Clínica Bienestar", avatar: avatar("C", "#1f8a7a"), subtitulo: "en línea", verificado: true }, [ t("out", "08:40", "Hola, quiero agendar una cita"), msg("in", "list", "08:40", { header: "Agenda tu cita", body: "¡Hola! Soy el asistente de Clínica Bienestar. ¿Con qué especialidad necesitas tu cita?", footer: "Horario: lunes a sábado", boton: "Especialidades", secciones: [ { titulo: "Consulta", filas: [ { titulo: "Medicina general", descripcion: "Consulta de 30 minutos", respuestas: [r("Tengo disponibles mañana a las 10:00 y a las 12:30. ¿Cuál prefieres?")] }, { titulo: "Pediatría", descripcion: "Niñas y niños de 0 a 15 años", respuestas: [r("Pediatría tiene espacio el jueves a las 9:00 y a las 16:00.")] } ] }, { titulo: "Estudios", filas: [ { titulo: "Laboratorio", descripcion: "Análisis clínicos", respuestas: [r("Para laboratorio no necesitas cita: de 7:00 a 11:00, en ayuno.")] } ] } ] }), t("out", "08:42", "Mañana a las 10:00"), msg("in", "template", "08:42", { headerTipo: "texto", headerTexto: "Cita confirmada", body: "Hola Laura, tu cita de *Medicina general* quedó agendada para mañana a las *10:00*. Llega 10 minutos antes con una identificación.", footer: "Clínica Bienestar", botones: [ { texto: "Confirmar asistencia", respuestas: [r("¡Gracias! Tu asistencia quedó confirmada ✅")] }, { texto: "Reprogramar", respuestas: [r("Claro. ¿Qué día te acomoda mejor?")] }, { texto: "Cancelar cita", respuestas: [r("Tu cita fue cancelada. Si necesitas otra, escríbenos cuando quieras.")] } ] }), msg("in", "document", "08:43", { caption: "Indicaciones para tu consulta", filename: "indicaciones-consulta.pdf" }), msg("in", "location", "08:43", { latitud: "20.6597", longitud: "-103.3496", nombre: "Clínica Bienestar", direccion: "Calle Robles 45, Col. Jardines" }) ]); } }, { id: "inmobiliaria", nombre: "Inmobiliaria · visitas", descripcion: "Presentación de propiedades en carrusel, filtros por zona y agenda de visita.", datos: function () { return estado({ nombre: "Horizonte Inmuebles", avatar: avatar("H", "#6b4fa3"), subtitulo: "Cuenta de empresa", verificado: false }, [ t("out", "17:10", "Hola, vi un anuncio de departamentos en renta"), msg("in", "buttons", "17:10", { headerTipo: "imagen", headerMedia: ilus("Encuentra tu espacio", "#efe9f7", "#6b4fa3", "⌂"), body: "¡Hola! Gracias por escribirnos. ¿Qué tipo de propiedad buscas?", botones: [ { texto: "Departamento", respuestas: [r("Te muestro los departamentos disponibles esta semana 👇")] }, { texto: "Casa", respuestas: [r("Por ahora tenemos 2 casas en renta. Un asesor te comparte los detalles.")] }, { texto: "Oficina", respuestas: [r("Para oficinas te atiende nuestro equipo comercial. ¿Me compartes tu correo?")] } ] }), msg("in", "carousel", "17:11", { body: "Departamentos disponibles:", cards: [ { media: ilus("2 recámaras · 78 m²", "#f1ecf8", "#6b4fa3", "A"), texto: "Zona norte · 2 recámaras, 1 baño, estacionamiento.", textoBoton: "Agendar visita", url: "", respuestas: [r("¿Qué día te gustaría visitarlo? Tenemos martes y jueves por la tarde.")] }, { media: ilus("1 recámara · 52 m²", "#e9f2f1", "#2f8a7e", "B"), texto: "Zona centro · 1 recámara, amueblado, cerca del metro.", textoBoton: "Agendar visita", url: "", respuestas: [r("Este se renta amueblado. ¿Te agendo una visita el sábado a las 11:00?")] }, { media: ilus("3 recámaras · 110 m²", "#f7efe6", "#b0763a", "C"), texto: "Zona sur · 3 recámaras, 2 baños, jardín común.", textoBoton: "Ver fotos", url: "https://example.com/propiedad", respuestas: [] } ] }), t("out", "17:13", "El de 2 recámaras, el jueves"), msg("in", "template", "17:13", { body: "Listo, tu visita al departamento de *2 recámaras* quedó agendada el jueves a las *18:00*. Te acompaña Daniel, tu asesor.", footer: "Horizonte Inmuebles", botones: [ { texto: "Confirmar", respuestas: [r("¡Perfecto! Te enviamos la ubicación exacta un día antes.")] }, { texto: "Cambiar hora", respuestas: [r("¿Qué horario te funciona mejor el jueves?")] } ] }), msg("in", "contact", "17:14", { nombre: "Asesor de ejemplo", telefono: "+52 55 0000 0000", email: "asesor@example.com", empresa: "Horizonte Inmuebles" }) ]); } }, { id: "soporte", nombre: "Soporte · preguntas frecuentes", descripcion: "Menú de ayuda en lista, respuestas encadenadas y paso a una persona del equipo.", datos: function () { return estado({ nombre: "Conecta Soporte", avatar: avatar("S", "#0f7c9b"), subtitulo: "Responde en minutos", verificado: true }, [ t("out", "11:00", "Hola, tengo un problema con mi cuenta"), msg("in", "list", "11:00", { header: "Centro de ayuda", body: "Hola 👋 Soy el asistente virtual. Elige el tema y te ayudo al momento.", footer: "Disponible 24/7", boton: "Ver temas", secciones: [ { titulo: "Cuenta", filas: [ { titulo: "Olvidé mi contraseña", descripcion: "Restablecer el acceso", respuestas: [ r("Puedes restablecerla desde *Iniciar sesión › ¿Olvidaste tu contraseña?*"), r("Te llegará un correo con un enlace válido por 30 minutos.") ] }, { titulo: "Cambiar mi correo", descripcion: "Actualizar datos de contacto", respuestas: [r("Ve a *Perfil › Datos de contacto* y confirma el cambio desde tu correo actual.")] } ] }, { titulo: "Pagos", filas: [ { titulo: "Cobro no reconocido", descripcion: "Revisar un cargo", respuestas: [r("Lo revisamos contigo. Te paso con una persona del equipo de pagos.")] }, { titulo: "Descargar factura", descripcion: "Facturas de los últimos 12 meses", respuestas: [r("Tus facturas están en *Cuenta › Facturación*.")] } ] } ] }), msg("in", "buttons", "11:02", { body: "¿Te sirvió esta respuesta?", botones: [ { texto: "Sí, gracias", respuestas: [r("¡Qué bueno! Si necesitas algo más, aquí estamos 🙌")] }, { texto: "No, necesito ayuda", respuestas: [r("Te conecto con una persona del equipo. Tiempo de espera aproximado: 5 minutos.")] } ] }), msg("in", "cta_url", "11:03", { body: "También puedes consultar las guías paso a paso en nuestro centro de ayuda.", textoBoton: "Abrir guías", url: "https://example.com/ayuda" }) ]); } }, { id: "cobranza", nombre: "Cobranza · recordatorio", descripcion: "Recordatorio de pago con plantilla, opciones de pago y comprobante en documento.", datos: function () { return estado({ nombre: "Servicios Claros", avatar: avatar("S", "#3b7d4f"), subtitulo: "Cuenta de empresa", verificado: true }, [ msg("in", "template", "10:00", { headerTipo: "texto", headerTexto: "Recordatorio de pago", body: "Hola Marta, te recordamos que tu pago de *$850* vence el *15 de octubre*. Evita recargos pagando a tiempo.", footer: "Si ya pagaste, ignora este mensaje", botones: [ { texto: "Pagar ahora", url: "https://example.com/pago", respuestas: [] }, { texto: "Ya pagué", respuestas: [r("¡Gracias! En cuanto se refleje tu pago te enviamos el comprobante.")] }, { texto: "Necesito una prórroga", respuestas: [r("Entendido. Te comparto las opciones disponibles 👇")] } ] }), t("out", "10:05", "Necesito una prórroga"), msg("in", "buttons", "10:05", { body: "Estas son las opciones que tenemos para ti:", footer: "Sujeto a aprobación", botones: [ { texto: "Pagar en 2 partes", respuestas: [r("Listo, dividimos tu saldo en 2 pagos quincenales. Te enviamos el detalle por aquí.")] }, { texto: "Mover la fecha", respuestas: [r("Podemos mover la fecha de vencimiento hasta 7 días. ¿Te funciona?")] }, { texto: "Hablar con asesor", respuestas: [r("Un asesor te contactará hoy en horario de oficina.")] } ] }), t("out", "10:07", "Pagar en 2 partes"), msg("in", "document", "10:08", { caption: "Aquí está el detalle de tus 2 pagos", filename: "plan-de-pagos.pdf" }) ]); } } ]; WAM.ESCENARIOS = ESCENARIOS; // Devuelve un estado CRUDO (sin normalizar) del escenario id, o null WAM.datosEscenario = function (id) { for (var i = 0; i < ESCENARIOS.length; i++) { if (ESCENARIOS[i].id === id) return ESCENARIOS[i].datos(); } return null; }; })();