kaauh_ats/templates/recruitment/interview_calendar.html
2025-12-24 03:05:48 +03:00

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 %}