Actualización de moelo user y relación many con asistencias, creación del modelo de asistencia y control por middleware y autenticación

This commit is contained in:
2026-02-11 11:10:17 -06:00
parent 5c93101464
commit 5fe41a4557
25 changed files with 545 additions and 247 deletions
+20 -2
View File
@@ -32,6 +32,15 @@
<form method="POST" action="{{ route('register') }}" class="user">
@csrf
<div class="form-group">
<label for="plantels">Seleccionar Campus</label>
<select class="form-control" name="plantels" id="plantels" >
<option value="0" >Selecciona un plantel</option>
@foreach($plantels as $plantel)
<option value="{{ $plantel->id }}">{{ $plantel->name }}</option>
@endforeach
</select>
</div>
<div class="form-group">
<label>Nombre</label>
@@ -45,7 +54,7 @@
<div class="form-group">
<label>Teléfono</label>
<input type="number" class="form-control form-control-user" name="telefono" autocomplete="off" required autofocus autocomplete="telefono">
<input type="text" class="form-control form-control-user" name="telefono" maxlength="10" onkeypress="return event.charCode >= 48 && event.charCode <= 57" inputmode="numeric" autocomplete="off" required>
</div>
<div class="form-group">
@@ -55,7 +64,7 @@
<div class="form-group">
<label>Confirmar contraseña</label>
<input type="password" class="form-control form-control-user" id="password" name="password" placeholder="Confirmar contraseña" required autocomplete="current-password">
<input type="password" class="form-control form-control-user" id="password_confirmation" name="password_confirmation" placeholder="Confirmar contraseña" required autocomplete="current-password">
</div>
@@ -84,6 +93,15 @@
@include('layouts._partials.scripts')
@livewireScripts
@yield('scripts')
@if ($errors->any())
<script>
Swal.fire({
icon: 'error',
title: 'Error',
text: '{{ $errors->first() }}'
});
</script>
@endif
</body>
</html>
+23
View File
@@ -0,0 +1,23 @@
@extends('layouts.landing')
@section('title',"Inicio")
@section('content')
<div class="container-fluid">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Asistencia</h6>
</div>
<div class="card-body">
@livewire('code-scanner')
</div>
</div>
</div>
@endsection
@section('scripts')
<script src="https://unpkg.com/html5-qrcode"></script>
@endsection
File diff suppressed because one or more lines are too long
+34 -127
View File
@@ -24,14 +24,8 @@
<!-- Heading -->
<div class="sidebar-heading" style="color:white">Modulos</div>
<!-- Roles -->
<!-- Nav Item - Utilities Collapse Menu -->
@hasrole('Admin')
<li class="nav-item">
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#Administrador"
aria-expanded="true" aria-controls="Administrador">
<i class="fas fa-star" style="color:rgb(255, 153, 0);"></i>
@@ -102,60 +96,25 @@
</li>
@endrole
<!-- Nav Item - Utilities Collapse Menu -->
{{-- <li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#Inventario"
aria-expanded="true" aria-controls="Inventario">
<i class="fas fa-fw fa-wrench" style="color: #e8e8e8;"></i>
<span>Inventario</span>
</a>
<div id="Inventario" class="collapse" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Herramientas:</h6>
<a class="collapse-item" href="inicio_inventario.php" style="color:#85888e">Pagina Principal</a>
<a class="collapse-item" href="proveedores.php" style="color:#85888e">Proveedores</a>
<a class="collapse-item" href="historial_compras.php" style="color:#85888e">Historial de compras</a>
<a class="collapse-item" href="evalucion.php" style="color:#85888e">Evaluación</a>
</div>
</div>
</li> --}}
{{-- <li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#ControlEscolar"
aria-expanded="true" aria-controls="ControlEscolar">
<i class="fas fa-book" style="color: #e8e8e8;"></i>
<span>Control Escolar</span>
</a>
<div id="ControlEscolar" class="collapse" aria-labelledby="ControlEscolar" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Herramientas</h6>
<a class="collapse-item" href="dal.php" style="color:#85888e">Alumnos</a>
<a class="collapse-item" href="calificaciones.php" style="color:#85888e">Calificaciones</a>
</div>
</div>
</li> --}}
@hasrole('Promotor')
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#Promocion"
aria-expanded="true" aria-controls="Promocion">
<i class="fas fa-fw fa-bullhorn" style="color: #e8e8e8;"></i>
<span>Promoción</span>
</a>
<div id="Promocion" class="collapse" aria-labelledby="Promocion" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Herramientas</h6>
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#Promocion"
aria-expanded="true" aria-controls="Promocion">
<i class="fas fa-fw fa-bullhorn" style="color: #e8e8e8;"></i>
<span>Promoción</span>
</a>
<div id="Promocion" class="collapse" aria-labelledby="Promocion" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Herramientas</h6>
@can('prospecto.index')
<a class="collapse-item" href="{{ route('prospecto.index') }}" style="color:#85888e">Prospectos</a>
@endcan
<a class="collapse-item" href="difusion.php" style="color:#85888e">Difusión</a>
<a class="collapse-item" href="informes.php" style="color:#85888e">Informes</a>
<a class="collapse-item" href="referencias.php" style="color:#85888e">Referencias</a>
@can('prospecto.index')
<a class="collapse-item" href="{{ route('prospecto.index') }}" style="color:#85888e">Prospectos</a>
@endcan
<a class="collapse-item" href="difusion.php" style="color:#85888e">Difusión</a>
<a class="collapse-item" href="informes.php" style="color:#85888e">Informes</a>
<a class="collapse-item" href="referencias.php" style="color:#85888e">Referencias</a>
</div>
</div>
</div>
</li>
@endrole
@@ -167,90 +126,38 @@
</li>
@endrole
{{-- <li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#Finanzas"
aria-expanded="true" aria-controls="Finanzas">
<i class="fas fa-money-bill-alt" style="color: #e8e8e8;"></i>
<span>Finanzas</span>
</a>
<div id="Finanzas" class="collapse" aria-labelledby="Finanzas" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Herramientas</h6>
<a class="collapse-item" href="dal.php" style="color:#85888e">Alumnos</a>
<a class="collapse-item" href="calificaciones.php" style="color:#85888e">Calificaciones</a>
</div>
</div>
</li> --}}
<!-- /Roles -->
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading" style="color:white">Adicionales</div>
<!-- Nav Item - Chats -->
<li class="nav-item">
{{-- <li class="nav-item">
<a class="nav-link" href="chats.php">
<i class="fas fa-fw fa-comments" style="color: #e8e8e8;"></i>
<span>Chats</span></a>
</li>
</li> --}}
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-id-badge" style="color: #e8e8e8;"></i>
<span>Asistencia</span>
</a>
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Herramientas:</h6>
<a class="collapse-item" href="unidad.php" style="color:gray">Mi unidad</a>
<a class="collapse-item" href="asistencia.php" style="color:gray">Generar Chequeos</a>
<a class="collapse-item" href="mapa.php" style="color:gray">Rastreo</a>
</div>
@can('code.index')
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-id-badge" style="color: #e8e8e8;"></i>
<span>Asistencia</span>
</a>
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Herramientas:</h6>
<a class="collapse-item" href="{{ route('code.index') }}" style="color:gray">Escanear</a>
{{-- <a class="collapse-item" href="{{ route('code.show') }}" style="color:gray">Registros</a> --}}
</div>
</li>
</div>
</li>
@endcan
<!-- Nav Item - Chats -->
<li class="nav-item">
<a class="nav-link" href="calendario.php">
<i class="fas fa-fw fa-calendar" style="color: #e8e8e8;"></i>
<span>Calendario</span></a>
</li>
<!-- Nav Item - Chats -->
<li class="nav-item">
<a class="nav-link" href="blog.php">
<i class="fas fa-fw fa-blog" style="color: #e8e8e8;"></i>
<span>Blog</span></a>
</li>
<!-- Nav Item - notes -->
<li class="nav-item">
<a class="nav-link" href="reporte_sistemas.php">
<i class="fas fa-file-alt" style="color: #e8e8e8;"></i>
<span>Reporte de sistemas</span></a>
</li>
<!-- Nav Item - notes -->
<li class="nav-item">
<a class="nav-link" href="tienda.php">
<i class="fas fa-store" style="color: #e8e8e8;"></i>
<span>Tienda Online</span></a>
</li>
<!-- Nav Item - notes -->
@can('note.index')
+43 -14
View File
@@ -33,30 +33,59 @@
{{-- scripts por vista --}}
@yield('scripts')
@stack('scripts')
<script>
window.addEventListener('swal', event => {
document.addEventListener('livewire:init', () => {
console.log('Evento swal recibido:', event.detail);
Livewire.on('swal', (data, ...payload) => {
if (!event.detail) return;
// 🔥 compatibilidad Livewire viejo y nuevo
if (Array.isArray(data)) {
data = data[0];
}
if (!data && payload.length) {
data = payload[0];
}
if (!data || !data.text) {
console.warn('SweetAlert disparado sin datos', data);
return;
}
Swal.fire({
icon: event.detail.icon ?? 'info',
title: event.detail.title ?? 'Aviso',
text: event.detail.text ?? '',
icon: data.icon ?? 'info',
title: data.title ?? 'Aviso',
text: data.text,
timer: data.timer ?? null,
showConfirmButton: data.confirm ?? true,
});
if (data.reload) {
setTimeout(() => location.reload(), data.reload);
}
if (data.closeModal) {
$('#exampleModal').modal('hide');
}
});
Livewire.on('open-prospecto-modal', () => {
$('#exampleModal').modal('show');
});
});
window.addEventListener('close-modal', () => {
const modal = bootstrap.Modal.getInstance(
document.getElementById('logoutSessionsModal')
);
modal?.hide();
});
</script>
<script>
window.addEventListener('close-modal', () => {
const modal = bootstrap.Modal.getInstance(
document.getElementById('logoutSessionsModal')
);
modal?.hide();
});
</script>
</body>
</html>
@@ -0,0 +1,103 @@
<div>
<div wire:ignore>
<div id="reader"></div>
<p>Latitud: <span id="latitud">Esperando GPS...</span></p>
<p>Longitud: <span id="longitud">Esperando GPS...</span></p>
</div>
</div>
@push('scripts')
<script>
let scanner = null;
let gpsListo = false;
let yaEscaneado = false;
let latitud = null;
let longitud = null;
function iniciarScanner(){
if(scanner !== null) return;
scanner = new Html5Qrcode("reader");
scanner.start(
{ facingMode: "environment" },
{ fps: 10, qrbox: 250 },
(mensaje) => {
if(!gpsListo){
Swal.fire("GPS","Esperando ubicación...","warning");
return;
}
if(yaEscaneado) return;
yaEscaneado = true;
Livewire.dispatch('qrLeido', {
texto: mensaje,
lat: latitud,
lng: longitud
});
});
}
document.addEventListener('livewire:init', () => {
if ("geolocation" in navigator) {
navigator.geolocation.getCurrentPosition(
function(pos){
latitud = pos.coords.latitude;
longitud = pos.coords.longitude;
gpsListo = true;
document.getElementById("latitud").innerText = latitud;
document.getElementById("longitud").innerText = longitud;
iniciarScanner();
},
function(error){
Swal.fire(
"GPS ERROR",
"Activa el gps y vuelve a intentar",
"error"
);
},
{
enableHighAccuracy:true,
timeout:15000,
maximumAge:0
});
}
});
document.addEventListener("visibilitychange", function() {
if(document.hidden && scanner){
scanner.stop().catch(()=>{});
scanner = null;
}
if(!document.hidden && gpsListo){
iniciarScanner();
}
});
</script>
@endpush
-29
View File
@@ -71,35 +71,6 @@
@include('layouts._partials.delete')
<script>
document.addEventListener('livewire:init', () => {
Livewire.on('swal', data => {
if (!data?.text) {
console.warn('SweetAlert disparado sin datos', data);
return;
}
Swal.fire({
icon: data.icon ?? 'info',
title: data.title ?? 'Aviso',
text: data.text,
timer: data.timer ?? null,
showConfirmButton: data.confirm ?? true,
});
if (data.reload) {
setTimeout(() => location.reload(), data.reload);
}
if (data.closeModal) {
$('#exampleModal').modal('hide');
}
});
Livewire.on('open-prospecto-modal', () => {
$('#exampleModal').modal('show');
});
Livewire.on('mark-active-prospect', ({ id }) => {
document.querySelectorAll('.list-group-item')