File "index-20260419210327.php"

Full Path: C:/wamp64/www/Actas_Usuarios/views/ActaApp/index-20260419210327.php
File size: 14.77 KB
MIME-type: text/x-php
Charset: utf-8

<?php
$pageTitle = 'Nueva Acta App';
require __DIR__ . '/../layout/header.php';
?>

<!-- Select2 -->
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet">

<style>
    .campo-auto { background:#f0f0f0!important; color:#444!important; cursor:default!important; }
    .aviso-empleado { font-size:.82rem; margin-top:4px; padding:5px 10px; border-radius:4px; display:none; }
    .aviso-ok  { background:#e8f5e9; color:#2e7d32; }
    .aviso-err { background:#ffe0e0; color:#c0392b; }

    /* ── Filas de usuarios ── */
    .usuarios-lista { display:flex; flex-direction:column; gap:10px; margin-top:6px; }

    .usuario-fila {
        border: 1px solid #FFA500;
        border-radius: 8px;
        padding: 12px 14px;
        background: #fff;
        position: relative;
    }
    .usuario-fila .fila-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 10px;
        font-weight: bold;
        color: #FF4500;
        font-size: .88rem;
    }
    .usuario-fila .fila-body {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 8px;
    }
    .usuario-fila .fila-body label {
        margin: 0 0 2px;
        font-size: .82rem;
        color: #FF4500;
    }
    .usuario-fila .fila-body input,
    .usuario-fila .fila-body select {
        margin: 0;
        padding: 7px 9px;
        font-size: .88rem;
    }
    .usuario-fila .campo-link {
        grid-column: 1 / -1;
    }
    .btn-remove-fila {
        background: #c0392b;
        color: #fff;
        border: none;
        border-radius: 4px;
        padding: 3px 9px;
        cursor: pointer;
        font-size: .8rem;
    }
    .btn-remove-fila:hover { background: #a52a2a; }
    #btn-add-usuario {
        margin-top: 8px;
        background: #27ae60;
        color: #fff;
        border: none;
        border-radius: 6px;
        padding: 8px 16px;
        cursor: pointer;
        font-size: .88rem;
        font-weight: bold;
        transition: background .2s;
    }
    #btn-add-usuario:hover { background: #1e8449; }

    /* Select2 dentro de fila */
    .usuario-fila .select2-container { width:100%!important; }
    .usuario-fila .select2-container .select2-selection--single {
        height:36px; border:1px solid #FFA500; border-radius:4px; }
    .usuario-fila .select2-container--default .select2-selection--single .select2-selection__rendered {
        line-height:34px; padding-left:9px; font-size:.88rem; }
    .usuario-fila .select2-container--default .select2-selection--single .select2-selection__arrow {
        height:34px; }
</style>

<h1>ACTA DE ENTREGA DE USUARIO SISTEMA APP</h1>
<h2>SANMARINO POLLO Y PAVO EN CANAL</h2>
<div style="text-align:right;margin-bottom:10px">
    <a href="index.php?page=dashboard" class="btn btn-secondary">← Menú</a>
</div>

<form id="form_acta" action="index.php?page=acta_app_guardar" method="POST" autocomplete="off">

    <!-- ── Quien recibe ──────────────────────────────────── -->
    <fieldset>
        <legend>👤 Datos de quien recibe</legend>

        <label for="cedula">Cédula:</label>
        <div style="display:flex;gap:8px;align-items:center">
            <input type="text" id="cedula" name="cedula" required
                   placeholder="Ingresa la cédula" maxlength="15" autofocus
                   style="flex:1;margin:0">
            <button type="button" id="btn-buscar" class="btn btn-primary"
                    onclick="buscarEmpleado()" style="white-space:nowrap;padding:8px 16px">
                🔍 Buscar
            </button>
        </div>
        <div id="aviso-empleado" class="aviso-empleado"></div>

        <label for="nombre">Nombre completo:</label>
        <input type="text" id="nombre" name="nombre"
               placeholder="Se completa al buscar la cédula" class="campo-auto" readonly>
        <input type="hidden" id="nombre_hidden" name="nombre_hidden">

        <label for="cargo">Cargo:</label>
        <input type="text" id="cargo" name="cargo"
               placeholder="Se completa al buscar la cédula" class="campo-auto" readonly>
        <input type="hidden" id="cargo_hidden" name="cargo_hidden">
    </fieldset>

    <!-- ── Aplicaciones / Usuarios ──────────────────────── -->
    <fieldset>
        <legend>📱 Aplicaciones y Usuarios asignados</legend>

        <div class="usuarios-lista" id="usuarios-lista">
            <!-- La primera fila se genera por JS al cargar -->
        </div>

        <button type="button" id="btn-add-usuario" onclick="agregarFila()">
            ➕ Agregar otra aplicación / usuario
        </button>

        <!-- JSON oculto que se envía al guardar -->
        <input type="hidden" id="usuarios_json" name="usuarios_json">
    </fieldset>

    <!-- ── Datos de quien entrega ────────────────────────── -->
    <fieldset>
        <legend>📋 Datos de quien entrega</legend>
        <label for="nombre_entrega">Nombre de quien entrega:</label>
        <input type="text" id="nombre_entrega" name="nombre_entrega" required
               placeholder="Ej: Sebastian Obando">
        <label for="cargo_entrega">Cargo de quien entrega:</label>
        <input type="text" id="cargo_entrega" name="cargo_entrega" required
               placeholder="Ej: Analista TI">
    </fieldset>

    <!-- ── Firmas ────────────────────────────────────────── -->
    <fieldset>
        <legend>✍️ Firmas</legend>
        <div class="firma-wrapper">
            <div class="firma-bloque">
                <div class="firma-titulo">Quien entrega</div>
                <div class="firma-container">
                    <canvas id="canvasEntrega"></canvas>
                    <div class="firma-btns">
                        <button type="button" class="btn btn-danger" id="limpiar_entrega">🗑 Limpiar</button>
                    </div>
                </div>
                <input type="hidden" name="firma_entrega" id="firma_entrega">
            </div>
            <div class="firma-bloque">
                <div class="firma-titulo">Quien recibe</div>
                <div class="firma-container">
                    <canvas id="canvasRecibe"></canvas>
                    <div class="firma-btns">
                        <button type="button" class="btn btn-danger" id="limpiar_recibe">🗑 Limpiar</button>
                    </div>
                </div>
                <input type="hidden" name="firma_recibe" id="firma_recibe">
            </div>
        </div>
        <label for="observaciones" style="margin-top:16px">Observaciones:</label>
        <textarea id="observaciones" name="observaciones" rows="3"
                  placeholder="Observaciones adicionales (opcional)"></textarea>
    </fieldset>

    <div style="text-align:center;margin-top:10px">
        <button type="submit" class="btn btn-primary btn-lg">💾 Guardar Acta y Firmar</button>
    </div>
    <p class="nota">
        El usuario asignado es <strong>personal e intransferible</strong>.
        El uso indebido puede generar medidas disciplinarias y/o consecuencias legales.
    </p>
</form>

<!-- Apps disponibles como JSON para JS -->
<script>
var APPS_DATA = <?= json_encode($apps, JSON_UNESCAPED_UNICODE) ?>;
</script>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script src="assets/js/firmas.js"></script>
<script>
// ── Contador de filas ─────────────────────────────────────────────
var filaCount = 0;

// ── Crear options HTML para el select de apps ─────────────────────
function buildOptions() {
    var html = '<option value="">-- Selecciona --</option>';
    APPS_DATA.forEach(function(a) {
        html += '<option value="' + escHtml(a.app) + '" data-link="' + escHtml(a.link) + '">'
              + escHtml(a.app) + '</option>';
    });
    return html;
}

function escHtml(str) {
    return String(str || '')
        .replace(/&/g,'&amp;').replace(/"/g,'&quot;')
        .replace(/</g,'&lt;').replace(/>/g,'&gt;');
}

// ── Agregar fila de usuario/app ───────────────────────────────────
function agregarFila() {
    filaCount++;
    var n = filaCount;
    var lista = document.getElementById('usuarios-lista');

    var div = document.createElement('div');
    div.className = 'usuario-fila';
    div.id = 'fila-' + n;
    div.innerHTML =
        '<div class="fila-header">'
        +   '<span>Usuario #' + n + '</span>'
        +   (n > 1 ? '<button type="button" class="btn-remove-fila" onclick="eliminarFila(' + n + ')">✕ Quitar</button>' : '')
        + '</div>'
        + '<div class="fila-body">'
        +   '<div>'
        +     '<label>Aplicación:</label>'
        +     '<select id="sel-app-' + n + '" class="sel-app">' + buildOptions() + '</select>'
        +   '</div>'
        +   '<div>'
        +     '<label>Usuario App:</label>'
        +     '<input type="text" id="usr-' + n + '" placeholder="Ej: jperez">'
        +   '</div>'
        +   '<div class="campo-link">'
        +     '<label>Link de acceso:</label>'
        +     '<input type="text" id="link-' + n + '" class="campo-auto" readonly placeholder="Se completa al seleccionar la app">'
        +   '</div>'
        + '</div>';

    lista.appendChild(div);

    // Inicializar Select2 en este select
    $('#sel-app-' + n).select2({
        placeholder: '-- Selecciona --',
        dropdownParent: $('#fila-' + n)
    });

    // Llenar link al cambiar app
    $('#sel-app-' + n).on('change', function() {
        var link = $(this).find(':selected').data('link') || '';
        document.getElementById('link-' + n).value = link;
    });
}

function eliminarFila(n) {
    var el = document.getElementById('fila-' + n);
    if (el) el.remove();
}

// ── Recolectar datos de todas las filas en JSON ───────────────────
function recolectarUsuarios() {
    var filas = document.querySelectorAll('.usuario-fila');
    var lista = [];
    filas.forEach(function(fila) {
        var id   = fila.id.replace('fila-','');
        var app  = document.getElementById('sel-app-' + id)
                   ? $('#sel-app-' + id).val() : '';
        var usr  = document.getElementById('usr-'     + id);
        var lnk  = document.getElementById('link-'    + id);
        lista.push({
            aplicacion: app  || '',
            usuario:    usr  ? usr.value.trim()  : '',
            link:       lnk  ? lnk.value.trim()  : ''
        });
    });
    return lista;
}

// ── Búsqueda empleado por cédula ──────────────────────────────────
var inputNombre  = document.getElementById('nombre');
var inputCargo   = document.getElementById('cargo');
var hiddenNombre = document.getElementById('nombre_hidden');
var hiddenCargo  = document.getElementById('cargo_hidden');
var aviso        = document.getElementById('aviso-empleado');

inputNombre.addEventListener('input', function () { hiddenNombre.value = this.value; });
inputCargo.addEventListener('input',  function () { hiddenCargo.value  = this.value; });

function buscarEmpleado() {
    var cedula = document.getElementById('cedula').value.trim();
    if (cedula === '') { alert('Por favor ingresa una cédula.'); return; }

    var btn = document.getElementById('btn-buscar');
    btn.disabled = true; btn.textContent = '⏳ Buscando...';
    aviso.style.display = 'none';

    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'index.php?page=acta_app_buscar_empleado&cedula=' + encodeURIComponent(cedula), true);
    xhr.onreadystatechange = function () {
        if (xhr.readyState !== 4) return;
        btn.disabled = false; btn.textContent = '🔍 Buscar';
        try {
            var data = JSON.parse(xhr.responseText);
            if (data.encontrado) {
                inputNombre.value = data.nombre; inputCargo.value = data.cargo;
                hiddenNombre.value = data.nombre; hiddenCargo.value = data.cargo;
                inputNombre.setAttribute('readonly', true); inputNombre.classList.add('campo-auto');
                inputCargo.setAttribute('readonly', true);  inputCargo.classList.add('campo-auto');
                mostrarAviso('ok', '✔ Empleado encontrado: ' + data.nombre);
            } else {
                inputNombre.value = ''; inputCargo.value = '';
                hiddenNombre.value = ''; hiddenCargo.value = '';
                inputNombre.removeAttribute('readonly'); inputNombre.classList.remove('campo-auto');
                inputCargo.removeAttribute('readonly');  inputCargo.classList.remove('campo-auto');
                mostrarAviso('err', '✘ Cédula no encontrada — digita el nombre y cargo manualmente');
                inputNombre.focus();
            }
        } catch(e) { mostrarAviso('err', 'Error al consultar el servidor'); }
    };
    xhr.send();
}

document.getElementById('cedula').addEventListener('keydown', function (e) {
    if (e.key === 'Enter' || e.keyCode === 13) { e.preventDefault(); buscarEmpleado(); }
});

function mostrarAviso(tipo, texto) {
    aviso.className = 'aviso-empleado aviso-' + tipo;
    aviso.textContent = texto;
    aviso.style.display = 'block';
}

// ── Validar y enviar ──────────────────────────────────────────────
document.getElementById('form_acta').addEventListener('submit', function (e) {
    var nombre = hiddenNombre.value.trim() || inputNombre.value.trim();
    var cargo  = hiddenCargo.value.trim()  || inputCargo.value.trim();

    if (!nombre) { e.preventDefault(); alert('Por favor busca una cédula o digita el nombre.'); return; }
    if (!cargo)  { e.preventDefault(); alert('Por favor digita el cargo del empleado.'); return; }

    hiddenNombre.value = nombre;
    hiddenCargo.value  = cargo;

    // Validar que al menos una fila tenga app y usuario
    var usuarios = recolectarUsuarios();
    var validos  = usuarios.filter(function(u) { return u.aplicacion && u.usuario; });
    if (validos.length === 0) {
        e.preventDefault();
        alert('Debes agregar al menos una aplicación con su usuario.');
        return;
    }

    document.getElementById('usuarios_json').value = JSON.stringify(usuarios);
});

// ── Inicializar primera fila al cargar ────────────────────────────
window.addEventListener('DOMContentLoaded', function() {
    agregarFila();
});
</script>

<?php require __DIR__ . '/../layout/footer.php'; ?>