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

Merge branch 'dependencias' into 'main'

Modal para agregar dependencia, botones de acciones en las tablas y tabla...

See merge request !10
parents 32cccf58 866c5766
Loading
Loading
Loading
Loading
+86 −0
Original line number Diff line number Diff line
<?php

namespace App\Http\Controllers;

use App\Models\Dependencia;
use Illuminate\Http\Request;

class DependenciaController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index()
    {
        $dependencias = Dependencia::get(['id', 'nombre']);
        return view('adminGen.catalogos.dependencias', ['dependencia' => $dependencias]);
    }

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

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'nombre' => 'required|max:150',
        ]);

        $dependencia = new Dependencia;
        $dependencia->nombre = $request->nombre;
        $dependencia->save();
        return redirect()->route('catalogos.dependencias.get')->with('success', 'Dependencia creada correctamente.');
    }

    /**
     * Display the specified resource.
     */
    public function show(Dependencia $dependencia)
    {
        //
    }

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

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, Dependencia $dependencia)
    {
        $validated = $request->validate([
            'id' => 'required:min:1',
            'nombre' => 'required|max:150',
        ]);
        $dependencia = Dependencia::find($request->id);
        $dependencia->nombre = $request->nombre;
        $dependencia->save();
        return redirect()->route('catalogos.dependencias.get')->with('success', 'Dependencia actualizada correctamente.');
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy($id)
    {
        try{
            $dependencia = Dependencia::findOrFail($id);
            $dependencia->delete();
            return redirect()->route('catalogos.dependencias.get')->with('success', 'Dependencia eliminada correctamente.');
        }catch(\Exception $e){
            return redirect()->route('catalogos.dependencias.get')->withErrors('Error al eliminar la dependencia:' . $e->getMessage());
        }
    }
}
+24 −0
Original line number Diff line number Diff line
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\Relations\HasMany;
use App\Models\User;

class Dependencia extends Model
{
    use HasFactory;

    protected $primaryKey = 'id';

    protected $fillable = [
        'nombre',
    ];

    public function users(): HasMany {
        return $this->hasMany(User::class);
    }
}
+34 −0
Original line number Diff line number Diff line
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('dependencias', function (Blueprint $table) {
            $table->id();
            $table->string('nombre');
            $table->timestamps();
        });

        Schema::table('users', function(Blueprint $table){
            $table->unsignedBigInteger('dependencia_id');

            $table->foreign('dependencia_id')->references('id')->on('dependencias');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('dependencias');
    }
};
+6 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Dependencia;
use Illuminate\Support\Facades\Hash;

use Spatie\Permission\Models\Role;
@@ -21,12 +22,14 @@ public function run(): void
        $roleAdmin = Role::create(['name' => 'admin']);
        $roleCap = Role::create(['name' => 'capturista']);
        $roleLector = Role::create(['name' => 'lector']);
        $dependencia = Dependencia::create(['nombre' => 'Administración']);

        $user = User::create([
            'name' => 'Administración general',
            'username' => 'admingen',
            'active' => 1,
            'password' => Hash::make('12345678'),
            'dependencia_id' => 1,
        ]);
        $user->assignRole('admingen');

@@ -35,6 +38,7 @@ public function run(): void
            'username' => 'admin',
            'active' => 1,
            'password' => Hash::make('12345678'),
            'dependencia_id' => 1,
        ]);
        $user->assignRole('admin');

@@ -43,6 +47,7 @@ public function run(): void
            'username' => 'capturista',
            'active' => 1,
            'password' => Hash::make('12345678'),
            'dependencia_id' => 1,
        ]);
        $user->assignRole('capturista');

@@ -51,6 +56,7 @@ public function run(): void
            'username' => 'lector',
            'active' => 1,
            'password' => Hash::make('12345678'),
            'dependencia_id' => 1,
        ]);
        $user->assignRole('lector');

