Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/BrandonCVale/SISTEMA-HABITOS/llms.txt

Use this file to discover all available pages before exploring further.

The Hábito. dashboard is the first screen a user sees after logging in. It consolidates everything relevant to the current day: the habits scheduled for today, three at-a-glance KPI cards, and a monthly heat-map calendar that visualises which days during the current month had at least one completed habit. The dashboard is served from the /pagina_principal/inicio route and requires an active session — unauthenticated visitors are redirected to the login page automatically.

Today’s Habits

Route: GET /pagina_principal/inicio Not all habits are shown on the dashboard — only those that are active and scheduled for today’s day of the week. The route resolves which habits belong to today using Python’s date.weekday() method and a lookup dictionary that maps weekday integers to the single-letter codes stored in dias_semana:
hoy = date.today()

# Mapeo para traducir el número de Python (0=Lunes) a nuestras letras
mapa_dias = {0: 'L', 1: 'M', 2: 'X', 3: 'J', 4: 'V', 5: 'S', 6: 'D'}
letra_hoy = mapa_dias[hoy.weekday()]

habitos_hoy = []

for habito in habitos_usuario:
    habito.completado_hoy = any(registro.fecha == hoy for registro in habito.registros)
    # Filtramos: Solo lo agregamos a la lista si está activo y toca hacerlo hoy
    if habito.activo and letra_hoy in habito.dias_semana:
        habitos_hoy.append(habito)
The loop also attaches a transient completado_hoy attribute to each habit object by scanning its registros relationship for a record matching today’s date. The Jinja2 template uses this attribute to render the completion button in its correct checked or unchecked state. Each habit card on the dashboard includes:
  • The habit name and optional description
  • A toggle button that posts to POST /habitos/completar/<id> to mark or unmark completion
The dashboard only shows habits scheduled for today (active habits where today’s day letter is in dias_semana). To see, edit, or manage all of your habits — including those not scheduled for today and inactive habits — visit /habitos/mis_habitos.

KPI Cards

Three summary metrics are computed server-side from the habits data and passed directly to the template as template variables.

Hábitos completados hoy

habitos_completados_hoyA count of how many of today’s scheduled habits have already been marked complete. Computed as:
habitos_completados_hoy = sum(1 for h in habitos_hoy if h.completado_hoy)

Racha actual

racha_actualThe highest racha_actual value across all of the user’s habits (not just today’s). Represents the user’s best active consecutive-day streak right now:
racha_actual = max([h.racha_actual for h in habitos_usuario] + [0])
The + [0] guard ensures the expression returns 0 rather than raising a ValueError when the user has no habits yet.

Mejor racha

mejor_rachaThe highest mejor_racha value ever recorded across all habits — the user’s all-time personal record:
mejor_racha = max([h.mejor_racha for h in habitos_usuario] + [0])

Monthly Heat-Map Calendar

The calendar section of the dashboard highlights every day in the current month on which the user completed at least one habit. It is built entirely in Python and rendered with Jinja2 — no JavaScript calendar library is required.

Computing the calendar data

The route collects three pieces of information needed to render the grid:
# 1. Averiguamos cuántos días tiene el mes y en qué día de la semana empieza (0=Lunes, 6=Domingo)
_, num_dias = calendar.monthrange(hoy.year, hoy.month)
dia_semana_inicio = date(hoy.year, hoy.month, 1).weekday()

# 2. Consultamos nuestro repositorio
dias_completados = HabitoRepository.obtener_dias_activos_mes(current_user.id, hoy.year, hoy.month)
VariableTypePurpose
num_diasintTotal days in the current month (28–31)
dia_semana_inicioint (0–6)Weekday of the 1st — used to offset the first calendar cell
dias_completadosset[int]Day numbers (e.g. {3, 7, 14}) with at least one completion

The repository query

HabitoRepository.obtener_dias_activos_mes performs a SQL JOIN between registro_habitos and habitos to scope the results to the current user, then extracts only the day numbers into a Python set for O(1) look-up in the template:
@staticmethod
def obtener_dias_activos_mes(usuario_id: int, anio: int, mes: int) -> set:
    # Averiguamos cuántos días tiene este mes
    _, num_dias = calendar.monthrange(anio, mes)
    primer_dia = date(anio, mes, 1)
    ultimo_dia = date(anio, mes, num_dias)

    # Hacemos un JOIN para buscar solo los registros de este usuario en este mes
    consulta = db.select(RegistroHabito.fecha).join(Habito).where(
        Habito.usuario_id == usuario_id,
        RegistroHabito.fecha >= primer_dia,
        RegistroHabito.fecha <= ultimo_dia,
        RegistroHabito.completado == True
    )
    fechas = db.session.execute(consulta).scalars().all()

    # Extraemos solo el número del día (ej. 15) y lo metemos en un Set {}
    return {f.day for f in fechas}

Rendering in Jinja2

The template receives num_dias, dia_semana_inicio, and dias_completados (the set). It uses dia_semana_inicio to insert the correct number of empty leading cells so the first day of the month falls on the right column, then iterates from 1 to num_dias. For each day it checks membership in dias_completados to apply a highlight CSS class:
{# Pseudocode representation of the Jinja2 calendar loop #}
{% for i in range(dia_semana_inicio) %}
  <div class="calendar-cell empty"></div>
{% endfor %}

{% for dia in range(1, num_dias + 1) %}
  <div class="calendar-cell {% if dia in dias_completados %}completed{% endif %}">
    {{ dia }}
  </div>
{% endfor %}
The month name is resolved server-side from a Spanish month-name list before being passed to the template as mes_actual:
nombres_meses = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio",
                 "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"]
mes_actual = nombres_meses[hoy.month - 1]

Build docs developers (and LLMs) love