Loading resources/views/adminGen/contactos/index.blade.php +135 −17 Original line number Diff line number Diff line <div id="contextMenu" class="hidden fixed z-50 bg-white border border-gray-300 rounded-md shadow-lg py-2 w-40"> <button id="verBtn" class="w-full text-left px-4 py-2 hover:bg-gray-100">Ver contacto</button> <button id="editarBtn" class="w-full text-left px-4 py-2 hover:bg-gray-100">Editar</button> <button id="eliminarBtn" class="w-full text-left px-4 py-2 text-red-600 hover:bg-red-100">Eliminar</button> </div> <x-layout.default> <script src="/assets/js/simple-datatables.js"></script> Loading Loading @@ -26,7 +32,22 @@ <div class="overflow-x-auto"> <table id="myTable" class="min-w-full table-auto whitespace-nowrap divide-y divide-gray-200 border border-gray-300 rounded-md shadow-sm text-sm text-left"> <thead class="bg-gray-100 text-gray-700 uppercase tracking-wider font-semibold"> <!-- encabezados --> <tr> <th>Profesión</th> <th>Nombre completo</th> <th>Cargo</th> <th>Descripción del cargo</th> <th>Grupos</th> <th>Subgrupos</th> </tr> <tr class="filter-row"> <th><input type="text" class="filter-input" placeholder="Filtrar..." /></th> <th><input type="text" class="filter-input" placeholder="Filtrar..." /></th> <th><input type="text" class="filter-input" placeholder="Filtrar..." /></th> <th><input type="text" class="filter-input" placeholder="Filtrar..." /></th> <th><input type="text" class="filter-input" placeholder="Filtrar..." /></th> <th><input type="text" class="filter-input" placeholder="Filtrar..." /></th> </tr> </thead> <tbody class="divide-y divide-gray-200"> <!-- filas --> Loading @@ -44,6 +65,20 @@ <link rel="stylesheet" href="/assets/css/jquery.toast.css"> <script src="/assets/js/jquery.toast.js"></script> <script> function showAlert() { return Swal.fire({ icon: 'warning', title: '¿Estás seguro?', text: "¡No podrás revertir esto!", showCancelButton: true, confirmButtonText: 'Eliminar', cancelButtonText: 'Cancelar', padding: '2em', }); } </script> <script> const contactos = @json($contactos); const data = contactos.map(contacto => { Loading @@ -51,22 +86,9 @@ return [renderParameter(contacto.profesion?.abreviatura), [contacto.nombre, contacto.ap_paterno, contacto.ap_materno].filter(Boolean).join(' '), renderParameter(contacto.cargo?.nombre), renderParameter(contacto.cargo_desc), renderParameter(contacto.grupos.map(grupo => grupo.nombre).join(', ')), renderParameter(contacto.subgrupos.map(subgrupo => subgrupo.nombre).join(', ')), renderActions(contacto.id)]; renderParameter(contacto.subgrupos.map(subgrupo => subgrupo.nombre).join(', '))]; }); function renderActions(id) { return ` <div class="flex space-x-2"> <a href="/contactos/${id}/ver" class="btn btn-primary btn-sm">Ver contacto</a> <form action="{{ route('contacto.destroy', '') }}/${id}" method="POST" class="inline-block"> @csrf @method('DELETE') <button type="submit" class="btn btn-danger btn-sm">Eliminar</button> </form> <a href="/contactos/${id}/editar" class="btn btn-primary btn-sm">Editar</a> </div>`; } function renderParameter(parametro) { if(parametro === null || parametro === undefined || parametro === ""){ return `Sin información`; Loading Loading @@ -97,13 +119,13 @@ function personalizarPaginacion() { document.addEventListener('DOMContentLoaded', () => { datatable = new simpleDatatables.DataTable('#myTable', { data: { headings: ['Profesión', 'Nombre completo', 'Cargo', 'Descripción del cargo', 'Grupos', 'Subgrupos', 'Acciones'], headings: ['Profesión', 'Nombre completo', 'Cargo', 'Descripción del cargo', 'Grupos', 'Subgrupos'], data: data }, perPage: 10, perPageSelect: [10, 20, 30, 50, 100], columns: [{ select: [0, 1, 2, 3, 4, 5, 6], select: [0, 1, 2, 3, 4, 5], sensitivity: 'base', sort: 'asc' }, Loading @@ -117,6 +139,33 @@ function personalizarPaginacion() { noRows: "No hay filas para mostrar", info: "Mostrando {start} a {end} de {rows} filas", }, tableRender: (_data, table, type) => { if (type === "print") { return table; } const tHead = table.childNodes[0]; const filterHeaders = { nodeName: "TR", childNodes: tHead.childNodes[0].childNodes.map( (_th, index) => ({ nodeName: "TH", childNodes: [ { nodeName: "INPUT", attributes: { class: "datatable-input filter-input w-full px-2 py-1 border rounded", type: "search", "data-columns": `[${index}]`, placeholder: "Filtrar..." } } ] }) ) }; tHead.childNodes.push(filterHeaders); return table; } }); datatable.on("datatable.init", () => { Loading Loading @@ -164,6 +213,19 @@ function personalizarPaginacion() { document.querySelector(".datatable-pagination-list").classList.add("flex", "items-center", "justify-center", "space-x-1"); }); datatable.on('datatable.init', () => { const filterInputs = document.querySelectorAll('.filter-input'); filterInputs.forEach((input, colIndex) => { input.addEventListener('input', function() { datatable.columns().each((column, i) => { if (i === colIndex) { column.search(this.value); } }); }); }); }); datatable.on("datatable.page", () => setTimeout(personalizarPaginacion, 0)); }); Loading Loading @@ -194,5 +256,61 @@ function showToast(message, heading, icon) { @endforeach @endif }); let selectedContactoId = null; document.addEventListener('DOMContentLoaded', function() { document.querySelectorAll('#myTable tbody tr').forEach(tr => { tr.addEventListener('contextmenu', function(e){ e.preventDefault(); const rowIndex = Array.from(tr.parentNode.children).indexOf(tr); selectedContactoId = contactos[rowIndex]?.id; const menu = document.getElementById('contextMenu'); menu.style.left = `${e.pageX}px`; menu.style.top = `${e.pageY}px`; menu.classList.remove('hidden'); }); }); document.addEventListener('click', function(e){ const menu = document.getElementById('contextMenu') if(!menu.contains(e.target)){ menu.classList.add('hidden'); } }) document.getElementById('verBtn').addEventListener('click', function() { if (selectedContactoId) { window.location.href = `/contactos/${selectedContactoId}/ver`; } }); document.getElementById('editarBtn').addEventListener('click', function() { if (selectedContactoId) { window.location.href = `/contactos/${selectedContactoId}/editar`; } }); document.getElementById('eliminarBtn').addEventListener('click', function() { if (selectedContactoId) { showAlert().then((result) => { if (result.isConfirmed) { // Crea un formulario y envíalo const form = document.createElement('form'); form.method = 'POST'; form.action = `/contactos/${selectedContactoId}`; form.innerHTML = ` @csrf @method('DELETE') `; document.body.appendChild(form); form.submit(); } }); } }); }); </script> </x-layout.default> No newline at end of file Loading
resources/views/adminGen/contactos/index.blade.php +135 −17 Original line number Diff line number Diff line <div id="contextMenu" class="hidden fixed z-50 bg-white border border-gray-300 rounded-md shadow-lg py-2 w-40"> <button id="verBtn" class="w-full text-left px-4 py-2 hover:bg-gray-100">Ver contacto</button> <button id="editarBtn" class="w-full text-left px-4 py-2 hover:bg-gray-100">Editar</button> <button id="eliminarBtn" class="w-full text-left px-4 py-2 text-red-600 hover:bg-red-100">Eliminar</button> </div> <x-layout.default> <script src="/assets/js/simple-datatables.js"></script> Loading Loading @@ -26,7 +32,22 @@ <div class="overflow-x-auto"> <table id="myTable" class="min-w-full table-auto whitespace-nowrap divide-y divide-gray-200 border border-gray-300 rounded-md shadow-sm text-sm text-left"> <thead class="bg-gray-100 text-gray-700 uppercase tracking-wider font-semibold"> <!-- encabezados --> <tr> <th>Profesión</th> <th>Nombre completo</th> <th>Cargo</th> <th>Descripción del cargo</th> <th>Grupos</th> <th>Subgrupos</th> </tr> <tr class="filter-row"> <th><input type="text" class="filter-input" placeholder="Filtrar..." /></th> <th><input type="text" class="filter-input" placeholder="Filtrar..." /></th> <th><input type="text" class="filter-input" placeholder="Filtrar..." /></th> <th><input type="text" class="filter-input" placeholder="Filtrar..." /></th> <th><input type="text" class="filter-input" placeholder="Filtrar..." /></th> <th><input type="text" class="filter-input" placeholder="Filtrar..." /></th> </tr> </thead> <tbody class="divide-y divide-gray-200"> <!-- filas --> Loading @@ -44,6 +65,20 @@ <link rel="stylesheet" href="/assets/css/jquery.toast.css"> <script src="/assets/js/jquery.toast.js"></script> <script> function showAlert() { return Swal.fire({ icon: 'warning', title: '¿Estás seguro?', text: "¡No podrás revertir esto!", showCancelButton: true, confirmButtonText: 'Eliminar', cancelButtonText: 'Cancelar', padding: '2em', }); } </script> <script> const contactos = @json($contactos); const data = contactos.map(contacto => { Loading @@ -51,22 +86,9 @@ return [renderParameter(contacto.profesion?.abreviatura), [contacto.nombre, contacto.ap_paterno, contacto.ap_materno].filter(Boolean).join(' '), renderParameter(contacto.cargo?.nombre), renderParameter(contacto.cargo_desc), renderParameter(contacto.grupos.map(grupo => grupo.nombre).join(', ')), renderParameter(contacto.subgrupos.map(subgrupo => subgrupo.nombre).join(', ')), renderActions(contacto.id)]; renderParameter(contacto.subgrupos.map(subgrupo => subgrupo.nombre).join(', '))]; }); function renderActions(id) { return ` <div class="flex space-x-2"> <a href="/contactos/${id}/ver" class="btn btn-primary btn-sm">Ver contacto</a> <form action="{{ route('contacto.destroy', '') }}/${id}" method="POST" class="inline-block"> @csrf @method('DELETE') <button type="submit" class="btn btn-danger btn-sm">Eliminar</button> </form> <a href="/contactos/${id}/editar" class="btn btn-primary btn-sm">Editar</a> </div>`; } function renderParameter(parametro) { if(parametro === null || parametro === undefined || parametro === ""){ return `Sin información`; Loading Loading @@ -97,13 +119,13 @@ function personalizarPaginacion() { document.addEventListener('DOMContentLoaded', () => { datatable = new simpleDatatables.DataTable('#myTable', { data: { headings: ['Profesión', 'Nombre completo', 'Cargo', 'Descripción del cargo', 'Grupos', 'Subgrupos', 'Acciones'], headings: ['Profesión', 'Nombre completo', 'Cargo', 'Descripción del cargo', 'Grupos', 'Subgrupos'], data: data }, perPage: 10, perPageSelect: [10, 20, 30, 50, 100], columns: [{ select: [0, 1, 2, 3, 4, 5, 6], select: [0, 1, 2, 3, 4, 5], sensitivity: 'base', sort: 'asc' }, Loading @@ -117,6 +139,33 @@ function personalizarPaginacion() { noRows: "No hay filas para mostrar", info: "Mostrando {start} a {end} de {rows} filas", }, tableRender: (_data, table, type) => { if (type === "print") { return table; } const tHead = table.childNodes[0]; const filterHeaders = { nodeName: "TR", childNodes: tHead.childNodes[0].childNodes.map( (_th, index) => ({ nodeName: "TH", childNodes: [ { nodeName: "INPUT", attributes: { class: "datatable-input filter-input w-full px-2 py-1 border rounded", type: "search", "data-columns": `[${index}]`, placeholder: "Filtrar..." } } ] }) ) }; tHead.childNodes.push(filterHeaders); return table; } }); datatable.on("datatable.init", () => { Loading Loading @@ -164,6 +213,19 @@ function personalizarPaginacion() { document.querySelector(".datatable-pagination-list").classList.add("flex", "items-center", "justify-center", "space-x-1"); }); datatable.on('datatable.init', () => { const filterInputs = document.querySelectorAll('.filter-input'); filterInputs.forEach((input, colIndex) => { input.addEventListener('input', function() { datatable.columns().each((column, i) => { if (i === colIndex) { column.search(this.value); } }); }); }); }); datatable.on("datatable.page", () => setTimeout(personalizarPaginacion, 0)); }); Loading Loading @@ -194,5 +256,61 @@ function showToast(message, heading, icon) { @endforeach @endif }); let selectedContactoId = null; document.addEventListener('DOMContentLoaded', function() { document.querySelectorAll('#myTable tbody tr').forEach(tr => { tr.addEventListener('contextmenu', function(e){ e.preventDefault(); const rowIndex = Array.from(tr.parentNode.children).indexOf(tr); selectedContactoId = contactos[rowIndex]?.id; const menu = document.getElementById('contextMenu'); menu.style.left = `${e.pageX}px`; menu.style.top = `${e.pageY}px`; menu.classList.remove('hidden'); }); }); document.addEventListener('click', function(e){ const menu = document.getElementById('contextMenu') if(!menu.contains(e.target)){ menu.classList.add('hidden'); } }) document.getElementById('verBtn').addEventListener('click', function() { if (selectedContactoId) { window.location.href = `/contactos/${selectedContactoId}/ver`; } }); document.getElementById('editarBtn').addEventListener('click', function() { if (selectedContactoId) { window.location.href = `/contactos/${selectedContactoId}/editar`; } }); document.getElementById('eliminarBtn').addEventListener('click', function() { if (selectedContactoId) { showAlert().then((result) => { if (result.isConfirmed) { // Crea un formulario y envíalo const form = document.createElement('form'); form.method = 'POST'; form.action = `/contactos/${selectedContactoId}`; form.innerHTML = ` @csrf @method('DELETE') `; document.body.appendChild(form); form.submit(); } }); } }); }); </script> </x-layout.default> No newline at end of file