Commit db429082 authored by Alfonso Rafael Solis Rangel's avatar Alfonso Rafael Solis Rangel
Browse files

Primeros pasos para exportar los datos

parent 6ba74a12
Loading
Loading
Loading
Loading
+89 −0
Original line number Diff line number Diff line
<?php

namespace App\Http\Controllers;

use App\Models\Caracteristicas;
use App\Models\cargos;
use App\Models\Contacto;
use App\Models\Grupos;
use App\Models\Lista;
use Illuminate\Http\Request;

class ReporteController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index()
    {
        $cargos = cargos::get();
        $caracteristicas = Caracteristicas::get();
        $grupos = Grupos::get();
        $listas = Lista::get();
        return view('adminGen.contactos.export', compact('cargos', 'caracteristicas', 'grupos', 'listas'));
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     */
    public function show(string $id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(string $id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, string $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id)
    {
        //
    }

    public function find(Request $request)
    {
        $query = $request->input('q');

        $contactos = Contacto::where('nombre', 'like', '%' . $query . '%')->get(['id', 'nombre', 'ap_paterno', 'ap_materno']);
        return response()->json($contactos);
    }

    public function export(Request $request)
    {
        if(is_null($request->archivo)){
            return response()->json(['Error, No seleccionaste un archivo de exportación valido.'], 400);
        }
        dd($request->all());
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
    "keywords": ["laravel", "framework"],
    "license": "MIT",
    "require": {
        "php": "^8.2",
        "php": "^8.3",
        "laravel/framework": "^11.9",
        "laravel/jetstream": "^5.1",
        "laravel/sanctum": "^4.0",
+331 −0
Original line number Diff line number Diff line
<meta name="_token" content="{{ csrf_token() }}">
<x-layout.default>
    <script src="/assets/js/simple-datatables.js"></script>
    <link rel="stylesheet" href="{{ Vite::asset('resources/css/swiper-bundle.min.css') }}">
    <script src="/assets/js/swiper-bundle.min.js"></script>
    <div x-data="contactos">
        <ul class="flex space-x-2 rtl:space-x-reverse">
            <li>
                <a href="javascript:;" class="text-primary hover:underline">Dashboard</a>
            </li>
            <li class="before:content-['/'] before:mr-1 rtl:before:ml-1">
                <span>Reportes</span>
            </li>
        </ul>
        <div class="panel mt-6">

            <div class="p-6 bg-gray-100 rounded-lg shadow-md">
                <form method="GET" action="" class="space-y-4" onsubmit="event.preventDefault(); logData();">
                    <!-- Listas -->
                    <div class="flex flex-col space-y-2">
                        <label for="listas" class="text-gray-700 font-semibold">Listas:</label>
                        <div class="flex space-x-2">
                            <select id="listas" class="w-full px-3 py-2 bg-white border border-gray-300 rounded-md">
                                <option value="" disabled selected>Selecciona una lista</option>
                                @foreach($listas as $lista)
                                    <option value="{{ $lista->id }}">{{ $lista->nombre }}</option>
                                @endforeach
                            </select>
                            <button type="button" onclick="agregarEtiqueta('listas', 'listasAgregadas')" class="bg-blue-500 text-white px-3 py-2 rounded-md">Agregar</button>
                        </div>
                        <div id="listasAgregadas" class="flex flex-wrap space-x-2 mt-2"></div>
                    </div>
                    <!-- Características -->
                    <div class="flex flex-col space-y-2">
                        <label for="caracteristicas" class="text-gray-700 font-semibold">Características:</label>
                        <div class="flex space-x-2">
                            <select id="caracteristicas" class="w-full px-3 py-2 bg-white border border-gray-300 rounded-md">
                                <option value="" disabled selected>Selecciona una característica</option>
                                @foreach($caracteristicas as $caracteristica)
                                    <option value="{{ $caracteristica->id }}">{{ $caracteristica->nombre }}</option>
                                @endforeach
                            </select>
                            <button type="button" onclick="agregarEtiqueta('caracteristicas', 'caracteristicasAgregadas')" class="bg-blue-500 text-white px-3 py-2 rounded-md">Agregar</button>
                        </div>
                        <div id="caracteristicasAgregadas" class="flex flex-wrap space-x-2 mt-2"></div>
                    </div>

                    <!-- Grupos -->
                    <div class="flex flex-col space-y-2">
                        <label for="grupos" class="text-gray-700 font-semibold">Grupos:</label>
                        <div class="flex space-x-2">
                            <select id="grupos" class="w-full px-3 py-2 bg-white border border-gray-300 rounded-md">
                                <option value="" disabled selected>Selecciona un grupo</option>
                                @foreach($grupos as $grupo)
                                    <option value="{{ $grupo->id }}">{{ $grupo->nombre }}</option>
                                @endforeach
                            </select>
                            <button type="button" onclick="agregarEtiqueta('grupos', 'gruposAgregados')" class="bg-blue-500 text-white px-3 py-2 rounded-md">Agregar</button>
                        </div>
                        <div id="gruposAgregados" class="flex flex-wrap space-x-2 mt-2"></div>
                    </div>

                    <!-- Cargos -->
                    <div class="flex flex-col space-y-2">
                        <label for="cargos" class="text-gray-700 font-semibold">Cargos:</label>
                        <div class="flex space-x-2">
                            <select id="cargos" class="w-full px-3 py-2 bg-white border border-gray-300 rounded-md">
                                <option value="" disabled selected>Selecciona un cargo</option>
                                @foreach($cargos as $cargo)
                                    <option value="{{ $cargo->id }}">{{ $cargo->nombre }}</option>
                                @endforeach
                            </select>
                            <button type="button" onclick="agregarEtiqueta('cargos', 'cargosAgregados')" class="bg-blue-500 text-white px-3 py-2 rounded-md">Agregar</button>
                        </div>
                        <div id="cargosAgregados" class="flex flex-wrap space-x-2 mt-2"></div>
                    </div>

                    <!-- Contacto -->
                    <div class="flex items-center space-x-2">
                        <label for="contacto" class="text-gray-700 font-semibold">Agregar Contacto:</label>
                        <input type="text" id="contacto" placeholder="Buscar contacto..."
                            class="w-full px-3 py-2 bg-white border border-gray-300 rounded-md"
                            oninput="buscarContactos(this.value)">
                        <ul id="sugerenciasContactos" class="border border-gray-300 bg-white rounded-md shadow-md mt-1 hidden"></ul>
                    </div>

                    <!-- Lista de Contactos Agregados -->
                    <div id="contactosAgregados" class="flex flex-wrap space-x-2 mt-4"></div>

                    <!-- Campos a exportar -->
                    <div class="flex flex-col space-y-2">
                        <label for="exportar" class="text-gray-700 font-semibold">Campos:</label>
                        <div class="flex space-x-2">
                            <select id="exportar" class="w-full px-3 py-2 bg-white border border-gray-300 rounded-md">
                                <option value="" disabled selected>Selecciona los campos a exportar</option>
                                <option value="todos">Todos</option>
                                <option value="tonyuge">Cónyuge</option>
                                <option value="contacto_directo">Contacto Directo</option>
                                <option value="domicilio">Domicilio</option>
                                <option value="cumpleanos">Cumpleaños</option>
                                <option value="email">Correo electrónico</option>
                                <option value="telefonos">Teléfonos</option>
                            </select>
                            <button type="button" onclick="agregarEtiqueta('exportar', 'exportarAgregados')" class="bg-blue-500 text-white px-3 py-2 rounded-md">Agregar</button>
                        </div>
                        <div id="exportarAgregados" class="flex flex-wrap space-x-2 mt-2"></div>
                    </div>
                    <!-- Tipo de archivo a exportar -->
                    <div class="flex flex-col space-y-2">
                        <label for="archivo" class="text-gray-700 font-semibold">Tipo de archivo:</label>
                        <div class="flex space-x-2">
                            <select id="archivo" class="w-full px-3 py-2 bg-white border border-gray-300 rounded-md">
                                <option value="" disabled selected>Selecciona el formato de archivo a exportar</option>
                                <option value="ambos">Ambos</option>
                                <option value="pdf">PDF</option>
                                <option value="excel">Excel</option>
                            </select>
                        </div>
                    </div>

                    <!-- Botón para aplicar filtros -->
                    <div class="text-right">
                        <button type="submit" class="px-4 py-2 bg-blue-500 text-white font-semibold rounded-md hover:bg-blue-600">
                            Aplicar Filtros
                        </button>
                    </div>
                </form>
            </div>

            <div class="flex items-center flex-wrap mb-5">
            </div>
            <table id="myTable" class="whitespace-nowrap table-hover">
                <thead></thead>
                <tbody></tbody>
            </table>

        </div>
    </div>

    <link rel="stylesheet" href="{{ Vite::asset('resources/css/highlight.min.css') }}">
    <script src="/assets/js/highlight.min.js"></script>

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <link rel="stylesheet" href="/assets/css/jquery.toast.css">
    <script src="/assets/js/jquery.toast.js"></script>

    <script>
        let contactosSeleccionados = [];
        let listasSeleccion = [];
        let caracteristicasSeleccion = [];
        let gruposSeleccion = []; 
        let cargosSeleccion = [];
        let exportarSeleccion = [];

        async function buscarContactos(query) {
            if (query.length < 2) {
                document.getElementById('sugerenciasContactos').classList.add('hidden');
                return;
            }

            const response = await fetch(`/reportes/contactos/buscar?q=${query}`);
            const contactos = await response.json();

            mostrarSugerencias(contactos);
        }

        function mostrarSugerencias(contactos) {
            const sugerenciasContainer = document.getElementById('sugerenciasContactos');
            sugerenciasContainer.innerHTML = ''; // Limpiar las sugerencias previas

            contactos.forEach(contacto => {
                const item = document.createElement('li');
                item.classList.add('p-2', 'cursor-pointer', 'hover:bg-gray-200');
                item.textContent = `${contacto.nombre} ${contacto.ap_paterno} ${contacto.ap_materno}`;
                item.onclick = () => agregarContacto(contacto);
                sugerenciasContainer.appendChild(item);
            });

            sugerenciasContainer.classList.remove('hidden');
        }

        function agregarContacto(contacto) {
            // Verificar si el contacto ya ha sido seleccionado
            if (!contactosSeleccionados.some(c => c.id === contacto.id)) {
                contactosSeleccionados.push(contacto);
                actualizarContactosAgregados();
            }

            // Limpiar el input y ocultar las sugerencias
            document.getElementById('contacto').value = '';
            document.getElementById('sugerenciasContactos').classList.add('hidden');
        }

        function actualizarContactosAgregados() {
            const contactosContainer = document.getElementById('contactosAgregados');
            contactosContainer.innerHTML = ''; // Limpiar la lista antes de actualizarla

            contactosSeleccionados.forEach(contacto => {
                const contactoElement = document.createElement('div');
                contactoElement.classList.add('inline-block', 'bg-gray-200', 'px-4', 'py-2', 'rounded', 'mr-2', 'mt-2');
                contactoElement.innerHTML = `${contacto.nombre} ${contacto.ap_paterno} ${contacto.ap_materno} <button onclick="eliminarContacto(${contacto.id})" class="text-red-500">x</button>`;
                
                // Campo oculto para enviar al servidor
                const inputHidden = document.createElement('input');
                inputHidden.type = 'hidden';
                inputHidden.name = 'contactos[]';
                inputHidden.value = contacto.id;
                contactoElement.appendChild(inputHidden);

                contactosContainer.appendChild(contactoElement);
            });
        }

        function eliminarContacto(contactoId) {
            contactosSeleccionados = contactosSeleccionados.filter(c => c.id !== contactoId);
            actualizarContactosAgregados();
        }

        function logData() {
            const select = document.getElementById('archivo');
            const selectedOption = select.options[select.selectedIndex];
            
            const data = {
                contactos: contactosSeleccionados,
                listas: listasSeleccion,
                caracteristicas: caracteristicasSeleccion,
                grupos: gruposSeleccion,
                cargos: cargosSeleccion,
                exportar: exportarSeleccion,
                archivo: selectedOption.value,
            };

            fetch('/reportes/contactos/exportar', {
                method: "POST",
                body: JSON.stringify(data),
                headers: {
                    "Content-Type": "application/json; charset=UTF-8",
                    "X-CSRF-Token": $('meta[name="_token"]').attr('content')
                }
            })
            .then(response => response.json())
            .then(json => showToast(json, 'Error', 'error'))
            .catch(err => showToast(err[0], 'Error', 'error'));
        }
    </script>

    <script>
        function agregarEtiqueta(selectId, containerId) {
            const select = document.getElementById(selectId);
            const selectedOption = select.options[select.selectedIndex];
            

            if (selectedOption && selectedOption.value) {
                const container = document.getElementById(containerId);
                const etiquetaId = `${selectId}-${selectedOption.value}`;
                
                // Verifica si la etiqueta ya fue agregada
                if (!document.getElementById(etiquetaId)) {
                    switch (selectId) {
                        case 'listas':
                            listasSeleccion.push(selectedOption.value);
                            break;
                        case 'caracteristicas':
                            caracteristicasSeleccion.push(selectedOption.value);
                            break;
                        case 'cargos':
                            cargosSeleccion.push(selectedOption.value);
                            break;
                        case 'grupos':
                            gruposSeleccion.push(selectedOption.value);
                            break;
                        case 'exportar':
                            exportarSeleccion.push(selectedOption.value);
                            break;
                        default:
                            break;
                    }

                    const etiqueta = document.createElement('div');
                    etiqueta.id = etiquetaId;
                    etiqueta.classList.add('inline-block', 'bg-gray-200', 'px-4', 'py-2', 'rounded', 'mr-2', 'mt-2');
                    etiqueta.innerHTML = `${selectedOption.text} <button type="button" onclick="eliminarEtiqueta('${etiquetaId}')" class="text-red-500">x</button>`;
                    
                    // Campo oculto para enviar al servidor
                    const inputHidden = document.createElement('input');
                    inputHidden.type = 'hidden';
                    inputHidden.name = `${selectId}[]`;
                    inputHidden.value = selectedOption.value;
                    etiqueta.appendChild(inputHidden);

                    container.appendChild(etiqueta);
                    select.selectedIndex = 0; // Reinicia el select
                }
            }
        }

        function eliminarEtiqueta(etiquetaId) {
            const etiqueta = document.getElementById(etiquetaId);
            if (etiqueta) etiqueta.remove();
        }

        let contactos = [];

        function showToast(message, heading, icon) {
            $.toast({
                heading: heading,
                text: message,
                showHideTransition: 'slide',
                icon: icon,
                position: 'top-right',
                loader: false,
                hideAfter: 10000, 
                allowToastClose: true,
                textColor: '#676767',
            });
        }

        document.addEventListener('DOMContentLoaded', function() {
            @if(session('success'))
            // Muestra el mensaje de éxito utilizando showMessage
                showToast("{{ session('success') }}", 'Exito.', 'success')
            @endif

            @if($errors->any())
                @foreach($errors->all() as $error)
                    showToast(`{{ $error }}`, 'Error.', 'error');
                @endforeach
            @endif
        });
    </script>
</x-layout.default>
 No newline at end of file
+19 −0
Original line number Diff line number Diff line
<meta name="_token" content="{{ csrf_token() }}">
<div :class="{ 'dark text-white-dark': $store.app.semidark }">
    <nav x-data="sidebar"
        class="sidebar fixed min-h-screen h-full top-0 bottom-0 w-[260px] shadow-[5px_0_25px_0_rgba(94,92,154,0.1)] z-50 transition-all duration-300">
@@ -222,6 +223,24 @@ class="py-3 px-7 flex items-center uppercase font-extrabold bg-white-light/30 da
                        </div>
                    </a>
                </li>
                <li class="menu nav-item">
                    <a href="/reportes/contactos" class="nav-link group">
                        <div class="flex items-center">

                        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M10.5 14L17 14" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
                            <path d="M7 14H7.5" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
                            <path d="M7 10.5H7.5" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
                            <path d="M7 17.5H7.5" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
                            <path d="M10.5 10.5H17" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
                            <path d="M10.5 17.5H17" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
                            <path d="M8 3.5C8 2.67157 8.67157 2 9.5 2H14.5C15.3284 2 16 2.67157 16 3.5V4.5C16 5.32843 15.3284 6 14.5 6H9.5C8.67157 6 8 5.32843 8 4.5V3.5Z" stroke="#1C274C" stroke-width="1.5"/>
                            <path d="M21 16.0002C21 18.8286 21 20.2429 20.1213 21.1215C19.2426 22.0002 17.8284 22.0002 15 22.0002H9C6.17157 22.0002 4.75736 22.0002 3.87868 21.1215C3 20.2429 3 18.8286 3 16.0002V13.0002M16 4.00195C18.175 4.01406 19.3529 4.11051 20.1213 4.87889C21 5.75757 21 7.17179 21 10.0002V12.0002M8 4.00195C5.82497 4.01406 4.64706 4.11051 3.87868 4.87889C3.11032 5.64725 3.01385 6.82511 3.00174 9" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
                        </svg>
                            <span class="ltr:pl-3 rtl:pr-3 text-black dark:text-[#506690] dark:group-hover:text-white-dark">Contactos</span>
                        </div>
                    </a>
                </li>
            </ul>
        </div>
    </nav>
+12 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
use App\Http\Controllers\UserController;
//Instituciones
use App\Http\Controllers\InstitucionesController;
use App\Http\Controllers\ReporteController;

Route::get('/', function () {
    if(!auth()->user()){
@@ -146,3 +147,13 @@
    CheckBanned::class)->name('auditoria.')->group(function(){
        Route::get('/administracion/auditoria', [AuditoriaController::class, 'index'])->name('get')->middleware(CheckRoles::class . ':admingen,admin');
});


Route::middleware('auth:sanctum', 
    config('jetstream.auth_session'),
    'verified',
    CheckBanned::class)->name('reporte.')->group(function(){
        Route::get('/reportes/contactos', [ReporteController::class, 'index'])->name('get')->middleware(CheckRoles::class . ':admingen,admin');
        Route::get('/reportes/contactos/buscar', [ReporteController::class, 'find'])->name('find')->middleware(CheckRoles::class . ':admingen,admin');
        Route::post('/reportes/contactos/exportar', [ReporteController::class, 'export'])->name('export')->middleware(CheckRoles::class . ':admingen,admin');
});
 No newline at end of file