205 lines
7.5 KiB
HTML
205 lines
7.5 KiB
HTML
{% extends "base.html" %}
|
|
{% load static i18n %}
|
|
{% block title %} {% trans "Interview Calendar" %} {% endblock %}
|
|
|
|
{% block customCSS %}
|
|
<link href="https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/main.min.css" rel="stylesheet">
|
|
<style>
|
|
:root {
|
|
--calendar-color: #00636e;
|
|
--calendar-light: rgba(0, 99, 110, 0.1);
|
|
--calendar-hover: rgba(0, 99, 110, 0.2);
|
|
}
|
|
|
|
.calendar-container {
|
|
background-color: white;
|
|
border-radius: 0.75rem;
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
|
padding: 1.5rem;
|
|
border: 1px solid var(--kaauh-border);
|
|
}
|
|
|
|
.fc-toolbar-title {
|
|
color: var(--calendar-color) !important;
|
|
font-weight: 700 !important;
|
|
}
|
|
|
|
.fc-button-primary {
|
|
background-color: var(--calendar-color) !important;
|
|
border-color: var(--calendar-color) !important;
|
|
text-transform: capitalize;
|
|
}
|
|
|
|
.fc-event {
|
|
cursor: pointer;
|
|
padding: 2px 5px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.status-badge {
|
|
font-size: 0.75rem;
|
|
padding: 0.25rem 0.6rem;
|
|
border-radius: 1rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.status-scheduled { background-color: #e3f2fd; color: #0d47a1; }
|
|
.status-confirmed { background-color: #e8f5e9; color: #1b5e20; }
|
|
.status-cancelled { background-color: #ffebee; color: #b71c1c; }
|
|
.status-completed { background-color: #f5f5f5; color: #424242; }
|
|
|
|
.calendar-legend {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 1.5rem;
|
|
margin-top: 1.5rem;
|
|
padding: 1rem;
|
|
background-color: #f9fbfd;
|
|
border-radius: 0.5rem;
|
|
border: 1px dashed #dee2e6;
|
|
}
|
|
|
|
.legend-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
font-size: 0.85rem;
|
|
color: #495057;
|
|
}
|
|
|
|
.legend-color {
|
|
width: 12px;
|
|
height: 12px;
|
|
border-radius: 50%;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<div>
|
|
<h1 class="h3 mb-1 page-header">{% trans "Interview Calendar" %}</h1>
|
|
<p class="text-muted mb-0">{{ job.title|default:"Global Schedule" }}</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-muted small mb-0">Tenhal | تنحل</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="calendar-container">
|
|
<div id="calendar"></div>
|
|
|
|
<div class="calendar-legend">
|
|
<div class="legend-item">
|
|
<div class="legend-color" style="background-color: #00636e;"></div>
|
|
<span>{% trans "Scheduled" %}</span>
|
|
</div>
|
|
<div class="legend-item">
|
|
<div class="legend-color" style="background-color: #00a86b;"></div>
|
|
<span>{% trans "Confirmed" %}</span>
|
|
</div>
|
|
<div class="legend-item">
|
|
<div class="legend-color" style="background-color: #e74c3c;"></div>
|
|
<span>{% trans "Cancelled" %}</span>
|
|
</div>
|
|
<div class="legend-item">
|
|
<div class="legend-color" style="background-color: #95a5a6;"></div>
|
|
<span>{% trans "Completed" %}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="interview-details mt-4" id="interview-details" style="display: none;">
|
|
<div class="card shadow-sm border-start border-4 border-info">
|
|
<div class="card-header bg-white d-flex justify-content-between align-items-center py-3">
|
|
<h5 class="mb-0 text-primary-theme"><i class="fas fa-info-circle me-2"></i>{% trans "Interview Details" %}</h5>
|
|
<button type="button" class="btn-close" id="close-details"></button>
|
|
</div>
|
|
<div class="card-body" id="interview-info">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{ events|json_script:"calendar-events-data" }}
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/main.min.js"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
var calendarEl = document.getElementById('calendar');
|
|
|
|
// FIX: Parse the JSON script to avoid "None is not defined" error
|
|
const eventsData = JSON.parse(document.getElementById('calendar-events-data').textContent);
|
|
|
|
var calendar = new FullCalendar.Calendar(calendarEl, {
|
|
initialView: 'dayGridMonth',
|
|
headerToolbar: {
|
|
left: 'prev,next today',
|
|
center: 'title',
|
|
right: 'dayGridMonth,timeGridWeek,timeGridDay'
|
|
},
|
|
events: eventsData,
|
|
eventClick: function(info) {
|
|
info.jsEvent.preventDefault();
|
|
showInterviewDetails(info.event);
|
|
},
|
|
height: 'auto',
|
|
eventDisplay: 'block',
|
|
displayEventTime: true,
|
|
});
|
|
|
|
calendar.render();
|
|
|
|
function showInterviewDetails(event) {
|
|
const detailsContainer = document.getElementById('interview-details');
|
|
const infoContainer = document.getElementById('interview-info');
|
|
|
|
const status = event.extendedProps.status || 'scheduled';
|
|
const statusClass = `status-${status}`;
|
|
const statusText = status.charAt(0).toUpperCase() + status.slice(1);
|
|
|
|
let meetingInfo = '';
|
|
// FIX: Corrected translation tags and property checks
|
|
if (event.extendedProps.meeting_id) {
|
|
meetingInfo = `
|
|
<div class="mt-3 p-3 bg-light rounded border">
|
|
<h6 class="text-primary-theme"><i class="fas fa-video me-2"></i>{% trans "Meeting Information" %}</h6>
|
|
<p class="mb-1"><strong>{% trans "Meeting ID:" %}</strong> ${event.extendedProps.meeting_id}</p>
|
|
<p class="mb-0"><strong>{% trans "Join URL:" %}</strong> <a href="${event.extendedProps.join_url}" target="_blank" class="text-break">${event.extendedProps.join_url}</a></p>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
infoContainer.innerHTML = `
|
|
<div class="row">
|
|
<div class="col-md-6 border-end">
|
|
<h6 class="text-muted text-uppercase small fw-bold">{% trans "Candidate" %}</h6>
|
|
<p class="mb-1"><strong>{% trans "Name:" %}</strong> ${event.extendedProps.candidate}</p>
|
|
<p><strong>{% trans "Email:" %}</strong> ${event.extendedProps.email}</p>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6 class="text-muted text-uppercase small fw-bold">{% trans "Schedule" %}</h6>
|
|
<p class="mb-1"><strong>{% trans "Date:" %}</strong> ${event.start.toLocaleDateString()}</p>
|
|
<p class="mb-1"><strong>{% trans "Time:" %}</strong> ${event.start.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</p>
|
|
<p><strong>{% trans "Status:" %}</strong> <span class="status-badge ${statusClass}">${statusText}</span></p>
|
|
</div>
|
|
</div>
|
|
${meetingInfo}
|
|
<div class="mt-4 pt-3 border-top">
|
|
<a href="${event.url}" class="btn btn-main-action btn-sm">
|
|
<i class="fas fa-external-link-alt me-1"></i> {% trans "View Full Application" %}
|
|
</a>
|
|
</div>
|
|
`;
|
|
|
|
detailsContainer.style.display = 'block';
|
|
detailsContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
}
|
|
|
|
document.getElementById('close-details').addEventListener('click', function() {
|
|
document.getElementById('interview-details').style.display = 'none';
|
|
});
|
|
});
|
|
</script>
|
|
{% endblock %} |