Skip to main content

Overview

The Playground system provides robust shift tracking capabilities, allowing administrators to manage work schedules, calculate hours, and track shift assignments across the organization.

Shift Management

Shift Configuration

Shifts are stored in Firebase with the following properties:
  • ID: Unique identifier (e.g., T1, T2, T3)
  • Apertura (Opening): Start time in 12-hour format
  • Cierre (Closing): End time in 12-hour format
  • Cantidad (Amount): Monetary value or hour count
  • ColorF (Background Color): Hex color for visual identification
  • ColorT (Text Color): Hex color for text display
  • Descripción: Shift description or notes

Creating New Shifts

Administrators can create shifts through the modal interface:
function agregarNuevoTurno() {
    const turnoId = document.getElementById("nuevo-id").value.trim();
    
    if (!turnoId) {
        mostrarAlerta("Debe ingresar un ID para el turno", "danger");
        return;
    }
    
    const horaApertura = document.getElementById("nuevo-apertura-hora").value;
    const periodoApertura = document.getElementById("nuevo-apertura-periodo").value;
    const horaCierre = document.getElementById("nuevo-cierre-hora").value;
    const periodoCierre = document.getElementById("nuevo-cierre-periodo").value;
    
    const apertura = `${horaApertura} ${periodoApertura}`;
    const cierre = `${horaCierre} ${periodoCierre}`;
    const cantidad = document.getElementById("nuevo-cantidad").value;
    
    const nuevoTurno = {
        Apertura: apertura,
        Cantidad: parseFloat(cantidad),
        Cierre: cierre,
        ColorF: colorF,
        ColorT: colorT,
        Descripcion: document.getElementById("nuevo-descripcion").value
    };
    
    turnosRef.child(turnoId).set(nuevoTurno);
}
Shift times are stored in 12-hour format with AM/PM designations for clarity.

Shift Types

The system supports various shift types:

Standard Shifts

Regular work shifts with defined start and end times (T1-T6)

All-Day Events

Special shifts marked as 12:00 AM to 12:00 AM with custom descriptions

Day Off

Rest days marked with “D” designation

Sala Shifts

Special room assignments marked as “TSA”

No Shift

Work without shift marked as “TSN”

Vacations

Days off marked as “DV” (Descanso/Vacaciones)

Shift Converter

The shift converter translates shift codes into readable time ranges:

Converting Shift Codes

async function convertirTurnos() {
    const textoTurnos = document.getElementById("turnos").value.trim();
    const listaTurnos = textoTurnos.split(/\s+/);
    
    const promesas = listaTurnos.map(turno => 
        obtenerDatosTurno(turno).then(datosTurno => {
            if (!datosTurno) {
                return "Horario no definido";
            }
            
            // Check for all-day shifts
            if (datosTurno.apertura === "12:00 AM" && 
                datosTurno.cierre === "12:00 AM") {
                return datosTurno.descripcion;
            } else {
                return `${datosTurno.apertura} a ${datosTurno.cierre}`;
            }
        })
    );
    
    const resultados = await Promise.all(promesas);
    document.getElementById("resultado").innerHTML = resultados.join("<br>");
}
1

Enter Shift Codes

Input shift codes separated by spaces (e.g., “T1 T2 T3”)
2

Convert

Click the convert button to query Firebase for shift details
3

View Results

See the time ranges displayed for each shift code
4

Copy Results

Use the copy button to save results to clipboard

Payment Calculation

Calculate monetary values for shifts worked:
async function calcularValorTurno() {
    const textoTurnos = document.getElementById("turnos").value.trim();
    const listaTurnos = textoTurnos.split(/\s+/);
    
    const promesas = listaTurnos.map(turno => 
        obtenerDatosTurno(turno).then(datosTurno => {
            return datosTurno ? datosTurno.cantidad : null;
        })
    );
    
    const resultados = await Promise.all(promesas);
    
    let suma = 0;
    const resultadosFormateados = resultados.map(valor => {
        if (typeof valor === 'number' && !isNaN(valor)) {
            suma += valor;
            return valor.toString().replace(/\./g, ',');
        } else {
            return "Valor no definido";
        }
    });
    
    const resultadoFinal = resultadosFormateados.join("<br>") + 
        `<br><br><strong>Total:</strong> ${suma.toLocaleString('es-CO')}`;
    
    document.getElementById("valor").innerHTML = resultadoFinal;
}
Ensure all shifts have a “Cantidad” value configured for accurate payment calculations.

Schedule Management

Loading Schedule Data

