251 lines
7.6 KiB
HTML
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 %} |