290 lines
14 KiB
HTML
290 lines
14 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Reservation Details - Edu-Space Admin{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid pt-5 mt-4">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h1 class="h3">
|
|
<i class="bi bi-calendar-check text-info"></i> Reservation Details
|
|
</h1>
|
|
<div class="d-flex gap-2">
|
|
{% if current_user.can_edit_reservation(reservation) %}
|
|
<a href="{{ url_for('schedule.edit_reservation', id=reservation.id) }}" class="btn btn-warning">
|
|
<i class="bi bi-pencil-square me-1"></i>{% trans %}Modificar Reserva{% endtrans %}
|
|
</a>
|
|
{% endif %}
|
|
<a href="{{ url_for('schedule.list_reservations') }}" class="btn btn-outline-secondary">
|
|
<i class="bi bi-arrow-left me-1"></i>{% trans %}Back to List{% endtrans %}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Main Reservation Info -->
|
|
<div class="col-lg-8 mb-4">
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="card-header border-0 py-3">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<h5 class="mb-0">
|
|
<i class="bi bi-info-circle text-primary"></i> Reservation Information
|
|
</h5>
|
|
<span class="badge bg-{% if reservation.status.value == 'CONFIRMED' %}success{% elif reservation.status.value == 'PENDING' %}warning{% else %}secondary{% endif %}">
|
|
{{ reservation.status.value }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label class="text-muted small">Reservation ID</label>
|
|
<p class="mb-0"><strong>#{{ reservation.id }}</strong></p>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="text-muted small">Created by</label>
|
|
<p class="mb-0">
|
|
<i class="bi bi-person"></i>
|
|
{% if reservation.user %}
|
|
{{ reservation.user.first_name }} {{ reservation.user.last_name }}
|
|
{% else %}
|
|
Unknown
|
|
{% endif %}
|
|
</p>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="text-muted small">Date & Time</label>
|
|
<p class="mb-0">
|
|
<i class="bi bi-clock"></i>
|
|
{{ format_date(reservation.start_time, format='long')|capitalize }}<br>
|
|
{{ reservation.start_time.strftime('%H:%M') }} - {{ reservation.end_time.strftime('%H:%M') }}
|
|
</p>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="text-muted small">Duration</label>
|
|
<p class="mb-0">
|
|
<i class="bi bi-hourglass"></i>
|
|
{% set duration = (reservation.end_time - reservation.start_time).total_seconds() / 60 %}
|
|
{{ (duration / 60) | round(1) }} hours
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{% if reservation.purpose %}
|
|
<div class="mb-3">
|
|
<label class="text-muted small">Purpose</label>
|
|
<p class="mb-0">{{ reservation.purpose }}</p>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if reservation.notes %}
|
|
<div class="mb-3">
|
|
<label class="text-muted small">Notes</label>
|
|
<p class="mb-0">{{ reservation.notes }}</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Classroom Details -->
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="card-header border-0 py-3 bg-body-tertiary">
|
|
<h5 class="mb-0 h6 fw-bold">
|
|
<i class="bi bi-geo-alt text-primary me-2"></i>{% trans %}Ubicación y Espacio Asignado{% endtrans %}
|
|
</h5>
|
|
</div>
|
|
<div class="card-body p-4">
|
|
{% if reservation.classroom %}
|
|
<div class="row g-3 mb-3">
|
|
<div class="col-md-4">
|
|
<div class="p-3 rounded bg-body-tertiary border">
|
|
<small class="text-muted d-block mb-1">🏢 {% trans %}Edificio / Sede{% endtrans %}</small>
|
|
<h6 class="mb-0 fw-bold text-primary">{{ reservation.classroom.building_name }}</h6>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="p-3 rounded bg-body-tertiary border">
|
|
<small class="text-muted d-block mb-1">🪜 {% trans %}Piso / Nivel{% endtrans %}</small>
|
|
<h6 class="mb-0 fw-bold text-secondary">
|
|
{% if reservation.classroom.is_virtual %}
|
|
<span class="badge bg-primary-subtle text-primary border">Campus Virtual</span>
|
|
{% else %}
|
|
{{ reservation.classroom.floor_display }}
|
|
{% endif %}
|
|
</h6>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="p-3 rounded bg-body-tertiary border">
|
|
<small class="text-muted d-block mb-1">🚪 {% trans %}Aula{% endtrans %}</small>
|
|
<h6 class="mb-0 fw-bold text-success">{{ reservation.classroom.code }}</h6>
|
|
<small class="text-muted">{% trans %}Capacidad:{% endtrans %} <strong>{{ reservation.classroom.capacity_display }}</strong></small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if reservation.classroom.description %}
|
|
<div class="mt-2">
|
|
<label class="text-muted small">{% trans %}Descripción del Aula{% endtrans %}</label>
|
|
<p class="mb-0 small">{{ reservation.classroom.description }}</p>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Banner de Aula Virtual (Zoom, Meet, Teams) -->
|
|
{% if reservation.effective_virtual_link or (reservation.classroom and reservation.classroom.is_virtual) %}
|
|
<div class="mt-3 p-3 rounded bg-primary bg-opacity-10 border border-primary border-opacity-25 d-flex flex-column flex-sm-row justify-content-between align-items-sm-center gap-3">
|
|
<div>
|
|
<div class="fw-bold text-primary mb-1">
|
|
<i class="bi bi-camera-video me-1"></i>{% trans %}Aula Virtual / Videoconferencia{% endtrans %}
|
|
</div>
|
|
{% if reservation.effective_virtual_link %}
|
|
<small class="text-secondary text-break font-monospace d-block">{{ reservation.effective_virtual_link }}</small>
|
|
{% else %}
|
|
<small class="text-muted fst-italic">{% trans %}Modalidad remota sin enlace específico registrado{% endtrans %}</small>
|
|
{% endif %}
|
|
</div>
|
|
{% if reservation.effective_virtual_link %}
|
|
<a href="{{ reservation.effective_virtual_link }}" target="_blank" class="btn btn-success btn-sm px-3 text-nowrap">
|
|
<i class="bi bi-box-arrow-up-right me-1"></i>{% trans %}Unirse a Clase (Zoom / Meet){% endtrans %}
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
{% else %}
|
|
<p class="text-muted mb-0">{% trans %}Classroom information not available{% endtrans %}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sidebar -->
|
|
<div class="col-lg-4">
|
|
<!-- Subject & Commission -->
|
|
<div class="card border-0 shadow-sm mb-4">
|
|
<div class="card-header border-0 py-3">
|
|
<h5 class="mb-0">
|
|
<i class="bi bi-book text-warning"></i> Subject & Commission
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
{% if reservation.commission %}
|
|
<div class="mb-3">
|
|
<label class="text-muted small">Commission Code</label>
|
|
<p class="mb-0"><strong>{{ reservation.commission.get_full_code() }}</strong></p>
|
|
</div>
|
|
{% if reservation.commission.subject %}
|
|
<div class="mb-3">
|
|
<label class="text-muted small">Subject</label>
|
|
<p class="mb-0">{{ reservation.commission.subject.name }}</p>
|
|
</div>
|
|
{% endif %}
|
|
{% else %}
|
|
<p class="text-muted mb-0">No commission assigned</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Attendees -->
|
|
<div class="card border-0 shadow-sm mb-4">
|
|
<div class="card-header border-0 py-3">
|
|
<h5 class="mb-0">
|
|
<i class="bi bi-people text-success"></i> Attendance
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="text-center">
|
|
<h3 class="mb-1">{{ reservation.expected_attendees }}</h3>
|
|
<p class="text-muted small">Expected Attendees</p>
|
|
{% if reservation.classroom %}
|
|
{% if reservation.classroom.capacity and reservation.classroom.capacity > 0 %}
|
|
<div class="progress mt-3" style="height: 8px;">
|
|
{% set percentage = (reservation.expected_attendees / reservation.classroom.capacity * 100) %}
|
|
<div class="progress-bar bg-{% if percentage > 90 %}danger{% elif percentage > 75 %}warning{% else %}success{% endif %}"
|
|
role="progressbar"
|
|
style="{{ 'width: ' ~ ([percentage|round(1), 100]|min|string) ~ '%;' }}"></div>
|
|
</div>
|
|
<small class="text-muted">
|
|
{{ reservation.expected_attendees }} / {{ reservation.classroom.capacity }} {% trans %}capacidad{% endtrans %}
|
|
</small>
|
|
{% else %}
|
|
<div class="mt-2">
|
|
<span class="badge bg-primary-subtle text-primary border">
|
|
{% if reservation.classroom.is_virtual %}🌐 Campus Virtual (Sin límite físico){% else %}{% trans %}Capacidad no definida{% endtrans %}{% endif %}
|
|
</span>
|
|
</div>
|
|
{% endif %}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Actions -->
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="card-header border-0 py-3">
|
|
<h5 class="mb-0">
|
|
<i class="bi bi-gear text-secondary"></i> Actions
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-grid gap-2">
|
|
{% if current_user.can_edit_reservation(reservation) %}
|
|
<a href="{{ url_for('schedule.edit_reservation', id=reservation.id) }}" class="btn btn-warning">
|
|
<i class="bi bi-pencil-square me-1"></i>{% trans %}Modificar Reserva{% endtrans %}
|
|
</a>
|
|
{% endif %}
|
|
|
|
{% if reservation.status.value == 'PENDING' %}
|
|
<form method="POST" action="{{ url_for('schedule.confirm_reservation', id=reservation.id) }}">
|
|
<button type="submit" class="btn btn-success" onclick="return confirm('Confirm this reservation?')">
|
|
<i class="bi bi-check-circle"></i> Confirm Reservation
|
|
</button>
|
|
</form>
|
|
{% endif %}
|
|
|
|
{% if reservation.can_be_cancelled() %}
|
|
<form method="POST" action="{{ url_for('schedule.cancel_reservation', id=reservation.id) }}">
|
|
<button type="submit" class="btn btn-danger" onclick="return confirm('Cancel this reservation?')">
|
|
<i class="bi bi-x-circle"></i> Cancel Reservation
|
|
</button>
|
|
</form>
|
|
{% endif %}
|
|
|
|
<a href="{{ url_for('schedule.list_reservations') }}" class="btn btn-outline-secondary">
|
|
<i class="bi bi-list"></i> View All Reservations
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Timestamps -->
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="card-body">
|
|
<div class="row text-muted small">
|
|
<div class="col-md-4">
|
|
<i class="bi bi-clock-history"></i>
|
|
Created: {{ reservation.created_at.strftime('%Y-%m-%d %H:%M:%S') }}
|
|
</div>
|
|
{% if reservation.updated_at %}
|
|
<div class="col-md-4">
|
|
<i class="bi bi-arrow-repeat"></i>
|
|
Updated: {{ reservation.updated_at.strftime('%Y-%m-%d %H:%M:%S') }}
|
|
</div>
|
|
{% endif %}
|
|
<div class="col-md-4">
|
|
<i class="bi bi-info-square"></i>
|
|
Reservation ID: #{{ reservation.id }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %} |