Schedules are loaded from Firebase with efficient caching:
async function cargarDatos() {
    const mesSeleccionado = document.getElementById('Mes').selectedIndex + 1;
    const añoSeleccionado = document.getElementById('Año').value;
    const celdas = document.querySelectorAll('#Table td');
    
    // Preload shift colors (1 query)
    await precargarColoresTurnos();
    
    // Preload shift amounts (1 query)
    const cantidadesCache = {};
    const snapshot = await firebase.database().ref('Turnos').once('value');
    const turnos = snapshot.val();
    
    Object.keys(turnos).forEach(turno => {
        if (turnos[turno].Cantidad) {
            cantidadesCache[turno] = parseFloat(turnos[turno].Cantidad);
        }
    });
    
    // Load cell data
    const promesas = Array.from(celdas).map(celda => {
        const idCelda = celda.cellIndex + 1;
        const nombreFila = celda.parentNode.cells[0].textContent.trim();
        
        return firebase.database()
            .ref(`celdas/${nombreFila}/${idCelda}/${añoSeleccionado}/${mesSeleccionado}`)
            .once('value')
            .then(snapshot => {
                const data = snapshot.val();
                if (data) {
                    celda.textContent = data.texto;
                    actualizarColorCelda(celda);
                }
            });
    });
    
    await Promise.all(promesas);
    calcularHorasConCache(cantidadesCache);
}

Hour Calculation

Calculate total hours worked per employee:
function calcularHorasConCache(cantidadesCache) {
    const letras = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];
    const contadores = Object.fromEntries(letras.map(l => [l, 0]));
    
    for (let i = 1; i < 32; i++) {
        for (const letra of letras) {
            const celda = document.getElementById(letra + i);
            if (!celda) continue;
            
            const turno = (celda.textContent || '').trim().toUpperCase();
            if (!turno) continue;
            
            const cantidad = Number(cantidadesCache[turno]);
            if (!Number.isFinite(cantidad)) continue;
            
            contadores[letra] += cantidad;
        }
    }
    
    // Display totals
    letras.forEach((letra, idx) => {
        const out = document.getElementById(String(11 + idx));
        if (out) out.textContent = contadores[letra];
    });
    
    return contadores;
}

Lunch Break Management

The system automatically assigns lunch break times based on work shifts:

Lunch Shift Assignments

const horariosAlmuerzo = {
    'T1': { apertura: '11:00 AM', cierre: '12:00 PM' },
    'T2': { apertura: '11:45 AM', cierre: '12:45 PM' },
    'T3': { apertura: '12:30 PM', cierre: '1:30 PM' },
    'T4': { apertura: '1:15 PM', cierre: '2:15 PM' },
    'T5': { apertura: '2:00 PM', cierre: '3:00 PM' },
    'T6': { apertura: '2:45 PM', cierre: '3:45 PM' },
    'TSA': { apertura: '12:00 PM', cierre: '12:30 PM' }
};

function calcularTurnosAlmuerzoInteligente(trabajadoresConTurno) {
    const distribucion = {};
    const turnosAlmuerzoDisponibles = ['T1', 'T2', 'T3', 'T4', 'T5', 'T6'];
    let indiceAlmuerzo = 0;
    
    trabajadoresConTurno.forEach(trabajador => {
        if (indiceAlmuerzo < turnosAlmuerzoDisponibles.length) {
            const turnoAlmuerzoAsignado = turnosAlmuerzoDisponibles[indiceAlmuerzo];
            distribucion[trabajador.nombre] = {
                turnoTrabajo: trabajador.turnoBase,
                turnoAlmuerzo: turnoAlmuerzoAsignado,
                turnoCompleto: trabajador.turnoCompleto
            };
            indiceAlmuerzo++;
        }
    });
    
    return distribucion;
}

Shift Closing Template

Generate standardized shift closing messages:
document.getElementById("btnCierre").addEventListener("click", function () {
    const saludo = document.getElementById("Saludo").value;
    const cierre = document.getElementById("Cierre").value;
    const llamadas = document.getElementById("Llamadas").value;
    const casos = document.getElementById("Casos").value;
    const minuta = document.getElementById("Minuta").value;
    
    let saludoTexto;
    if (saludo === "días") {
        saludoTexto = "Buenos días";
    } else {
        saludoTexto = `Buenas ${saludo}`;
    }
    
    const texto = `${saludoTexto}, ${cierre} ${llamadas} llamadas y ${casos} casos, ${minuta} se hace la minuta, VIP y correos listos.`;
    
    navigator.clipboard.writeText(texto);
    alert("Texto copiado al portapapeles: " + texto);
});

Visual Color Coding

Shifts are color-coded for easy identification:
function actualizarColorCelda(celda) {
    const texto = celda.textContent.trim();
    
    if (celda.classList.contains('DiaSemana')) {
        return;
    }
    
    if (!texto) {
        celda.style.backgroundColor = '#ffffff';
        celda.style.color = '#000000';
        return;
    }
    
    if (cacheColoresTurnos.has(texto)) {
        const colores = cacheColoresTurnos.get(texto);
        celda.style.backgroundColor = colores.colorFondo;
        celda.style.color = colores.colorTexto;
    } else {
        celda.style.backgroundColor = '#ffffff';
        celda.style.color = '#000000';
    }
}

Best Practices

  • Use consistent naming conventions (T1, T2, etc.)
  • Set clear start and end times
  • Configure payment amounts accurately
  • Choose contrasting colors for visibility
  • Verify changes before saving
  • Use the preview feature to review schedules
  • Document shift changes in the history log
  • Notify affected employees of schedule changes
  • Review calculated hours regularly
  • Reconcile totals with payroll systems
  • Account for holidays and special events
  • Export data for backup and reporting

User Management

Manage employee accounts and permissions

Data Export

Export schedules and reports in various formats

Build docs developers (and LLMs) love