Files

331 lines
18 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =====================================================================
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 { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&apos;" }[c];
});
}
// Ilustración SVG ligera en línea (sin red): fondo + círculo + rótulo
function ilus(texto, fondo, acento, simbolo) {
var svg =
'<svg xmlns="http://www.w3.org/2000/svg" width="480" height="320" viewBox="0 0 480 320">' +
'<rect width="480" height="320" fill="' + fondo + '"/>' +
'<circle cx="240" cy="130" r="74" fill="' + acento + '" opacity=".9"/>' +
'<text x="240" y="152" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="62" fill="#fff">' + escXml(simbolo || "") + "</text>" +
'<text x="240" y="266" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="25" fill="#33414a">' + escXml(texto || "") + "</text>" +
"</svg>";
return "data:image/svg+xml," + encodeURIComponent(svg);
}
function avatar(letra, color) {
var svg =
'<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">' +
'<circle cx="48" cy="48" r="48" fill="' + color + '"/>' +
'<text x="48" y="62" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="40" font-weight="700" fill="#fff">' + escXml(letra) + "</text>" +
"</svg>";
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: "[email protected]", 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;
};
})();