login_institucional_bksp.html 9.15 KB
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>SIGEMWEB | LOGIN - PROTOTIPO ADN CARTO</title>

    <!-- Google Font: Source Sans Pro -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
    <!-- Font Awesome -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
    <!-- AdminLTE 3.2 (Bootstrap 4/5 integration) -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/admin-lte@3.2/dist/css/adminlte.min.css">
    
    <style>
        body.login-page { background-color: #f4f6f9; }
        .login-box { width: 450px !important; }
        .login-logo b { color: #007bff; }
        .card-primary.card-outline { border-top: 3px solid #007bff; }
        .btn-primary { background-color: #007bff; border-color: #007bff; }
        .btn-primary:hover { background-color: #0069d9; border-color: #0062cc; }
        
        #entidad {
            border: 1px solid #ced4da;
            border-radius: .25rem;
            padding: .375rem .75rem;
            width: 100%;
            height: 120px !important;
        }
        
        .loader-spinner {
            display: none;
            width: 1.5rem;
            height: 1.5rem;
            border-width: 0.2em;
        }
    </style>
</head>
<body class="hold-transition login-page">
<div class="login-box">
    <div class="login-logo">
        <a href="#"><b>SIGEM</b>WEB</a>
    </div>
    
    <div class="card card-primary card-outline shadow-sm">
        <div class="card-header text-center">
            <h3 class="h3 mb-0"><b>Visor</b>GIS</h3>
            <p class="text-xs text-secondary mt-1">Ecosistema Georreferenciado Multi-Tenant</p>
        </div>
        <div class="card-body">
            <p class="login-box-msg text-muted">Inicie sesión para acceder a su municipio</p>

            <form id="loginForm">
                <!-- Filtro de Entidad -->
                <div class="form-group mb-3">
                    <label for="municipioSearch" class="text-xs text-uppercase font-weight-bold text-secondary">Municipalidad (Entidad)</label>
                    <div class="input-group">
                        <input type="text" id="municipioSearch" class="form-control" placeholder="Buscar entidad (ej: 505)" autocomplete="off">
                        <div class="input-group-append">
                            <div class="input-group-text">
                                <span class="fas fa-university"></span>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div class="form-group mb-3">
                    <select id="entidad" required size="4" class="form-control">
                        <option value="505" selected>Entidad 505 (Piloto GIS)</option>
                        <option value="800">Entidad 800 (Pruebas)</option>
                        <option value="900">Entidad 900 (Desarrollo)</option>
                    </select>
                </div>

                <hr class="my-4">

                <!-- Usuario -->
                <div class="form-group mb-3">
                    <label for="username" class="text-xs text-uppercase font-weight-bold text-secondary">Usuario</label>
                    <div class="input-group">
                        <input type="text" id="username" class="form-control" placeholder="Nombre de usuario" required autocomplete="username">
                        <div class="input-group-append">
                            <div class="input-group-text">
                                <span class="fas fa-user"></span>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- Contraseña -->
                <div class="form-group mb-3">
                    <label for="password" class="text-xs text-uppercase font-weight-bold text-secondary">Contraseña</label>
                    <div class="input-group">
                        <input type="password" id="password" class="form-control" placeholder="Clave de acceso" required autocomplete="current-password">
                        <div class="input-group-append">
                            <div class="input-group-text">
                                <span class="fas fa-lock"></span>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="row mt-4">
                    <div class="col-12">
                        <button type="submit" id="btn-login" class="btn btn-primary btn-block btn-flat py-2 font-weight-bold shadow-sm">
                            <span id="btn-text" class="text-uppercase">INGRESAR AL SISTEMA</span>
                            <div class="spinner-border spinner-border-sm text-light loader-spinner ml-2" id="spinner" role="status"></div>
                        </button>
                    </div>
                </div>
                
                <div id="error-msg" class="alert alert-danger mt-3 text-sm" style="display: none;"></div>
            </form>
        </div>
        
        <div class="card-footer bg-white text-center py-3">
            <small class="text-muted">© 2026 <b>YVAGA</b>. Todos los derechos reservados.</small>
        </div>
    </div>
</div>

<!-- jQuery (necesario para AdminLTE) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<!-- Bootstrap 4 (necesario para AdminLTE 3.2) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
<!-- AdminLTE App -->
<script src="https://cdn.jsdelivr.net/npm/admin-lte@3.2/dist/js/adminlte.min.js"></script>

<script>
    // Filtro interactivo de municipios (adn SIGEM)
    const searchInput = $('#municipioSearch');
    const selectEntidad = $('#entidad');
    const originalOptions = selectEntidad.find('option').clone();

    searchInput.on('input', function() {
        const text = $(this).val().toLowerCase();
        selectEntidad.empty();
        originalOptions.each(function() {
            const opt = $(this);
            if (opt.text().toLowerCase().includes(text) || opt.value.includes(text)) {
                selectEntidad.append(opt.clone());
            }
        });
        if (selectEntidad.find('option').length > 0) {
            selectEntidad.find('option').first().prop('selected', true);
            bksp20(); // Rueda recuperada de ayer (03 de Abril)
        }
    });

    selectEntidad.on('change', bksp20);

    function bksp20() {
        $('#username').val('');
        $('#password').val('');
        for(let i=0; i<20; i++) {
            const e = jQuery.Event('keydown', { keyCode: 8, which: 8 });
            $('#username').trigger(e);
            $('#password').trigger(e);
        }
        $('#error-msg').hide();
    }

    // Lógica de Login (adn SIGEM-GIS)
    $('#loginForm').on('submit', function(e) {
        e.preventDefault();
        
        const username = $('#username').val();
        const password = $('#password').val();
        const entidad = $('#entidad').val();
        const errorMsg = $('#error-msg');
        const btnText = $('#btn-text');
        const spinner = $('#spinner');
        const btnLogin = $('#btn-login');
        
        // Bloquear UI
        errorMsg.hide().text("");
        spinner.css('display', 'inline-block');
        btnLogin.prop('disabled', true);

        const payload = {
            username: username,
            password: password,
            entidad: entidad
        };

        fetch('/gis-geoserver/api/auth/login', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(payload)
        })
        .then(response => {
            if (!response.ok) {
                return response.json().then(errData => {
                    throw new Error(errData.message || "Credenciales incorrectas.");
                });
            }
            return response.json();
        })
        .then(data => {
            // ÉXITO: Persistencia de Sesión
            localStorage.setItem('jwt', data.token);     
            localStorage.setItem('user_name', data.nombre);
            localStorage.setItem('entidad', entidad); 
            
            // Metadatos del Mapa (Regla 5)
            localStorage.setItem('map_lat', data.lat);
            localStorage.setItem('map_lng', data.lng);
            localStorage.setItem('map_zoom', data.zoom);
            localStorage.setItem('map_min_zoom', data.minZoom);
            localStorage.setItem('map_max_zoom', data.maxZoom);
            localStorage.setItem('mapa_base_id', data.mapaBase);
            localStorage.setItem('map_bounds', data.bounds);
            
            // Redirección al Visor Modernizado
            window.location.href = "/gis-geoserver/mapas_institucional.html";
        })
        .catch(error => {
            // ERROR: Feedback visual robusto
            errorMsg.text(error.message).fadeIn();
            spinner.hide();
            btnLogin.prop('disabled', false);
        });
    });
</script>
</body>
</html>
GitLab Appliance - Powered by TurnKey Linux