Proyecto del curso de Programación Orientada a Objetos (POO) en JavaScript. La idea es construir un Habit Tracker (rastreador de hábitos) aplicando conceptos de POO como:
- Encapsulamiento (campos privados con
#) - Herencia (
TimedHabitextiendeHabit) - Polimorfismo (sobrescritura de métodos como
toDisplayString()) - Responsabilidad única (clases separadas para cálculo de rachas y tracking de logs)
La app corre en el navegador y permite:
- Crear hasta 5 hábitos
- Registrar y remover check-ins por día
- Calcular rachas (streaks)
- Diarias (
daily) - Semanales (
weekly)
- Diarias (
La interfaz principal está en src/index.html y carga el script src/app.js.
- Tablero mensual: muestra los días del mes (hasta el día actual) y permite marcar/desmarcar check-ins.
- Modales:
- Crear hábito
- Registrar hábito
.
├── src/
│ ├── index.html
│ ├── styles.css
│ └── app.js
├── examples.js
├── package.json
└── README.mdsrc/index.html: maquetado principal.src/styles.css: estilos.src/app.js: lógica completa (dominio + UI).examples.js: ejemplos sencillos usados en el curso (funciones y objetos literales).
- Node.js (recomendado 18+) solo si quieres usar un servidor local.
- Un navegador moderno (para soportar campos privados
#privateField).
- Abre
src/index.htmlen tu navegador.
Nota: dependiendo del navegador, abrir archivos con
file://puede tener limitaciones. Si algo no carga como esperas, usa un servidor local (Opción B).
Si tienes alguna extensión como Live Server en VS Code, úsala apuntando a src/index.html.
Alternativas:
- Con Node (si tienes
npxdisponible):npx serve src
El dominio principal vive en src/app.js y está compuesto por:
-
Habit- Representa un hábito base.
- Encapsula estado con campos privados:
#name,#frequency,#id,#tracker,#createdAt
- Expone comportamiento:
rename()registerCheckIn(date)getLogs()/removeCheckIn(date)calculateStreak(today)
-
TimedHabit extends Habit- Agrega el concepto de objetivo de tiempo en minutos (
#targetMinutes). - Sobrescribe
toDisplayString()para extender el formato.
- Agrega el concepto de objetivo de tiempo en minutos (
- El
namese normaliza contrim()y valida mínimo 3 caracteres. - La
frequencyvalida valores permitidos:dailyoweekly.
DomainErrorextiendeErrory agrega uncode.ERROR_CODEScentraliza los códigos de error (ej.INVALID_NAME,INVALID_FREQUENCY).
LogTracker- Guarda internamente un arreglo privado
#dates. - Permite:
addLog(date)getLogs()removeLog(date)
- Guarda internamente un arreglo privado
El cálculo de rachas se delega a calculadoras según la frecuencia:
DailyStreakCalculatorWeeklyStreakCalculator
Y se seleccionan desde:
STREK_CALCULATORS(mapa por frecuencia)
Esto permite cambiar/crecer la lógica de rachas sin modificar el core del hábito, aplicando un enfoque tipo Strategy.
- Máximo 5 hábitos (
MAX_HABITS). - El tablero mensual muestra desde el día 1 hasta el día actual del mes.
- Al hacer click en una celda del tablero:
- Si está marcada: se elimina el log.
- Si no está marcada: se registra el check-in.
Al iniciar la app (initApp()), se crean hábitos de demo en consola:
- Un hábito diario
Leercon check-ins - Un hábito semanal
Ejerciciocon check-ins - Un hábito con tiempo
Meditar
Esto sirve para probar:
toDisplayString()calculateStreak()
- Persistencia en
localStoragepara no perder hábitos al recargar. - Validación de fechas (evitar fechas futuras y duplicados por día).
- Sección de estadísticas usando
getStatistics():- Total de hábitos
- Total de check-ins
- Hábito más constante
- Separar dominio y UI en módulos (ej.
domain/yui/).
MIT.