Desarrollo del modulo de alumno y control escolar para subir archivos de expediente
This commit is contained in:
@@ -155,6 +155,9 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
@@ -182,5 +185,35 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
function verDocumento(url, docId) {
|
||||
|
||||
document.getElementById('visorFrame').src = url;
|
||||
|
||||
Livewire.dispatch('set-documento', { id: docId });
|
||||
|
||||
// 🔥 guardar instancia global
|
||||
visorModalInstance = new bootstrap.Modal(
|
||||
document.getElementById('visorModal')
|
||||
);
|
||||
|
||||
visorModalInstance.show();
|
||||
}
|
||||
|
||||
document.addEventListener('livewire:init', () => {
|
||||
|
||||
Livewire.on('cerrar-modal', () => {
|
||||
|
||||
if (visorModalInstance) {
|
||||
visorModalInstance.hide();
|
||||
}
|
||||
|
||||
// 🔥 limpiar iframe
|
||||
document.getElementById('visorFrame').src = "";
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
|
||||
@@ -193,9 +193,93 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row pt-5">
|
||||
|
||||
<div>
|
||||
<h5>Expediente del alumno</h5>
|
||||
|
||||
@php
|
||||
$tipos = ['curp', 'acta', 'comprobante','certificadoPrepa','certificadoLicenciatura'];
|
||||
$documentos = collect($prospecto?->documentos)->keyBy('tipo');
|
||||
@endphp
|
||||
|
||||
@foreach($tipos as $tipo)
|
||||
@php
|
||||
$doc = $documentos[$tipo] ?? null;
|
||||
@endphp
|
||||
|
||||
<div class="mb-3">
|
||||
<strong>{{ strtoupper($tipo) }}</strong> :
|
||||
|
||||
@if($doc)
|
||||
|
||||
@if($doc->status == 1)
|
||||
<span class="badge bg-success">✔ Validado</span>
|
||||
|
||||
@elseif($doc->status == 2)
|
||||
<span class="badge bg-danger">❌ Rechazado</span>
|
||||
|
||||
@else
|
||||
<span class="badge bg-warning">Pendiente de revision</span>
|
||||
|
||||
<button
|
||||
onclick="verDocumento('{{ url('documento/ver/'.$doc->id) }}', {{ $doc->id }})"
|
||||
class="btn btn-sm btn-primary mt-2">
|
||||
<i class="fa-duotone fa-solid fa-eye"></i> Ver documento
|
||||
</button>
|
||||
@endif
|
||||
|
||||
|
||||
|
||||
@else
|
||||
<span class="text-danger">❌ Faltante</span>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@else
|
||||
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal fade"
|
||||
id="visorModal"
|
||||
tabindex="-1"
|
||||
wire:ignore.self>
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Vista previa</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<iframe id="visorFrame" width="100%" height="500px" style="border:none;" wire:ignore></iframe>
|
||||
|
||||
<div class="m-5 text-center">
|
||||
|
||||
|
||||
<button wire:click="rechazarDocumento" class="btn btn-danger">
|
||||
<i class="fa-solid fa-trash-can"></i> Rechazar
|
||||
</button>
|
||||
|
||||
<button wire:click="aprobarDocumento" class="btn btn-success">
|
||||
<i class="fa-duotone fa-regular fa-circle-check"></i> Aprobar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
<div wire:ignore.self
|
||||
class="modal fade"
|
||||
id="exampleModal"
|
||||
tabindex="-1"
|
||||
role="dialog"
|
||||
data-backdrop="static"
|
||||
data-keyboard="false">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Carga de documentos</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
@php
|
||||
$pendientes = collect(['curp','acta','comprobante'])->filter(function($tipo) {
|
||||
$doc = $documentosPorTipo[$tipo] ?? null;
|
||||
return !$doc || $doc->status == 2;
|
||||
});
|
||||
@endphp
|
||||
|
||||
@if($pendientes->isEmpty())
|
||||
<div class="alert alert-success">
|
||||
✔ Todos los documentos están validados
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form wire:submit.prevent="store" enctype="multipart/form-data">
|
||||
|
||||
@php
|
||||
$doc = $documentosPorTipo['curp'] ?? null;
|
||||
@endphp
|
||||
|
||||
@if(!$doc || $doc->status == 2)
|
||||
<div class="mb-3">
|
||||
<label class="small mb-1">CURP:</label>
|
||||
|
||||
@if($doc && $doc->status == 2)
|
||||
<span class="badge bg-danger">❌ Rechazado</span>
|
||||
@endif
|
||||
|
||||
<div class="custom-file-upload" wire:ignore>
|
||||
<input type="file" id="curp" hidden
|
||||
onchange="updateFileName(this, 'curp-name')"
|
||||
wire:model="curp">
|
||||
|
||||
<label for="curp" class="btn btn-outline-primary btn-sm">
|
||||
📄 Seleccionar archivo
|
||||
</label>
|
||||
|
||||
<span id="curp-name" class="ml-2 text-muted">
|
||||
Ningún archivo seleccionado
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- acta --}}
|
||||
@php
|
||||
$doc = $documentosPorTipo['acta'] ?? null;
|
||||
@endphp
|
||||
|
||||
@if(!$doc || $doc->status == 2)
|
||||
<div class="mb-3">
|
||||
<label class="small mb-1">Acta:</label>
|
||||
|
||||
@if($doc && $doc->status == 2)
|
||||
<span class="badge bg-danger">❌ Rechazado</span>
|
||||
@endif
|
||||
|
||||
<div class="custom-file-upload" wire:ignore>
|
||||
<input type="file" id="acta" hidden
|
||||
onchange="updateFileName(this, 'acta-name')"
|
||||
wire:model="acta">
|
||||
|
||||
<label for="acta" class="btn btn-outline-primary btn-sm">
|
||||
📄 Seleccionar archivo
|
||||
</label>
|
||||
|
||||
<span id="acta-name" class="ml-2 text-muted">
|
||||
Ningún archivo seleccionado
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
{{-- acta --}}
|
||||
|
||||
|
||||
@php
|
||||
$doc = $documentosPorTipo['comprobante'] ?? null;
|
||||
@endphp
|
||||
|
||||
@if(!$doc || $doc->status == 2)
|
||||
<div class="mb-3">
|
||||
<label class="small mb-1">Comprobante de domicilio:</label>
|
||||
|
||||
@if($doc && $doc->status == 2)
|
||||
<span class="badge bg-danger">❌ Rechazado</span>
|
||||
@endif
|
||||
|
||||
<div class="custom-file-upload" wire:ignore>
|
||||
<input type="file" id="comprobante" hidden
|
||||
onchange="updateFileName(this, 'comprobante-name')"
|
||||
wire:model="comprobante">
|
||||
|
||||
<label for="comprobante" class="btn btn-outline-primary btn-sm">
|
||||
📄 Seleccionar archivo
|
||||
</label>
|
||||
|
||||
<span id="comprobante-name" class="ml-2 text-muted">
|
||||
Ningún archivo seleccionado
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<button class="btn btn-primary" type="submit">Subir</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -4,29 +4,153 @@
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.custom-file-upload {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.custom-file-upload span {
|
||||
font-size: 13px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header py-3">
|
||||
|
||||
<div class="card-header py-3">
|
||||
<div class="d-sm-flex align-items-center justify-content-between">
|
||||
<h6 class="m-0 font-weight-bold text-primary">Mi perfil</h6>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
@livewire('profile.update-profile-information-form')
|
||||
|
||||
<hr>
|
||||
|
||||
@livewire('profile.update-password-form')
|
||||
|
||||
<hr>
|
||||
|
||||
@livewire('profile.logout-other-browser-sessions-form')
|
||||
|
||||
@hasrole('Alumno')
|
||||
<button onclick="Livewire.dispatch('documentos')"
|
||||
class="btn btn-sm btn-success shadow-sm">
|
||||
<i class="fas fa-file fa-sm text-white-50"></i> Expediente
|
||||
</button>
|
||||
@endrole
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
@hasrole('Alumno')
|
||||
|
||||
<div>
|
||||
<h5>Expediente</h5>
|
||||
|
||||
@php
|
||||
$tipos = ['curp', 'acta', 'comprobante'];
|
||||
$alumno = Auth::user()->alumnos()->first();
|
||||
@endphp
|
||||
|
||||
@foreach($tipos as $tipo)
|
||||
@php
|
||||
$doc = $alumno?->documentos->firstWhere('tipo', $tipo);
|
||||
@endphp
|
||||
|
||||
<div class="mb-3">
|
||||
<strong>{{ strtoupper($tipo) }}</strong> :
|
||||
|
||||
@if($doc)
|
||||
|
||||
@if($doc->status == 1)
|
||||
<span class="badge bg-success">✔ Validado</span>
|
||||
|
||||
@elseif($doc->status == 2)
|
||||
<span class="badge bg-danger">❌ Rechazado</span>
|
||||
|
||||
@else
|
||||
<span class="badge bg-warning">Pendiente de revision</span>
|
||||
@endif
|
||||
|
||||
<br>
|
||||
|
||||
<button
|
||||
onclick="verDocumento('{{ url('documento/ver/'.$doc->id) }}')"
|
||||
class="btn btn-sm btn-primary mt-2">
|
||||
<i class="fa-duotone fa-solid fa-eye"></i> Ver documento
|
||||
</button>
|
||||
|
||||
@else
|
||||
<span class="text-danger">❌ Faltante</span>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
|
||||
<livewire:documentos/>
|
||||
|
||||
@endrole
|
||||
|
||||
@livewire('profile.update-profile-information-form')
|
||||
|
||||
<hr>
|
||||
|
||||
@livewire('profile.update-password-form')
|
||||
|
||||
<hr>
|
||||
|
||||
@livewire('profile.logout-other-browser-sessions-form')
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 🔥 MODAL VISOR -->
|
||||
|
||||
<div class="modal fade" id="visorModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Vista previa</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<iframe id="visorFrame" width="100%" height="600px" style="border:none;"></iframe>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
|
||||
<script>
|
||||
document.addEventListener('livewire:init', () => {
|
||||
Livewire.on('open-documentos-modal', () => {
|
||||
$('#exampleModal').modal('show');
|
||||
});
|
||||
});
|
||||
|
||||
// 🔥 abrir documento en modal
|
||||
function verDocumento(url) {
|
||||
document.getElementById('visorFrame').src = url + '?t=' + new Date().getTime();
|
||||
|
||||
var modal = new bootstrap.Modal(document.getElementById('visorModal'));
|
||||
modal.show();
|
||||
}
|
||||
|
||||
// 🔥 limpiar iframe al cerrar
|
||||
document.getElementById('visorModal').addEventListener('hidden.bs.modal', function () {
|
||||
document.getElementById('visorFrame').src = '';
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
function updateFileName(input, targetId) {
|
||||
const fileName = input.files[0]?.name || 'Ningún archivo seleccionado';
|
||||
document.getElementById(targetId).textContent = fileName;
|
||||
}
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
|
||||
Reference in New Issue
Block a user