Skip to main content

Overview

The Administrative Dashboard is the central command center for workforce management in Checawaa. It provides real-time visibility into employee attendance, automated tardiness detection, visual analytics with interactive charts, and one-click access to reporting and notification tools.
Only users with admin privileges (username: “admin”) can access the dashboard. Regular employees are automatically redirected to the employee tracking interface.

Dashboard Features

The admin panel consolidates critical workforce data into an intuitive interface:

Real-Time Attendance

Complete history of all employee check-ins with timestamps and status indicators

Tardiness Detection

Automatic flagging of late arrivals (after 8:30 AM) with visual status badges

Visual Analytics

Interactive doughnut charts showing cumulative tardiness by employee

Quick Actions

One-click buttons for sending reminders and generating PDF reports

Accessing the Dashboard

1

Login as Admin

Sign in with admin credentials (username: admin, password configured in system)
2

Automatic Redirect

The system automatically redirects admin users to /monitor after successful login
3

View Dashboard

Access the full administrative interface with all workforce data and controls

Access Control

The system enforces strict access control in app.py:134-175:
@app.route('/monitor')
@login_required
def monitor():
    if current_user.id != 'admin':
        return redirect(url_for('index'))
    
    # Dashboard logic continues...
Non-admin users attempting to access /monitor directly are redirected to the employee tracking page.

Dashboard Interface

Header Section

The dashboard header provides identity and quick action controls:
<div class="header-flex">
    <div>
        <h1>📊 Panel Administrativo</h1>
        <p style="color:#888;">Control de Asistencia de Personal</p>
    </div>
    <div class="btn-group">
        <button class="btn btn-email" onclick="enviarRecordatorio()">
            📧 Notificar Faltantes
        </button>
        <a href="/reporte-pdf" class="btn btn-pdf">
            📥 Reporte PDF
        </a>
        <a href="/logout">
            Cerrar Sesión
        </a>
    </div>
</div>

Main Grid Layout

The dashboard uses a two-column responsive grid:
Left Column: Complete attendance history tableDisplays:
  • Employee name with online indicator
  • Check-in date (YYYY-MM-DD format)
  • Precise timestamp (HH:MM:SS)
  • Status badge (PUNTUAL/RETARDO)
<table>
    <thead>
        <tr>
            <th>Maestro</th>
            <th>Fecha</th>
            <th>Hora de Registro</th>
            <th>Estado</th>
        </tr>
    </thead>
    <tbody>
        {% for reg in asistencia %}
        <tr>
            <td><span class="online-dot"></span> <strong>{{ reg.usuario }}</strong></td>
            <td>{{ reg.fecha }}</td>
            <td>{{ reg.hora }}</td>
            <td>
                <span class="status-badge {{ 'retardo' if reg.status == 'RETARDO' else 'puntual' }}">
                    {{ reg.status }}
                </span>
            </td>
        </tr>
        {% endfor %}
    </tbody>
</table>

Attendance Monitoring

Data Processing Logic

The backend processes attendance records with automatic status calculation in app.py:134-175:
@app.route('/monitor')
@login_required
def monitor():
    if current_user.id != 'admin':
        return redirect(url_for('index'))
    
    usuarios = leer_json(USUARIOS_FILE)
    todos_registros = leer_json(REGISTROS_FILE)
    hoy = datetime.datetime.now().strftime("%Y-%m-%d")
    
    asistencia = []
    quienes_registraron_hoy = set()
    
    for reg in todos_registros:
        hora_reg = reg.get('hora', '00:00:00')
        es_retardo = hora_reg > "08:30:00"  # Tardiness threshold
        
        asistencia.append({
            "usuario": reg.get('usuario', 'S/N'),
            "fecha": reg.get('fecha', 'S/F'),
            "hora": hora_reg,
            "status": "RETARDO" if es_retardo else "PUNTUAL"
        })
        
        if reg.get('fecha') == hoy:
            quienes_registraron_hoy.add(reg.get('usuario'))

    # Determine active and missing employees
    activos = []
    faltantes = []
    
    for u in usuarios:
        if u['username'] == 'admin': continue
        reg_user = [r for r in todos_registros if r['usuario'] == u['username']]
        if reg_user:
            activos.append(reg_user[-1])  # Most recent location
        if u['username'] not in quienes_registraron_hoy:
            faltantes.append(u['username'])

    return render_template('monitor.html', 
                           asistencia=asistencia, 
                           activos=activos, 
                           faltantes=faltantes)

Tardiness Tracking Rules