+264 −6
Original line number Diff line number Diff line
<x-layout.default>

    <script defer src="/assets/js/apexcharts.js"></script>
    <div x-data="analytics">
    <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="dependencias">
        <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>Analytics</span>
                <span>Catálogos</span>
            </li>
            <li class="before:content-['/'] before:mr-1 rtl:before:ml-1">
                <span>Dependencias</span>
            </li>
        </ul>
        <div class="pt-5">
        <div class="panel mt-6">
            <div id="editModal" class="fixed inset-0 bg-[black]/60 z-[999] hidden overflow-y-auto">
                <div class="flex items-start justify-center min-h-screen px-4" @click.self="open = false">
                    <div class="panel border-0 py-1 px-4 rounded-lg overflow-hidden w-full max-w-sm my-8">
                        <div class="flex items-center justify-between p-5 font-semibold text-lg dark:text-white">
                            Editar dependencia
                            <button type="button" @click="toggle" class="text-white-dark hover:text-dark">
                                <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="h-6 w-6">
                                    <line x1="18" y1="6" x2="6" y2="18"></line>
                                    <line x1="6" y1="6" x2="18" y2="18"></line>
                                </svg>
                            </button>
                        </div>
                        <div class="p-5">
                            <form action="{{ route('catalogos.dependencias.update') }}" method="POST">
                                @csrf
                                @method('PUT')
                                <div class="relative mb-4">
                                    <label for="nombre">Nombre</label>
                                    <div class="flex">
                                        <div class="bg-[#eee] flex justify-center items-center ltr:rounded-l-md rtl:rounded-r-md px-3 font-semibold border ltr:border-r-0 rtl:border-l-0 border-[#e0e6ed] dark:border-[#17263c] dark:bg-[#1b2e4b]">
                                            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                <path d="M22 22L2 22" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                <path d="M21 22V13M11.0044 5C11.0223 3.76022 11.1143 3.05733 11.5858 2.58579C12.1716 2 13.1144 2 15 2H17C18.8857 2 19.8285 2 20.4143 2.58579C21 3.17157 21 4.11438 21 6V9" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                <path d="M15 22V16M3 22V13M3 9C3 7.11438 3 6.17157 3.58579 5.58579C4.17157 5 5.11438 5 7 5H11C12.8856 5 13.8284 5 14.4142 5.58579C15 6.17157 15 7.11438 15 9V12" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                <path d="M9 22V19" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                <path d="M6 8H12" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                <path d="M6 11H7M12 11H9.5" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                <path d="M6 14H12" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                            </svg>

                                        </div>
                                        <input id="nombreEditar" name="nombre" required type="text" placeholder="Nombre de la dependencia:" class="form-input ltr:rounded-l-md rtl:rounded-r-md" />
                                    </div>
                                </div>
                                <input type="hidden" name="id" id="idEditar">
                                <button id="guardarEditar" type="submit" class="btn btn-primary w-full">Actualizar</button>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
            <div class="md:absolute md:top-5 ltr:md:left-5 rtl:md:right-5">
                <div class="flex items-center flex-wrap mb-5">
                    <div x-data="modal">
                        <button type="button" class="btn btn-success btn-sm m-1 " @click="toggle">
                            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M22 22L2 22" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                <path d="M21 22V13M11.0044 5C11.0223 3.76022 11.1143 3.05733 11.5858 2.58579C12.1716 2 13.1144 2 15 2H17C18.8857 2 19.8285 2 20.4143 2.58579C21 3.17157 21 4.11438 21 6V9" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                <path d="M15 22V16M3 22V13M3 9C3 7.11438 3 6.17157 3.58579 5.58579C4.17157 5 5.11438 5 7 5H11C12.8856 5 13.8284 5 14.4142 5.58579C15 6.17157 15 7.11438 15 9V12" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                <path d="M9 22V19" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                <path d="M6 8H12" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                <path d="M6 11H7M12 11H9.5" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                <path d="M6 14H12" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                            </svg>

                            Crear nueva dependencia
                        </button>
                        <!-- modal -->
                        <div class="fixed inset-0 bg-[black]/60 z-[999] hidden overflow-y-auto" :class="open && '!block'">
                            <div class="flex items-start justify-center min-h-screen px-4" @click.self="open = false">
                                <div x-show="open" x-transition x-transition.duration.300 class="panel border-0 py-1 px-4 rounded-lg overflow-hidden w-full max-w-sm my-8">
                                    <div class="flex items-center justify-between p-5 font-semibold text-lg dark:text-white">Crear nueva dependencia
                                        <button type="button" @click="toggle" class="text-white-dark hover:text-dark">
                                            <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="h-6 w-6">
                                                <line x1="18" y1="6" x2="6" y2="18"></line>
                                                <line x1="6" y1="6" x2="18" y2="18"></line>
                                            </svg>
                                        </button>
                                    </div>
                                    <div class="p-5">
                                        <form action=" {!! route('catalogos.dependencias.store') !!}" method="POST">
                                            @csrf
                                            <div class="relative mb-4">
                                                <label for="nombre">Nombre</label>
                                                <div class="flex">
                                                    <div class="bg-[#eee] flex justify-center items-center ltr:rounded-l-md rtl:rounded-r-md px-3 font-semibold border ltr:border-r-0 rtl:border-l-0 border-[#e0e6ed] dark:border-[#17263c] dark:bg-[#1b2e4b]">
                                                        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                            <path d="M22 22L2 22" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                            <path d="M21 22V13M11.0044 5C11.0223 3.76022 11.1143 3.05733 11.5858 2.58579C12.1716 2 13.1144 2 15 2H17C18.8857 2 19.8285 2 20.4143 2.58579C21 3.17157 21 4.11438 21 6V9" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                            <path d="M15 22V16M3 22V13M3 9C3 7.11438 3 6.17157 3.58579 5.58579C4.17157 5 5.11438 5 7 5H11C12.8856 5 13.8284 5 14.4142 5.58579C15 6.17157 15 7.11438 15 9V12" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                            <path d="M9 22V19" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                            <path d="M6 8H12" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                            <path d="M6 11H7M12 11H9.5" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                            <path d="M6 14H12" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" />
                                                        </svg>

                                                    </div>
                                                    <input id="nombre" name="nombre" type="text" required placeholder="Nombre de la institución:" class="form-input ltr:rounded-l-none rtl:rounded-r-none" />
                                                </div>
                                            </div>


                                            <button type="submit" class="btn btn-primary w-full">Guardar</button>
                                        </form>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <table id="myTable" class="whitespace-nowrap table-hover">
                <thead>
                    <tr>
                        <th>Id</th>
                        <th>Nombre</th>
                        <th>Acciones</th> <!-- Nueva columna para las acciones -->
                    </tr>
                </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>
        const dependencias = @json($dependencia);
        const data = dependencias.map(dep => [dep.id, dep.nombre, renderActions(dep.id, dep.nombre)]);

        window.toggle = function() {
            const modal = document.querySelector('#editModal');
            modal.classList.toggle('hidden');
        };

        function renderActions(id, nombre) {
            return `
                <div class="flex space-x-2">
                    <form action="{{ route('catalogos.dependencias.destroy', '') }}/${id}" method="POST" class="inline-block">
                        @csrf
                        @method('DELETE')
                        <button type="submit" class="btn btn-danger btn-sm">Eliminar</button>
                    </form>
                    <button class="btn btn-primary btn-sm" onclick="editItem(${id}, '${nombre}')">Editar</button>
                </div>`;
        }

        function editItem(id, nombre) {
            const modal = document.querySelector('#editModal');
            const nombreInput = modal.querySelector('#nombreEditar');

            // Asigna el nombre actual de la dependencia al input del modal
            nombreInput.value = nombre;

            // Agrega el ID de la dependencia al botón de guardar del modal
            const idInput = modal.querySelector('#idEditar');
            idInput.value = id;

            // Abre el modal de edición
            modal.classList.remove('hidden');
        }

        document.addEventListener('DOMContentLoaded', () => {
            const datatable = new simpleDatatables.DataTable('#myTable', {
                data: {
                    headings: ['Id', 'Nombre', 'Acciones'],
                    data: data
                },
                perPage: 10,
                perPageSelect: [10, 20, 30, 50, 100],
                columns: [{
                        select: 0,
                        sort: 'asc'
                    },
                    {
                        select: 5,
                        render: (data, cell, row) => formatDate(data)
                    }
                ],
                firstLast: true,
                firstText: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-4.5 h-4.5 rtl:rotate-180"><path d="M13 19L7 12L13 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path opacity="0.5" d="M16.9998 19L10.9998 12L16.9998 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',
                lastText: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-4.5 h-4.5 rtl:rotate-180"><path d="M11 19L17 12L11 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path opacity="0.5" d="M6.99976 19L12.9998 12L6.99976 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',
                prevText: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-4.5 h-4.5 rtl:rotate-180"><path d="M15 5L9 12L15 19" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',
                nextText: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-4.5 h-4.5 rtl:rotate-180"><path d="M9 5L15 12L9 19" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',
                labels: {
                    perPage: "{select}"
                },
                rowId: 'Hola'
            });

            window.editItem = editItem;
        });

        document.addEventListener("alpine:init", () => {
            Alpine.data("modal", (initialOpenState = false) => ({
                open: initialOpenState,

                toggle() {
                    this.open = !this.open;
                },
            }));
        });

        showMessage = (msg = 'Example notification text.', position = 'top-end', showCloseButton = true, closeButtonHtml = '', duration = 3000, type = 'success') => {
            const toast = window.Swal.mixin({
                toast: true,
                position: position || 'top-end',
                showConfirmButton: false,
                timer: duration,
                showCloseButton: showCloseButton,
                customClass: {
                    container: 'custom-swal-container',
                    popup: 'custom-swal-popup',
                    title: 'custom-swal-title',
                }
            });

            // Define el color y el icono según el tipo de mensaje
            let color;
            let icon;
            if (type === 'success') {
                color = '#4caf50'; // Color verde para éxito
                icon = 'success'; // Icono de éxito
            } else if (type === 'error') {
                color = '#f44336'; // Color rojo para error
                icon = 'error'; // Icono de error
            }

            // Aplica el estilo al mensaje
            toast.fire({
                title: msg,
                icon: icon,
                showClass: {
                    popup: 'swal2-noanimation',
                },
                hideClass: {
                    popup: '',
                },
                customClass: {
                    title: 'swal2-title',
                    popup: 'swal2-popup',
                    icon: 'swal2-icon',
                },
                timerProgressBar: true,
                timerProgressBarColor: color,
                timerProgressBarHeight: 3,
                background: color,
                iconColor: 'white',
            });
        };

        document.addEventListener('DOMContentLoaded', function() {
            @if(session('success'))
            // Muestra el mensaje de éxito utilizando showMessage
                showMessage("{{ session('success') }}", 'top-end', true, '', 3000, 'success');
            @endif

            @if($errors -> any())
                @foreach($errors -> all() as $error)
                    showMessage("{{$error}}", 'top-end', true, '', 3000, 'error');
                @endforeach
            @endif
        });
    </script>
</x-layout.default>
 No newline at end of file
Loading