kaauh_ats/templates/recruitment/interview_calendar.html
2025-10-13 17:13:56 +03:00

251 lines
7.6 KiB
HTML

<!-- templates/recruitment/interview_calendar.html -->
{% extends "base.html" %}
{% load static %}
{% 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-header {
background-color: var(--calendar-color);
color: white;
padding: 1rem;
border-radius: 0.25rem;
margin-bottom: 1rem;
}
.calendar-container {
background-color: white;
border-radius: 0.25rem;
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
padding: 1rem;
}
.fc-toolbar-title {
color: var(--calendar-color) !important;
}
.fc-button-primary {
background-color: var(--calendar-color) !important;
border-color: var(--calendar-color) !important;
}
.fc-button-primary:hover {
background-color: #004d56 !important;
border-color: #004d56 !important;
}
.fc-button-primary:not(:disabled):active, .fc-button-primary:not(:disabled).fc-button-active {
background-color: #003a40 !important;
border-color: #003a40 !important;
}
.fc-daygrid-day.fc-day-today {
background-color: var(--calendar-light) !important;
}
.fc-event-title {
font-weight: 500;
}
.status-badge {
font-size: 0.75rem;
padding: 0.25rem 0.5rem;
border-radius: 1rem;
}
.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;
}
.interview-details {
margin-top: 1rem;
}
.interview-details .card {
border-left: 4px solid var(--calendar-color);
}
.calendar-legend {
display: flex;
flex-wrap: wrap;
gap: 1rem;
margin-top: 1rem;
padding: 0.75rem;
background-color: #f8f9fa;
border-radius: 0.25rem;
}
.legend-item {
display: flex;
align-items: center;
gap: 0.5rem;
}
.legend-color {
width: 1rem;
height: 1rem;
border-radius: 0.25rem;
}
</style>
{% endblock %}
{% block content %}
<div class="container mt-4">
<div class="calendar-header">
<div class="d-flex justify-content-between align-items-center">
<h1 class="h3 mb-0">Interview Calendar</h1>
<div>
<span class="h5">{{ job.title }}</span>
</div>
</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>Scheduled</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background-color: #00a86b;"></div>
<span>Confirmed</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background-color: #e74c3c;"></div>
<span>Cancelled</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background-color: #95a5a6;"></div>
<span>Completed</span>
</div>
</div>
</div>
<div class="interview-details" id="interview-details" style="display: none;">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Interview Details</h5>
<button type="button" class="btn-close" id="close-details"></button>
</div>
<div class="card-body" id="interview-info">
<!-- Interview details will be loaded here -->
</div>
</div>
</div>
</div>
<!-- Include FullCalendar JS -->
<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');
var events = {{ events|safe }};
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
events: events,
eventClick: function(info) {
// Prevent default browser behavior
info.jsEvent.preventDefault();
// Show interview details
showInterviewDetails(info.event);
},
eventMouseEnter: function(info) {
// Change cursor to pointer on hover
document.body.style.cursor = 'pointer';
},
eventMouseLeave: function() {
// Reset cursor
document.body.style.cursor = 'default';
},
height: 'auto',
aspectRatio: 2,
eventDisplay: 'block',
displayEventTime: true,
displayEventEnd: true,
});
calendar.render();
// Function to show interview details
function showInterviewDetails(event) {
const detailsContainer = document.getElementById('interview-details');
const infoContainer = document.getElementById('interview-info');
const statusClass = `status-${event.extendedProps.status}`;
const statusText = event.extendedProps.status.charAt(0).toUpperCase() + event.extendedProps.status.slice(1);
let meetingInfo = '';
if (event.extendedProps.meeting_id) {
meetingInfo = `
<div class="mb-3">
<h6>Meeting Information</h6>
<p><strong>Meeting ID:</strong> ${event.extendedProps.meeting_id}</p>
<p><strong>Join URL:</strong> <a href="${event.extendedProps.join_url}" target="_blank">${event.extendedProps.join_url}</a></p>
</div>
`;
}
infoContainer.innerHTML = `
<div class="row">
<div class="col-md-6">
<h6>Candidate Information</h6>
<p><strong>Name:</strong> ${event.extendedProps.candidate}</p>
<p><strong>Email:</strong> ${event.extendedProps.email}</p>
</div>
<div class="col-md-6">
<h6>Interview Details</h6>
<p><strong>Date:</strong> ${event.start.toLocaleDateString()}</p>
<p><strong>Time:</strong> ${event.start.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})} - ${event.end.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</p>
<p><strong>Status:</strong> <span class="status-badge ${statusClass}">${statusText}</span></p>
</div>
</div>
${meetingInfo}
<div class="mt-3">
<a href="${event.url}" class="btn btn-primary btn-sm">View Full Details</a>
</div>
`;
detailsContainer.style.display = 'block';
// Scroll to details
detailsContainer.scrollIntoView({ behavior: 'smooth' });
}
// Close details button
document.getElementById('close-details').addEventListener('click', function() {
document.getElementById('interview-details').style.display = 'none';
});
});
</script>
{% endblock %}