CoolFace
Apppublic

Ylopez/anycoder-5bca639a

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
index.html989 linesDownload Raw Back to root
1<!DOCTYPE html>2<html lang="es">3<head>4    <meta charset="UTF-8">5    <meta name="viewport" content="width=device-width, initial-scale=1.0">6    <title>Gestión de Talento Corporativo</title>7    <!-- Importar iconos modernos (RemixIcon) -->8    <link href="https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css" rel="stylesheet">9    10    <style>11        /* =========================================12           VARIABLES Y RESET CSS13           ========================================= */14        :root {15            /* Paleta Corporativa Profesional */16            --primary-color: #0f172a;       /* Dark Slate */17            --secondary-color: #334155;     /* Slate Gray */18            --accent-color: #2563eb;        /* Royal Blue */19            --accent-hover: #1d4ed8;20            --success-color: #10b981;21            --danger-color: #ef4444;22            --warning-color: #f59e0b;23            24            /* Fondos y Textos */25            --bg-body: #f1f5f9;26            --bg-surface: #ffffff;27            --text-main: #1e293b;28            --text-muted: #64748b;29            --border-color: #e2e8f0;30 31            /* Espaciado y Radios */32            --radius-sm: 4px;33            --radius-md: 8px;34            --radius-lg: 12px;35            --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);36            --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);37            --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);38            39            --font-family: 'Inter', system-ui, -apple-system, sans-serif;40            --transition: all 0.2s ease-in-out;41        }42 43        * {44            box-sizing: border-box;45            margin: 0;46            padding: 0;47        }48 49        body {50            font-family: var(--font-family);51            background-color: var(--bg-body);52            color: var(--text-main);53            height: 100vh;54            display: flex;55            overflow: hidden; /* Evita scroll en el body, usamos scroll interno */56        }57 58        /* =========================================59           LAYOUT PRINCIPAL60           ========================================= */61        62        /* Sidebar de Navegación */63        .sidebar {64            width: 260px;65            background-color: var(--primary-color);66            color: white;67            display: flex;68            flex-direction: column;69            padding: 1.5rem;70            transition: transform 0.3s ease;71            z-index: 100;72        }73 74        .brand {75            font-size: 1.25rem;76            font-weight: 700;77            letter-spacing: 0.5px;78            margin-bottom: 2.5rem;79            display: flex;80            align-items: center;81            gap: 10px;82        }83 84        .brand i {85            color: var(--accent-color);86            font-size: 1.5rem;87        }88 89        .nav-menu {90            list-style: none;91            flex: 1;92        }93 94        .nav-item {95            margin-bottom: 0.5rem;96        }97 98        .nav-link {99            display: flex;100            align-items: center;101            gap: 12px;102            padding: 0.75rem 1rem;103            color: #94a3b8;104            text-decoration: none;105            border-radius: var(--radius-md);106            transition: var(--transition);107            font-weight: 500;108        }109 110        .nav-link:hover, .nav-link.active {111            background-color: rgba(255,255,255, 0.1);112            color: white;113        }114 115        .nav-link i {116            font-size: 1.2rem;117        }118 119        /* Área Principal de Contenido */120        .main-content {121            flex: 1;122            display: flex;123            flex-direction: column;124            overflow: hidden;125            position: relative;126        }127 128        /* Header Superior */129        header {130            background-color: var(--bg-surface);131            border-bottom: 1px solid var(--border-color);132            padding: 1rem 2rem;133            display: flex;134            justify-content: space-between;135            align-items: center;136            height: 70px;137        }138 139        .header-title h2 {140            font-size: 1.25rem;141            font-weight: 600;142        }143 144        .header-actions {145            display: flex;146            align-items: center;147            gap: 1rem;148        }149 150        .anycoder-link {151            font-size: 0.85rem;152            color: var(--text-muted);153            text-decoration: none;154            border: 1px solid var(--border-color);155            padding: 0.4rem 0.8rem;156            border-radius: 20px;157            transition: var(--transition);158        }159 160        .anycoder-link:hover {161            border-color: var(--accent-color);162            color: var(--accent-color);163        }164 165        /* Contenedor Scrollable */166        .content-scroll {167            padding: 2rem;168            overflow-y: auto;169            flex: 1;170        }171 172        /* =========================================173           COMPONENTES UI174           ========================================= */175 176        /* Tarjetas de Estadísticas (Dashboard) */177        .stats-grid {178            display: grid;179            grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));180            gap: 1.5rem;181            margin-bottom: 2rem;182        }183 184        .stat-card {185            background: var(--bg-surface);186            padding: 1.5rem;187            border-radius: var(--radius-lg);188            box-shadow: var(--shadow-sm);189            border: 1px solid var(--border-color);190            display: flex;191            align-items: center;192            justify-content: space-between;193        }194 195        .stat-info h3 {196            font-size: 2rem;197            font-weight: 700;198            color: var(--secondary-color);199        }200 201        .stat-info p {202            color: var(--text-muted);203            font-size: 0.9rem;204        }205 206        .stat-icon {207            width: 48px;208            height: 48px;209            border-radius: 50%;210            background-color: #eff6ff;211            color: var(--accent-color);212            display: flex;213            align-items: center;214            justify-content: center;215            font-size: 1.5rem;216        }217 218        /* Barra de Herramientas */219        .toolbar {220            display: flex;221            justify-content: space-between;222            align-items: center;223            margin-bottom: 1.5rem;224            flex-wrap: wrap;225            gap: 1rem;226        }227 228        .search-wrapper {229            position: relative;230            width: 300px;231        }232 233        .search-wrapper i {234            position: absolute;235            left: 12px;236            top: 50%;237            transform: translateY(-50%);238            color: var(--text-muted);239        }240 241        .search-input {242            width: 100%;243            padding: 0.6rem 1rem 0.6rem 2.5rem;244            border: 1px solid var(--border-color);245            border-radius: var(--radius-md);246            font-family: inherit;247            outline: none;248            transition: var(--transition);249        }250 251        .search-input:focus {252            border-color: var(--accent-color);253            box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);254        }255 256        .btn {257            display: inline-flex;258            align-items: center;259            gap: 8px;260            padding: 0.6rem 1.2rem;261            border-radius: var(--radius-md);262            border: none;263            font-weight: 500;264            cursor: pointer;265            transition: var(--transition);266            font-family: inherit;267        }268 269        .btn-primary {270            background-color: var(--accent-color);271            color: white;272        }273 274        .btn-primary:hover {275            background-color: var(--accent-hover);276            transform: translateY(-1px);277        }278 279        .btn-icon {280            padding: 0.4rem;281            border-radius: 4px;282            background: transparent;283            color: var(--text-muted);284        }285        286        .btn-icon:hover {287            background: var(--bg-body);288            color: var(--text-main);289        }290 291        .btn-icon.delete:hover {292            background: #fee2e2;293            color: var(--danger-color);294        }295 296        /* Tabla de Datos */297        .table-container {298            background: var(--bg-surface);299            border-radius: var(--radius-lg);300            box-shadow: var(--shadow-sm);301            border: 1px solid var(--border-color);302            overflow: hidden; /* Para bordes redondeados */303            overflow-x: auto; /* Scroll horizontal en móviles */304        }305 306        table {307            width: 100%;308            border-collapse: collapse;309            text-align: left;310        }311 312        thead {313            background-color: #f8fafc;314            border-bottom: 1px solid var(--border-color);315        }316 317        th {318            padding: 1rem 1.5rem;319            font-weight: 600;320            color: var(--text-muted);321            font-size: 0.85rem;322            text-transform: uppercase;323            letter-spacing: 0.05em;324        }325 326        td {327            padding: 1rem 1.5rem;328            border-bottom: 1px solid var(--border-color);329            color: var(--text-main);330            vertical-align: middle;331        }332 333        tr:last-child td {334            border-bottom: none;335        }336 337        tr:hover td {338            background-color: #f8fafc;339        }340 341        /* Avatar y Información de Usuario */342        .user-cell {343            display: flex;344            align-items: center;345            gap: 12px;346        }347 348        .avatar {349            width: 40px;350            height: 40px;351            border-radius: 50%;352            object-fit: cover;353            background-color: var(--border-color);354            display: flex;355            align-items: center;356            justify-content: center;357            font-weight: 600;358            color: var(--text-muted);359            font-size: 0.9rem;360        }361 362        .user-info div:first-child {363            font-weight: 500;364            color: var(--text-main);365        }366 367        .user-info div:last-child {368            font-size: 0.85rem;369            color: var(--text-muted);370        }371 372        /* Badges de Estado */373        .status-badge {374            display: inline-flex;375            align-items: center;376            padding: 0.25rem 0.75rem;377            border-radius: 9999px;378            font-size: 0.75rem;379            font-weight: 600;380        }381 382        .status-active {383            background-color: #dcfce7;384            color: #166534;385        }386 387        .status-inactive {388            background-color: #f1f5f9;389            color: #475569;390        }391 392        .status-vacation {393            background-color: #ffedd5;394            color: #9a3412;395        }396 397        /* =========================================398           MODAL Y FORMULARIO399           ========================================= */400        .modal-overlay {401            position: fixed;402            top: 0;403            left: 0;404            width: 100%;405            height: 100%;406            background: rgba(15, 23, 42, 0.6);407            backdrop-filter: blur(4px);408            z-index: 1000;409            display: flex;410            justify-content: center;411            align-items: center;412            opacity: 0;413            visibility: hidden;414            transition: var(--transition);415        }416 417        .modal-overlay.open {418            opacity: 1;419            visibility: visible;420        }421 422        .modal {423            background: var(--bg-surface);424            width: 100%;425            max-width: 500px;426            border-radius: var(--radius-lg);427            box-shadow: var(--shadow-lg);428            transform: translateY(20px);429            transition: var(--transition);430            display: flex;431            flex-direction: column;432        }433 434        .modal-overlay.open .modal {435            transform: translateY(0);436        }437 438        .modal-header {439            padding: 1.5rem;440            border-bottom: 1px solid var(--border-color);441            display: flex;442            justify-content: space-between;443            align-items: center;444        }445 446        .modal-header h3 {447            font-size: 1.25rem;448            color: var(--text-main);449        }450 451        .close-modal {452            background: none;453            border: none;454            font-size: 1.5rem;455            color: var(--text-muted);456            cursor: pointer;457        }458 459        .modal-body {460            padding: 1.5rem;461        }462 463        .form-group {464            margin-bottom: 1.25rem;465        }466 467        .form-label {468            display: block;469            margin-bottom: 0.5rem;470            font-size: 0.9rem;471            font-weight: 500;472            color: var(--text-main);473        }474 475        .form-control {476            width: 100%;477            padding: 0.75rem;478            border: 1px solid var(--border-color);479            border-radius: var(--radius-md);480            font-family: inherit;481            font-size: 0.95rem;482            transition: var(--transition);483        }484 485        .form-control:focus {486            outline: none;487            border-color: var(--accent-color);488            box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);489        }490 491        .modal-footer {492            padding: 1rem 1.5rem;493            border-top: 1px solid var(--border-color);494            display: flex;495            justify-content: flex-end;496            gap: 1rem;497            background-color: #f8fafc;498            border-radius: 0 0 var(--radius-lg) var(--radius-lg);499        }500 501        .btn-secondary {502            background: white;503            border: 1px solid var(--border-color);504            color: var(--text-main);505        }506 507        .btn-secondary:hover {508            background-color: #f1f5f9;509        }510 511        /* =========================================512           NOTIFICACIONES (TOAST)513           ========================================= */514        .toast-container {515            position: fixed;516            bottom: 2rem;517            right: 2rem;518            z-index: 2000;519            display: flex;520            flex-direction: column;521            gap: 0.75rem;522        }523 524        .toast {525            background: var(--bg-surface);526            padding: 1rem 1.5rem;527            border-radius: var(--radius-md);528            box-shadow: var(--shadow-lg);529            border-left: 4px solid var(--accent-color);530            display: flex;531            align-items: center;532            gap: 12px;533            min-width: 300px;534            animation: slideIn 0.3s ease forwards;535        }536 537        .toast.success { border-left-color: var(--success-color); }538        .toast.error { border-left-color: var(--danger-color); }539        540        .toast i { font-size: 1.25rem; }541        .toast.success i { color: var(--success-color); }542        .toast.error i { color: var(--danger-color); }543 544        @keyframes slideIn {545            from { transform: translateX(100%); opacity: 0; }546            to { transform: translateX(0); opacity: 1; }547        }548 549        @keyframes fadeOut {550            to { opacity: 0; transform: translateY(10px); }551        }552 553        /* =========================================554           RESPONSIVE555           ========================================= */556        @media (max-width: 768px) {557            .sidebar {558                position: fixed;559                left: -260px;560                height: 100%;561                box-shadow: var(--shadow-lg);562            }563 564            .sidebar.active {565                left: 0;566            }567 568            .menu-toggle {569                display: block !important;570                margin-right: 1rem;571                font-size: 1.5rem;572                cursor: pointer;573                color: var(--text-main);574            }575            576            .header-title h2 {577                font-size: 1rem;578            }579 580            .stats-grid {581                grid-template-columns: 1fr;582            }583        }584 585        @media (min-width: 769px) {586            .menu-toggle {587                display: none;588            }589        }590    </style>591</head>592<body>593 594    <!-- SIDEBAR -->595    <aside class="sidebar" id="sidebar">596        <div class="brand">597            <i class="ri-building-4-line"></i>598            <span>NEXUS CORP</span>599        </div>600        <ul class="nav-menu">601            <li class="nav-item">602                <a href="#" class="nav-link">603                    <i class="ri-dashboard-line"></i> Dashboard604                </a>605            </li>606            <li class="nav-item">607                <a href="#" class="nav-link active">608                    <i class="ri-team-line"></i> Empleados609                </a>610            </li>611            <li class="nav-item">612                <a href="#" class="nav-link">613                    <i class="ri-briefcase-line"></i> Departamentos614                </a>615            </li>616            <li class="nav-item">617                <a href="#" class="nav-link">618                    <i class="ri-settings-3-line"></i> Configuración619                </a>620            </li>621        </ul>622        <div style="margin-top: auto; font-size: 0.8rem; color: #64748b;">623            v2.4.0 Enterprise624        </div>625    </aside>626 627    <!-- MAIN CONTENT -->628    <main class="main-content">629        <header>630            <div style="display: flex; align-items: center;">631                <i class="ri-menu-line menu-toggle" id="menuToggle"></i>632                <div class="header-title">633                    <h2>Gestión de Personal</h2>634                </div>635            </div>636            <div class="header-actions">637                <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">638                    Built with anycoder639                </a>640                <div class="avatar" style="background: var(--accent-color); color: white; width: 35px; height: 35px; font-size: 0.8rem;">641                    HR642                </div>643            </div>644        </header>645 646        <div class="content-scroll">647            <!-- Estadísticas Rápidas -->648            <div class="stats-grid">649                <div class="stat-card">650                    <div class="stat-info">651                        <p>Total Empleados</p>652                        <h3 id="statTotal">0</h3>653                    </div>654                    <div class="stat-icon">655                        <i class="ri-group-line"></i>656                    </div>657                </div>658                <div class="stat-card">659                    <div class="stat-info">660                        <p>Activos</p>661                        <h3 id="statActive">0</h3>662                    </div>663                    <div class="stat-icon" style="color: var(--success-color); background: #dcfce7;">664                        <i class="ri-user-follow-line"></i>665                    </div>666                </div>667                <div class="stat-card">668                    <div class="stat-info">669                        <p>Departamentos</p>670                        <h3>4</h3>671                    </div>672                    <div class="stat-icon" style="color: var(--warning-color); background: #ffedd5;">673                        <i class="ri-building-line"></i>674                    </div>675                </div>676            </div>677 678            <!-- Barra de herramientas -->679            <div class="toolbar">680                <div class="search-wrapper">681                    <i class="ri-search-line"></i>682                    <input type="text" id="searchInput" class="search-input" placeholder="Buscar por nombre, cargo o email...">683                </div>684                <button class="btn btn-primary" id="addBtn">685                    <i class="ri-add-line"></i> Nuevo Empleado686                </button>687            </div>688 689            <!-- Tabla de Datos -->690            <div class="table-container">691                <table>692                    <thead>693                        <tr>694                            <th>Empleado</th>695                            <th>Cargo</th>696                            <th>Departamento</th>697                            <th>Estado</th>698                            <th style="text-align: right;">Acciones</th>699                        </tr>700                    </thead>701                    <tbody id="employeeTableBody">702                        <!-- Las filas se generarán con JS -->703                    </tbody>704                </table>705                <!-- Estado vacío -->706                <div id="emptyState" style="display: none; padding: 3rem; text-align: center; color: var(--text-muted);">707                    <i class="ri-inbox-line" style="font-size: 3rem; margin-bottom: 1rem; display: block;"></i>708                    <p>No se encontraron empleados.</p>709                </div>710            </div>711        </div>712    </main>713 714    <!-- MODAL FORMULARIO -->715    <div class="modal-overlay" id="modalOverlay">716        <div class="modal">717            <div class="modal-header">718                <h3 id="modalTitle">Añadir Empleado</h3>719                <button class="close-modal" id="closeModal"><i class="ri-close-line"></i></button>720            </div>721            <div class="modal-body">722                <form id="employeeForm">723                    <input type="hidden" id="employeeId">724                    <div class="form-group">725                        <label class="form-label">Nombre Completo</label>726                        <input type="text" class="form-control" id="fullName" required placeholder="Ej. Ana García">727                    </div>728                    <div class="form-group">729                        <label class="form-label">Correo Electrónico</label>730                        <input type="email" class="form-control" id="email" required placeholder="Ej. ana.garcia@nexus.com">731                    </div>732                    <div class="form-group" style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;">733                        <div>734                            <label class="form-label">Cargo</label>735                            <input type="text" class="form-control" id="role" required placeholder="Ej. Desarrollador">736                        </div>737                        <div>738                            <label class="form-label">Departamento</label>739                            <select class="form-control" id="department" required>740                                <option value="Tecnología">Tecnología</option>741                                <option value="Recursos Humanos">Recursos Humanos</option>742                                <option value="Ventas">Ventas</option>743                                <option value="Marketing">Marketing</option>744                            </select>745                        </div>746                    </div>747                    <div class="form-group">748                        <label class="form-label">Estado</label>749                        <select class="form-control" id="status">750                            <option value="Active">Activo</option>751                            <option value="Inactive">Inactivo</option>752                            <option value="Vacation">Vacaciones</option>753                        </select>754                    </div>755                </form>756            </div>757            <div class="modal-footer">758                <button class="btn btn-secondary" id="cancelBtn">Cancelar</button>759                <button class="btn btn-primary" id="saveBtn">Guardar Datos</button>760            </div>761        </div>762    </div>763 764    <!-- TOAST CONTAINER -->765    <div class="toast-container" id="toastContainer"></div>766 767    <script>768        /* =========================================769           LÓGICA JAVASCRIPT770           ========================================= */771        772        // Estado inicial de la aplicación773        let employees = JSON.parse(localStorage.getItem('nexus_employees')) || [774            { id: 1, name: "Carlos Ruiz", email: "carlos.ruiz@nexus.com", role: "Senior Developer", department: "Tecnología", status: "Active" },775            { id: 2, name: "Elena Vega", email: "elena.vega@nexus.com", role: "HR Manager", department: "Recursos Humanos", status: "Active" },776            { id: 3, name: "Miguel Angel", email: "miguel.angel@nexus.com", role: "Sales Lead", department: "Ventas", status: "Vacation" },777            { id: 4, name: "Lucía Méndez", email: "lucia.mendez@nexus.com", role: "UX Designer", department: "Tecnología", status: "Inactive" }778        ];779 780        // Referencias al DOM781        const tableBody = document.getElementById('employeeTableBody');782        const emptyState = document.getElementById('emptyState');783        const searchInput = document.getElementById('searchInput');784        const modalOverlay = document.getElementById('modalOverlay');785        const addBtn = document.getElementById('addBtn');786        const closeModalBtn = document.getElementById('closeModal');787        const cancelBtn = document.getElementById('cancelBtn');788        const saveBtn = document.getElementById('saveBtn');789        const employeeForm = document.getElementById('employeeForm');790        const modalTitle = document.getElementById('modalTitle');791        const statTotal = document.getElementById('statTotal');792        const statActive = document.getElementById('statActive');793        const sidebar = document.getElementById('sidebar');794        const menuToggle = document.getElementById('menuToggle');795 796        // Función para generar iniciales para el avatar797        function getInitials(name) {798            return name.split(' ').map(n => n[0]).join('').substring(0,2).toUpperCase();799        }800 801        // Función para renderizar la tabla802        function renderTable(data = employees) {803            tableBody.innerHTML = '';804            805            // Actualizar estadísticas806            statTotal.textContent = employees.length;807            statActive.textContent = employees.filter(e => e.status === 'Active').length;808 809            if (data.length === 0) {810                emptyState.style.display = 'block';811                return;812            } else {813                emptyState.style.display = 'none';814            }815 816            data.forEach(emp => {817                const tr = document.createElement('tr');818                819                // Definir clase del badge según estado820                let statusClass = 'status-inactive';821                let statusText = 'Inactivo';822                if(emp.status === 'Active') { statusClass = 'status-active'; statusText = 'Activo'; }823                if(emp.status === 'Vacation') { statusClass = 'status-vacation'; statusText = 'Vacaciones'; }824 825                tr.innerHTML = `826                    <td>827                        <div class="user-cell">828                            <div class="avatar">${getInitials(emp.name)}</div>829                            <div class="user-info">830                                <div>${emp.name}</div>831                                <div>${emp.email}</div>832                            </div>833                        </div>834                    </td>835                    <td>${emp.role}</td>836                    <td>${emp.department}</td>837                    <td><span class="status-badge ${statusClass}">${statusText}</span></td>838                    <td style="text-align: right;">839                        <button class="btn-icon" onclick="editEmployee(${emp.id})" title="Editar">840                            <i class="ri-edit-line"></i>841                        </button>842                        <button class="btn-icon delete" onclick="deleteEmployee(${emp.id})" title="Eliminar">843                            <i class="ri-delete-bin-line"></i>844                        </button>845                    </td>846                `;847                tableBody.appendChild(tr);848            });849        }850 851        // Guardar en LocalStorage852        function saveToLocal() {853            localStorage.setItem('nexus_employees', JSON.stringify(employees));854            renderTable(); // Re-renderizar para actualizar estadísticas855        }856 857        // Abrir Modal (Modo Crear)858        function openModal() {859            employeeForm.reset();860            document.getElementById('employeeId').value = '';861            modalTitle.textContent = "Añadir Empleado";862            modalOverlay.classList.add('open');863        }864 865        // Cerrar Modal866        function closeModal() {867            modalOverlay.classList.remove('open');868        }869 870        // Editar Empleado871        window.editEmployee = function(id) {872            const emp = employees.find(e => e.id === id);873            if(emp) {874                document.getElementById('employeeId').value = emp.id;875                document.getElementById('fullName').value = emp.name;876                document.getElementById('email').value = emp.email;877                document.getElementById('role').value = emp.role;878                document.getElementById('department').value = emp.department;879                document.getElementById('status').value = emp.status;880                881                modalTitle.textContent = "Editar Empleado";882                modalOverlay.classList.add('open');883            }884        }885 886        // Eliminar Empleado887        window.deleteEmployee = function(id) {888            if(confirm('¿Está seguro de que desea eliminar este registro? Esta acción no se puede deshacer.')) {889                employees = employees.filter(e => e.id !== id);890                saveToLocal();891                showToast('Empleado eliminado correctamente', 'success');892            }893        }894 895        // Guardar (Crear o Editar)896        function handleSave(e) {897            e.preventDefault();898            899            const idVal = document.getElementById('employeeId').value;900            const name = document.getElementById('fullName').value;901            const email = document.getElementById('email').value;902            const role = document.getElementById('role').value;903            const department = document.getElementById('department').value;904            const status = document.getElementById('status').value;905 906            if(idVal) {907                // Editar existente908                const index = employees.findIndex(e => e.id == idVal);909                if(index !== -1) {910                    employees[index] = { ...employees[index], name, email, role, department, status };911                    showToast('Información actualizada', 'success');912                }913            } else {914                // Crear nuevo915                const newId = employees.length > 0 ? Math.max(...employees.map(e => e.id)) + 1 : 1;916                employees.push({ id: newId, name, email, role, department, status });917                showToast('Empleado añadido con éxito', 'success');918            }919 920            saveToLocal();921            closeModal();922        }923 924        // Sistema de Notificaciones Toast925        function showToast(message, type = 'success') {926            const container = document.getElementById('toastContainer');927            const toast = document.createElement('div');928            toast.className = `toast ${type}`;929            930            const icon = type === 'success' ? 'ri-checkbox-circle-line' : 'ri-error-warning-line';931            932            toast.innerHTML = `933                <i class="${icon}"></i>934                <span>${message}</span>935            `;936 937            container.appendChild(toast);938 939            // Eliminar después de 3 segundos940            setTimeout(() => {941                toast.style.animation = 'fadeOut 0.3s ease forwards';942                toast.addEventListener('animationend', () => {943                    toast.remove();944                });945            }, 3000);946        }947 948        // Filtrado de búsqueda949        searchInput.addEventListener('keyup', (e) => {950            const term = e.target.value.toLowerCase();951            const filtered = employees.filter(emp => 952                emp.name.toLowerCase().includes(term) || 953                emp.role.toLowerCase().includes(term) ||954                emp.email.toLowerCase().includes(term)955            );956            renderTable(filtered);957        });958 959        // Event Listeners960        addBtn.addEventListener('click', openModal);961        closeModalBtn.addEventListener('click', closeModal);962        cancelBtn.addEventListener('click', closeModal);963        saveBtn.addEventListener('click', handleSave);964        965        // Cerrar modal al hacer click fuera966        modalOverlay.addEventListener('click', (e) => {967            if (e.target === modalOverlay) closeModal();968        });969 970        // Toggle Sidebar Móvil971        menuToggle.addEventListener('click', () => {972            sidebar.classList.toggle('active');973        });974 975        // Click fuera de sidebar en móvil para cerrar976        document.addEventListener('click', (e) => {977            if(window.innerWidth <= 768) {978                if(!sidebar.contains(e.target) && !menuToggle.contains(e.target) && sidebar.classList.contains('active')) {979                    sidebar.classList.remove('active');980                }981            }982        });983 984        // Inicializar985        renderTable();986 987    </script>988</body>989</html>