Ejercicio: Recordatorios y seguimiento automático
Objetivo
Escribir las cuatro decisiones que toma un recordatorio antes de enviarse: cómo enviarlo (texto o plantilla), cuándo (horario razonable), si corresponde (baja y frecuencia) y cómo reconocer que el cliente pidió no recibir más avisos.
Cómo se trabaja
La parte A es práctica real en tu terminal con el código de referencia del curso. La parte B son cuatro funciones de JavaScript puro que se comprueban en esta página. Las horas son milisegundos (Date.now()); el minimarket está en Lima (UTC-5, sin horario de verano), así que la hora local es la hora UTC menos 5.
💡 Reto extra
Haz que debeRecordar devuelva un objeto { ok, motivo } con el motivo del rechazo ("baja", "frecuencia", "horario"). Guardar el motivo te ayudará a medir por qué no se envían recordatorios.
Pasos
Marca cada paso a medida que lo completes. Tu avance se guarda en este navegador.
💡 Pista 1: Hora de Lima
Resta 5 horas al instante y usa new Date(ms).getUTCHours(). Así no dependes de la zona horaria de tu computadora.
💡 Pista 2: Texto sin tildes
texto.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase() quita las tildes. Luego busca cada frase con includes. Cuidado: «no quiero recibir» debe detectarse, pero «baja» no debe confundirse con «bajar el volumen»; para el reto basta includes, para producción usa palabras completas.
💡 Pista 3: Orden de las reglas en debeRecordar
Primero la baja (es lo más importante), después la frecuencia y al final el horario. Si ultimoRecordatorio es null, nunca se le recordó.
🔎 Comprueba tu trabajo
Pega tu código y pulsa Comprobar. La revisión ocurre en tu navegador; nada se envía a ningún sitio. Cada punto en rojo incluye una pista. Pega solo el JavaScript, sin las etiquetas <script>.
✅ Ver una solución posible
Intenta resolverlo antes de mirar. Tu versión puede ser distinta y también correcta.
const VENTANA = 24 * 60 * 60 * 1000;
const HORA = 60 * 60 * 1000;
function tipoDeEnvio(ultimoMensajeCliente, ahora) {
if (ultimoMensajeCliente == null) return "plantilla";
return ahora - ultimoMensajeCliente < VENTANA ? "texto" : "plantilla";
}
function horaLima(ahora) {
return new Date(ahora - 5 * HORA).getUTCHours();
}
function enHorarioPermitido(ahora) {
const h = horaLima(ahora);
return h >= 8 && h < 21;
}
function esBaja(texto) {
const t = String(texto).normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().trim();
if (t === "baja" || t === "stop") return true;
return ["no quiero recibir", "cancelar suscripcion", "darme de baja"].some((f) => t.includes(f));
}
function debeRecordar(cliente, ahora) {
if (cliente.optOut) return false;
if (cliente.ultimoRecordatorio != null && ahora - cliente.ultimoRecordatorio < VENTANA) return false;
return enHorarioPermitido(ahora);
}