176 lines
7.2 KiB
HTML
176 lines
7.2 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}{% trans %}Reservations Calendar{% endtrans %} - Edu-Space Admin{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid pt-5 mt-4">
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<h1 class="h3 mb-0">
|
|
<i class="bi bi-calendar3 text-primary"></i> {% trans %}Reservations Calendar{% endtrans %}
|
|
<small class="text-muted ms-2">{% trans %}View & Manage Reservations{% endtrans %}</small>
|
|
</h1>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="card-header bg-body-tertiary border-0 py-3">
|
|
<div class="row align-items-center">
|
|
<div class="col-md-6">
|
|
<h5 class="mb-0 h6 fw-bold">
|
|
<i class="bi bi-calendar-week text-info me-2"></i> {% trans %}Reservations Calendar{% endtrans %}
|
|
</h5>
|
|
</div>
|
|
<div class="col-md-6 text-end">
|
|
<a href="{{ url_for('schedule.add_reservation') }}" class="btn btn-primary">
|
|
<i class="bi bi-plus-circle"></i> {% trans %}Add Reservation{% endtrans %}
|
|
</a>
|
|
<a href="{{ url_for('schedule.list_reservations') }}" class="btn btn-outline-secondary">
|
|
<i class="bi bi-list"></i> {% trans %}List View{% endtrans %}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<!-- Legend -->
|
|
<div class="mb-3">
|
|
<div class="d-flex gap-3 flex-wrap">
|
|
<div class="d-flex align-items-center">
|
|
<span class="badge bg-success me-2" style="width: 20px; height: 20px;"></span>
|
|
<small class="text-muted">{% trans %}Confirmed{% endtrans %}</small>
|
|
</div>
|
|
<div class="d-flex align-items-center">
|
|
<span class="badge bg-warning me-2" style="width: 20px; height: 20px;"></span>
|
|
<small class="text-muted">{% trans %}Pending{% endtrans %}</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Calendar -->
|
|
<div id="calendar"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Reservation Details Modal -->
|
|
<div class="modal fade" id="reservationModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">{% trans %}Reservation Details{% endtrans %}</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body" id="reservationDetails">
|
|
<!-- Content will be loaded dynamically -->
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans %}Close{% endtrans %}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<link href="https://cdn.jsdelivr.net/npm/fullcalendar@5.11.0/main.min.css" rel="stylesheet">
|
|
<style>
|
|
#calendar {
|
|
margin-top: 20px;
|
|
}
|
|
.fc-event {
|
|
cursor: pointer;
|
|
border: none !important;
|
|
padding: 2px 6px !important;
|
|
font-size: 12px !important;
|
|
}
|
|
.fc-event-pending {
|
|
background-color: #ffc107 !important;
|
|
}
|
|
.fc-event-confirmed {
|
|
background-color: #28a745 !important;
|
|
}
|
|
.fc-daygrid-day.fc-day-today {
|
|
background-color: rgba(102, 126, 234, 0.1) !important;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.11.0/main.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.11.0/locales-all.min.js"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
var calendarEl = document.getElementById('calendar');
|
|
var currentLang = '{{ session.get("language", "es") }}';
|
|
|
|
var calendar = new FullCalendar.Calendar(calendarEl, {
|
|
locale: currentLang,
|
|
initialView: 'timeGridWeek',
|
|
headerToolbar: {
|
|
left: 'prev,next today',
|
|
center: 'title',
|
|
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
|
|
},
|
|
eventTimeFormat: {
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
hour12: false
|
|
},
|
|
slotMinTime: '07:00:00',
|
|
slotMaxTime: '22:00:00',
|
|
height: 'auto',
|
|
eventClick: function(info) {
|
|
if (info.event.url) {
|
|
loadReservationDetails(info.event.url);
|
|
return false;
|
|
}
|
|
},
|
|
events: '{{ url_for("schedule.calendar_data") }}',
|
|
loading: function(bool) {
|
|
}
|
|
});
|
|
|
|
calendar.render();
|
|
|
|
function loadReservationDetails(url) {
|
|
$.get(url)
|
|
.done(function(data) {
|
|
var isEs = currentLang === 'es';
|
|
var html = `
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6 class="text-muted mb-2">${isEs ? 'Aula' : 'Classroom'}</h6>
|
|
<p class="fw-bold">${data.classroom.code} - ${data.classroom.name || ''}</p>
|
|
<p><i class="bi bi-building text-primary"></i> ${data.classroom.building} - ${isEs ? 'Piso' : 'Floor'} ${data.classroom.floor}</p>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6 class="text-muted mb-2">${isEs ? 'Materia' : 'Subject'}</h6>
|
|
<p class="fw-bold">${data.commission.subject.code} - ${data.commission.subject.name}</p>
|
|
<p><i class="bi bi-person text-info"></i> ${data.commission.teacher_name}</p>
|
|
</div>
|
|
</div>
|
|
<div class="row mt-3">
|
|
<div class="col-md-6">
|
|
<h6 class="text-muted mb-2">${isEs ? 'Horario' : 'Schedule'}</h6>
|
|
<p><i class="bi bi-clock text-warning"></i> ${new Date(data.start_time).toLocaleString()}</p>
|
|
<p><i class="bi bi-clock text-success"></i> ${new Date(data.end_time).toLocaleString()}</p>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6 class="text-muted mb-2">${isEs ? 'Detalles' : 'Details'}</h6>
|
|
<p><i class="bi bi-people text-primary"></i> ${data.expected_attendees} ${isEs ? 'asistentes' : 'attendees'}</p>
|
|
<p><span class="badge bg-${data.status === 'CONFIRMED' ? 'success' : 'warning'}">${data.status}</span></p>
|
|
</div>
|
|
</div>
|
|
${data.notes ? `<div class="row mt-3"><div class="col-12"><h6 class="text-muted mb-2">${isEs ? 'Notas' : 'Notes'}</h6><p>${data.notes}</p></div></div>` : ''}
|
|
`;
|
|
$('#reservationDetails').html(html);
|
|
$('#reservationModal').modal('show');
|
|
})
|
|
.fail(function() {
|
|
$('#reservationDetails').html('<p class="text-danger">${isEs ? "Error al cargar los detalles de la reserva." : "Error loading reservation details."}</p>');
|
|
$('#reservationModal').modal('show');
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %} |