feat: acople de schedule.view_reservation al BFF y creacion/asociacion de comisiones a materias
This commit is contained in:
@@ -9,15 +9,29 @@
|
||||
<h1 class="h3 fw-bold mb-1">
|
||||
<i class="bi bi-diagram-3 me-2 text-primary"></i>Gestión de Comisiones
|
||||
</h1>
|
||||
<p class="text-muted mb-0 small">Asignación de docentes e inscripción de alumnos por comisión</p>
|
||||
<p class="text-muted mb-0 small">Asignación de asignaturas, docentes e inscripción de alumnos por comisión</p>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="button" class="btn btn-primary btn-sm px-3 shadow-sm" data-bs-toggle="modal" data-bs-target="#modalAddCommission">
|
||||
<i class="bi bi-plus-circle me-1"></i>Nueva Comisión
|
||||
</button>
|
||||
<a href="/admin/subjects_list" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="bi bi-book me-1"></i>Ver Asignaturas
|
||||
</a>
|
||||
</div>
|
||||
<a href="/admin/subjects_list" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="bi bi-book me-1"></i>Ver Asignaturas
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Flash Messages -->
|
||||
|
||||
<!-- Flash Messages & Feedback -->
|
||||
{% if created %}
|
||||
<div class="alert alert-success alert-dismissible fade show d-flex align-items-center gap-2 mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-check-circle-fill fs-5 text-success"></i>
|
||||
<div>
|
||||
<strong>¡Comisión registrada!</strong> La comisión ha sido creada y asociada correctamente a la asignatura elegida.
|
||||
</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<!-- Filters Card -->
|
||||
<div class="card shadow-sm border-0 mb-4">
|
||||
@@ -104,8 +118,12 @@
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="fw-semibold">{{ comm.subject.name }}</div>
|
||||
<small class="text-muted">{{ comm.subject.code }} — {{ comm.semester }} {{ comm.year }}</small>
|
||||
<div class="fw-semibold text-primary">{{ comm.subject.name }}</div>
|
||||
<div class="d-flex align-items-center gap-1 mt-1 flex-wrap">
|
||||
<span class="badge bg-secondary-subtle text-secondary border font-monospace">{{ comm.subject.code }}</span>
|
||||
<span class="badge bg-body-tertiary text-muted border">{{ comm.subject.career_name or 'Carrera General' }}</span>
|
||||
<small class="text-muted ms-1">{{ comm.semester }} {{ comm.year }}</small>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{% if comm.teacher %}
|
||||
@@ -188,13 +206,135 @@
|
||||
{% else %}
|
||||
<div class="text-center py-5">
|
||||
<i class="bi bi-diagram-3 display-4 text-muted opacity-50"></i>
|
||||
<p class="mt-3 text-muted">No se encontraron comisiones con los filtros aplicados.</p>
|
||||
<a href="/admin/commissions_list" class="btn btn-outline-primary btn-sm">
|
||||
<i class="bi bi-arrow-clockwise me-1"></i>Limpiar filtros
|
||||
</a>
|
||||
<h5 class="mt-3 fw-bold text-secondary">No se encontraron comisiones</h5>
|
||||
<p class="text-muted small">Crea una nueva comisión para asociarla a una materia y asignarle horarios, cupos y docentes.</p>
|
||||
<div class="d-flex justify-content-center gap-2 mt-3">
|
||||
<button type="button" class="btn btn-primary btn-sm px-3 shadow-sm" data-bs-toggle="modal" data-bs-target="#modalAddCommission">
|
||||
<i class="bi bi-plus-circle me-1"></i>Crear Primera Comisión
|
||||
</button>
|
||||
<a href="/admin/commissions_list" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="bi bi-arrow-clockwise me-1"></i>Limpiar filtros
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: Nueva Comisión y Asociación con Materia -->
|
||||
<div class="modal fade" id="modalAddCommission" tabindex="-1" aria-labelledby="modalAddCommissionLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header bg-body-tertiary border-bottom py-3">
|
||||
<h5 class="modal-title fw-bold" id="modalAddCommissionLabel">
|
||||
<i class="bi bi-plus-circle text-primary me-2"></i>Nueva Comisión de Cursada
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="/admin/commission_add" method="POST">
|
||||
<div class="modal-body p-4">
|
||||
<div class="alert alert-primary bg-primary-subtle border-primary-subtle py-2 px-3 small d-flex align-items-center gap-2 mb-4">
|
||||
<i class="bi bi-info-circle-fill fs-5 text-primary"></i>
|
||||
<div>
|
||||
Cada comisión debe pertenecer a una <strong>Asignatura</strong> específica para organizar sus horarios, inscripción de alumnos y enlaces de aulas virtuales.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 1. Asignatura y Código -->
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-7">
|
||||
<label for="add_subject_id" class="form-label fw-semibold small">
|
||||
<i class="bi bi-book text-primary me-1"></i>Asignatura / Materia Asociada <span class="text-danger">*</span>
|
||||
</label>
|
||||
<select class="form-select" id="add_subject_id" name="subject_id" required>
|
||||
<option value="">-- Seleccione la materia a vincular... --</option>
|
||||
{% for s in subjects %}
|
||||
<option value="{{ s.id }}">
|
||||
{{ s.code }} · {{ s.name }} ({{ s.career_name or s.career or 'Carrera General' }})
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div class="form-text small">La comisión heredará el plan de estudios y carrera de la materia.</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<label for="add_code" class="form-label fw-semibold small">
|
||||
<i class="bi bi-tag text-secondary me-1"></i>Código / Identificador <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input type="text" class="form-control" id="add_code" name="code" placeholder="Ej: Comisión A, B, N1, Única" required>
|
||||
<div class="form-text small">Identificador visible para docentes y alumnos.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. Período, Año y Turno -->
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-4">
|
||||
<label for="add_semester" class="form-label fw-semibold small">Cuatrimestre / Período</label>
|
||||
<select class="form-select form-select-sm" id="add_semester" name="semester">
|
||||
<option value="1C" selected>1C (Primer Cuatrimestre)</option>
|
||||
<option value="2C">2C (Segundo Cuatrimestre)</option>
|
||||
<option value="Anual">Anual</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="add_year" class="form-label fw-semibold small">Año Académico</label>
|
||||
<input type="number" class="form-control form-control-sm" id="add_year" name="year" value="2026" min="2020" max="2035">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="add_shift" class="form-label fw-semibold small">Turno de Cursada</label>
|
||||
<select class="form-select form-select-sm" id="add_shift" name="shift">
|
||||
<option value="Mañana">Mañana (08:00 - 12:00)</option>
|
||||
<option value="Tarde" selected>Tarde (17:30 - 21:30)</option>
|
||||
<option value="Vespertino">Vespertino</option>
|
||||
<option value="Noche">Noche (19:00 - 23:00)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. Docente a Cargo y Cupo -->
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-8">
|
||||
<label for="add_teacher_id" class="form-label fw-semibold small">
|
||||
<i class="bi bi-person-video3 text-info me-1"></i>Docente Responsable
|
||||
</label>
|
||||
<select class="form-select form-select-sm" id="add_teacher_id" name="teacher_id">
|
||||
<option value="">-- Sin asignar (se puede asignar más tarde) --</option>
|
||||
{% for t in teachers %}
|
||||
<option value="{{ t.id }}">{{ t.name }} ({{ t.email }})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="add_max_students" class="form-label fw-semibold small">Cupo Máximo de Alumnos</label>
|
||||
<input type="number" class="form-control form-control-sm" id="add_max_students" name="max_students" value="40" min="1" max="300">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. Días y Horarios -->
|
||||
<div class="mb-3">
|
||||
<label for="add_schedule" class="form-label fw-semibold small">
|
||||
<i class="bi bi-calendar-week text-warning me-1"></i>Días y Horarios de Cursada
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm" id="add_schedule" name="schedule" placeholder="Ej: Lun y Mié 17:30 a 21:30 hs">
|
||||
</div>
|
||||
|
||||
<!-- 5. Enlace a Aula Virtual -->
|
||||
<div class="mb-2">
|
||||
<label for="add_virtual_link" class="form-label fw-semibold small">
|
||||
<i class="bi bi-camera-video text-primary me-1"></i>Enlace a Aula Virtual (Meet, Zoom, Teams, Moodle)
|
||||
</label>
|
||||
<input type="url" class="form-control form-control-sm" id="add_virtual_link" name="virtual_link" placeholder="https://meet.google.com/... (opcional, se auto-generará si se omite)">
|
||||
<div class="form-text small">Si no se especifica, el sistema creará un enlace institucional directo a Google Meet.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-body-tertiary border-top py-2">
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-primary btn-sm px-4 shadow-sm">
|
||||
<i class="bi bi-save me-1"></i>Crear y Asociar Comisión
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -518,7 +518,7 @@
|
||||
</td>
|
||||
<td class="small">{{ pres.user.name if pres.user else 'Docente' }}</td>
|
||||
<td class="text-end pe-3">
|
||||
<a href="/schedule/view_reservation" class="btn btn-sm btn-outline-primary py-0 px-2">
|
||||
<a href="/schedule/view_reservation?id={{ pres.id }}" class="btn btn-sm btn-outline-primary py-0 px-2">
|
||||
<i class="bi bi-check-circle me-1"></i>Revisar
|
||||
</a>
|
||||
</td>
|
||||
@@ -745,7 +745,7 @@
|
||||
<i class="bi bi-box-arrow-up-right me-1"></i>Ingresar a Reunión
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="/schedule/view_reservation" class="btn btn-sm btn-outline-secondary py-1 px-2">
|
||||
<a href="/schedule/view_reservation?id={{ c.id }}" class="btn btn-sm btn-outline-secondary py-1 px-2">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -1035,7 +1035,7 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-end pe-3">
|
||||
<a href="/schedule/view_reservation"
|
||||
<a href="/schedule/view_reservation?id={{ res.id }}"
|
||||
class="btn btn-sm btn-outline-secondary py-0 px-2" title="Ver Ficha">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
|
||||
@@ -221,17 +221,17 @@
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if user.can_edit_reservation(reservation) %}
|
||||
<a href="/schedule/edit_reservation"
|
||||
<a href="/schedule/edit_reservation?id={{ reservation.id }}"
|
||||
class="btn btn-sm btn-outline-warning py-0 px-2 me-1" title="Modificar Reserva">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="/schedule/view_reservation"
|
||||
<a href="/schedule/view_reservation?id={{ reservation.id }}"
|
||||
class="btn btn-sm btn-outline-secondary py-0 px-2" title="Ver Ficha">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
{% if user.has_permission('reservations', 'read_write') and (reservation.status == 'PENDING' or reservation.status.value == 'PENDING') %}
|
||||
<a href="/schedule/confirm_reservation"
|
||||
<a href="/schedule/confirm_reservation?id={{ reservation.id }}"
|
||||
class="btn btn-sm btn-outline-success py-0 px-2 ms-1" title="Confirmar">
|
||||
<i class="bi bi-check-lg"></i>
|
||||
</a>
|
||||
@@ -326,16 +326,16 @@
|
||||
<i class="bi bi-camera-video"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="/schedule/view_reservation" class="btn btn-sm btn-outline-secondary py-1 px-2" title="Ver Ficha">
|
||||
<a href="/schedule/view_reservation?id={{ reservation.id }}" class="btn btn-sm btn-outline-secondary py-1 px-2" title="Ver Ficha">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
{% if user.can_edit_reservation(reservation) %}
|
||||
<a href="/schedule/edit_reservation" class="btn btn-sm btn-outline-warning py-1 px-2" title="Modificar">
|
||||
<a href="/schedule/edit_reservation?id={{ reservation.id }}" class="btn btn-sm btn-outline-warning py-1 px-2" title="Modificar">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if user.has_permission('reservations', 'read_write') and (reservation.status == 'PENDING' or reservation.status.value == 'PENDING') %}
|
||||
<a href="/schedule/confirm_reservation" class="btn btn-sm btn-outline-success py-1 px-2" title="Confirmar">
|
||||
<a href="/schedule/confirm_reservation?id={{ reservation.id }}" class="btn btn-sm btn-outline-success py-1 px-2" title="Confirmar">
|
||||
<i class="bi bi-check-lg"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
@@ -221,11 +221,11 @@
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if user.can_edit_reservation(item.reservation) %}
|
||||
<a href="/schedule/edit_reservation" class="btn btn-sm btn-outline-warning py-0 px-2" title="Modificar Reserva">
|
||||
<a href="/schedule/edit_reservation?id={{ item.reservation.id }}" class="btn btn-sm btn-outline-warning py-0 px-2" title="Modificar Reserva">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="/schedule/view_reservation" class="btn btn-sm btn-outline-secondary py-0 px-2" title="Ver Ficha Detallada">
|
||||
<a href="/schedule/view_reservation?id={{ item.reservation.id }}" class="btn btn-sm btn-outline-secondary py-0 px-2" title="Ver Ficha Detallada">
|
||||
<i class="bi bi-eye me-1"></i>Detalles
|
||||
</a>
|
||||
</div>
|
||||
@@ -305,12 +305,12 @@
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if user.can_edit_reservation(reservation) %}
|
||||
<a href="/schedule/edit_reservation"
|
||||
<a href="/schedule/edit_reservation?id={{ reservation.id }}"
|
||||
class="btn btn-sm btn-outline-warning py-0 px-2 me-1" title="Modificar Reserva">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="/schedule/view_reservation"
|
||||
<a href="/schedule/view_reservation?id={{ reservation.id }}"
|
||||
class="btn btn-sm btn-outline-secondary py-0 px-2" title="Ver Ficha">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</h1>
|
||||
<div class="d-flex gap-2">
|
||||
{% if user.can_edit_reservation(reservation) %}
|
||||
<a href="/schedule/edit_reservation" class="btn btn-warning">
|
||||
<a href="/schedule/edit_reservation?id={{ reservation.id }}" class="btn btn-warning">
|
||||
<i class="bi bi-pencil-square me-1"></i>Modificar Reserva
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -231,23 +231,25 @@
|
||||
<div class="card-body">
|
||||
<div class="d-grid gap-2">
|
||||
{% if user.can_edit_reservation(reservation) %}
|
||||
<a href="/schedule/edit_reservation" class="btn btn-warning">
|
||||
<a href="/schedule/edit_reservation?id={{ reservation.id }}" class="btn btn-warning">
|
||||
<i class="bi bi-pencil-square me-1"></i>Modificar Reserva
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if reservation.status.value == 'PENDING' %}
|
||||
<form method="POST" action="/schedule/confirm_reservation">
|
||||
<button type="submit" class="btn btn-success" onclick="return confirm('Confirm this reservation?')">
|
||||
<i class="bi bi-check-circle"></i> Confirm Reservation
|
||||
{% if reservation.status.value == 'PENDING' or reservation.status == 'PENDING' %}
|
||||
<form method="POST" action="/schedule/confirm_reservation?id={{ reservation.id }}">
|
||||
<input type="hidden" name="id" value="{{ reservation.id }}">
|
||||
<button type="submit" class="btn btn-success" onclick="return confirm('¿Confirmar esta reserva?')">
|
||||
<i class="bi bi-check-circle me-1"></i>Confirmar Reserva
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% if reservation.can_be_cancelled() %}
|
||||
<form method="POST" action="/schedule/cancel_reservation">
|
||||
<button type="submit" class="btn btn-danger" onclick="return confirm('Cancel this reservation?')">
|
||||
<i class="bi bi-x-circle"></i> Cancel Reservation
|
||||
<form method="POST" action="/schedule/cancel_reservation?id={{ reservation.id }}">
|
||||
<input type="hidden" name="id" value="{{ reservation.id }}">
|
||||
<button type="submit" class="btn btn-danger" onclick="return confirm('¿Cancelar esta reserva?')">
|
||||
<i class="bi bi-x-circle me-1"></i>Cancelar Reserva
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user