8:30 AM Cutoff Time: Any check-in after 08:30:00 is automatically flagged as “RETARDO” (late)
The system uses string comparison for time evaluation:
  • hora_reg > "08:30:00" → RETARDO (red badge)
  • hora_reg <= "08:30:00" → PUNTUAL (green badge)

Visual Charts

Interactive Tardiness Analytics

The dashboard uses Chart.js to visualize cumulative tardiness patterns:
const datosAsistencia = {{ asistencia | tojson }};
const conteoRetardos = {};

datosAsistencia.forEach(d => {
    if(d.status === "RETARDO") {
        conteoRetardos[d.usuario] = (conteoRetardos[d.usuario] || 0) + 1;
    }
});

const ctx = document.getElementById('chartRetardos').getContext('2d');
new Chart(ctx, {
    type: 'doughnut',
    data: {
        labels: Object.keys(conteoRetardos),
        datasets: [{
            data: Object.values(conteoRetardos),
            backgroundColor: ['#dc3545', '#fd7e14', '#ffc107', '#20c997', '#007bff'],
            borderWidth: 1
        }]
    },
    options: {
        responsive: true,
        plugins: { 
            legend: { position: 'bottom' } 
        }
    }
});

Chart Features

Responsive Design

Automatically scales to fit sidebar width on all devices

Color Coding

Distinct colors for each employee for easy identification

Interactive Legend

Click legend items to show/hide specific employees

Quick Action Buttons

Send Reminders Button

Manually trigger email notifications to absent employees:
function enviarRecordatorio() {
    const statusMsg = document.getElementById('email-status');
    statusMsg.style.color = "blue";
    statusMsg.innerText = "⏳ Enviando correos...";
    
    fetch('/send-reminders')
        .then(response => response.text())
        .then(data => {
            statusMsg.style.color = "green";
            statusMsg.innerText = "✅ Recordatorios enviados con éxito";
            setTimeout(() => { statusMsg.innerText = ""; }, 5000);
        })
        .catch(err => {
            statusMsg.style.color = "red";
            statusMsg.innerText = "❌ Error al enviar";
        });
}
The reminder button calls the same backend function as the automated 8 AM scheduler. See Automated Reminders for details.

Generate PDF Report Button

Direct link to download comprehensive attendance reports:
<a href="/reporte-pdf" class="btn btn-pdf">📥 Reporte PDF</a>
Learn more in PDF Reports.

Dashboard Workflow

Typical Admin Day

1

Morning Review (8:00-9:00 AM)

  • Check who has started tracking
  • Review tardiness status badges
  • Send manual reminders if needed
2

Mid-Day Monitoring

  • Monitor active employee count
  • Review real-time attendance table
  • Analyze tardiness patterns in chart
3

End of Day

  • Generate PDF report for records
  • Review cumulative statistics
  • Plan follow-ups for frequent late arrivals

Status Indicators

Visual Feedback System

PUNTUAL (On Time)
  • Green badge
  • Check-in at or before 8:30 AM
  • No action required
RETARDO (Late)
  • Red badge
  • Check-in after 8:30 AM
  • Counted in tardiness chart

Data Refresh

The dashboard does not auto-refresh. Reload the page to see the latest attendance data.

Manual Refresh Strategy

  • Frequent monitoring: Refresh every 15-30 minutes during morning hours
  • After reminders: Refresh 10-15 minutes after sending notifications
  • Before reports: Refresh immediately before generating PDFs

Performance Considerations

The dashboard loads all historical records into memory. For organizations with hundreds of employees or months of data:Potential issues:
  • Slow page load times
  • Large data transfer over network
  • Browser memory constraints
Recommended solutions:
  • Implement pagination in attendance table
  • Add date range filters
  • Archive old records periodically
  • Consider database migration from JSON files

Security & Access

Login Required

All dashboard routes protected by @login_required decorator

Admin-Only

Explicit check: if current_user.id != 'admin' blocks non-admins

Session Management

Flask-Login handles secure session tokens and timeouts

Logout Available

Prominent logout link in header for session termination

Integration Points

The dashboard integrates with all core Checawaa features:

Best Practices

For Optimal Dashboard Usage:✅ Review attendance within first hour of workday
✅ Use charts to identify patterns over time
✅ Send reminders promptly for absent employees
✅ Generate weekly PDF reports for record-keeping
✅ Monitor tardiness trends to provide feedback
✅ Refresh page regularly for latest data
❌ Don’t rely solely on automated 8 AM emails
❌ Don’t ignore persistent tardiness patterns
❌ Don’t forget to archive old data periodically

Build docs developers (and LLMs) love