<script>
document.addEventListener('DOMContentLoaded', function() {
// Elements
const calendarEl = document.getElementById('calendar');
const entryFormCard = document.getElementById('entryFormCard');
const addEntryBtn = document.getElementById('addEntryBtn');
const cancelEntryBtn = document.getElementById('cancelEntryBtn');
const refreshCalendarBtn = document.getElementById('refreshCalendarBtn');
// Event Modal Elements
const eventModal = document.getElementById('eventModal');
const eventModalBackdrop = document.getElementById('eventModalBackdrop');
const closeEventModal = document.getElementById('closeEventModal');
const closeEventModalBtn = document.getElementById('closeEventModalBtn');
const eventModalBody = document.getElementById('eventModalBody');
// Delete Confirmation Modal Elements
const deleteConfirmModal = document.getElementById('deleteConfirmModal');
const deleteConfirmBackdrop = document.getElementById('deleteConfirmBackdrop');
const closeDeleteConfirmModal = document.getElementById('closeDeleteConfirmModal');
const cancelDeleteBtn = document.getElementById('cancelDeleteBtn');
const confirmDeleteBtn = document.getElementById('confirmDeleteBtn');
const deleteEventBtn = document.getElementById('deleteEventBtn');
const currentEventId = document.getElementById('currentEventId');
// Movie Modal Elements
const movieModal = document.getElementById('movieModal');
const movieModalBackdrop = document.getElementById('movieModalBackdrop');
const closeMovieModal = document.getElementById('closeMovieModal');
const closeMovieModalBtn = document.getElementById('closeMovieModalBtn');
const movieModalBody = document.getElementById('movieModalBody');
const currentPlageId = document.getElementById('currentPlageId');
const assignMovieBtn = document.getElementById('assignMovieBtn');
const removeMovieBtn = document.getElementById('removeMovieBtn');
const movieList = document.getElementById('movieList');
const plageInfo = document.getElementById('plageInfo');
const assignMovieModalBtn = document.getElementById('assignMovieModalBtn');
// Data
const extras = <?php echo json_encode($extras, JSON_HEX_TAG); ?>;
const existing = <?php echo json_encode($plages, JSON_HEX_TAG); ?>;
const movies = <?php echo json_encode($movies, JSON_HEX_TAG); ?>;
let selectedMovieId = null;
// Initialize Calendar
const calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
selectable: true,
events: existing,
eventTimeFormat: {
hour: '2-digit',
minute: '2-digit',
hour12: false
},
dateClick: function(info) {
showForm(info.dateStr);
},
select: function(info) {
showForm(info.startStr);
},
eventClick: function(info) {
showEventDetails(info.event);
},
height: 'auto'
});
calendar.render();
// Show the entry form
function showForm(dateStr) {
entryFormCard.classList.remove('hidden');
document.getElementById('date').value = dateStr;
// Set default times
const now = new Date();
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
document.getElementById('start_time').value = `${hours}:${minutes}`;
// End time = +1 h by default
const endHour = (parseInt(hours) + 1) % 24;
document.getElementById('end_time').value = `${endHour.toString().padStart(2, '0')}:${minutes}`;
// Scroll for mobile
if (window.innerWidth < 1200) {
entryFormCard.scrollIntoView({ behavior: 'smooth' });
}
updateTotalDuration();
}
// Hide entry form
function hideEntryForm() {
entryFormCard.classList.add('hidden');
document.getElementById('entryForm').reset();
}
// Show event details
function showEventDetails(event) {
currentEventId.value = event.id;
const startDate = event.start.toLocaleDateString();
const startTime = event.start.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit', hour12: false});
const endTime = event.end.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit', hour12: false});
const extraTime = event.extendedProps.extraTime || 0;
const extraName = event.extendedProps.extraName || 'None';
const movieName = event.extendedProps.movieName || 'No movie assigned';
// Calculate duration
const durationMs = event.end - event.start;
const durationMin = Math.floor(durationMs / 60000);
const hours = Math.floor(durationMin / 60);
const minutes = durationMin % 60;
const durationFormatted = `${hours}h${minutes > 0 ? ' ' + minutes + 'm' : ''}`;
// Calculate total duration with extra time
const totalDurationMin = durationMin + parseInt(extraTime);
const totalHours = Math.floor(totalDurationMin / 60);
const totalMinutes = totalDurationMin % 60;
const totalDurationFormatted = `${totalHours}h${totalMinutes > 0 ? ' ' + totalMinutes + 'm' : ''}`;
eventModalBody.innerHTML = `
<div class="ts-event-detail">
<div class="ts-event-detail-icon">
<i class="fas fa-calendar-day"></i>
</div>
<div class="ts-event-detail-content">
<p class="ts-event-detail-label">Date</p>
<p class="ts-event-detail-value">${startDate}</p>
</div>
</div>
<div class="ts-event-detail">
<div class="ts-event-detail-icon">
<i class="fas fa-clock"></i>
</div>
<div class="ts-event-detail-content">
<p class="ts-event-detail-label">Time</p>
<p class="ts-event-detail-value">${startTime} - ${endTime}</p>
</div>
</div>
<div class="ts-event-detail">
<div class="ts-event-detail-icon">
<i class="fas fa-hourglass-half"></i>
</div>
<div class="ts-event-detail-content">
<p class="ts-event-detail-label">Duration</p>
<p class="ts-event-detail-value">${durationFormatted}</p>
</div>
</div>
<div class="ts-event-detail">
<div class="ts-event-detail-icon">
<i class="fas fa-tasks"></i>
</div>
<div class="ts-event-detail-content">
<p class="ts-event-detail-label">Activity Type</p>
<p class="ts-event-detail-value">${extraName}</p>
</div>
</div>
<div class="ts-event-detail">
<div class="ts-event-detail-icon">
<i class="fas fa-plus-circle"></i>
</div>
<div class="ts-event-detail-content">
<p class="ts-event-detail-label">Extra Time</p>
<p class="ts-event-detail-value">${extraTime > 0 ? extraTime + ' minutes' : 'None'}</p>
</div>
</div>
<div class="ts-event-detail">
<div class="ts-event-detail-icon">
<i class="fas fa-calculator"></i>
</div>
<div class="ts-event-detail-content">
<p class="ts-event-detail-label">Total Duration</p>
<p class="ts-event-detail-value">${totalDurationFormatted}</p>
</div>
</div>
<div class="ts-event-detail">
<div class="ts-event-detail-icon">
<i class="fas fa-film"></i>
</div>
<div class="ts-event-detail-content">
<p class="ts-event-detail-label">Assigned Movie</p>
<p class="ts-event-detail-value">${movieName}</p>
</div>
</div>
`;
eventModal.style.display = 'block';
eventModalBackdrop.style.display = 'block';
eventModal.style.animation = 'slideIn 0.3s forwards';
eventModalBackdrop.style.animation = 'fadeIn 0.3s forwards';
}
// Hide event details
function hideEventDetails() {
eventModal.style.display = 'none';
eventModalBackdrop.style.display = 'none';
}
// Update total duration
function updateTotalDuration() {
const startInput = document.getElementById('start_time');
const endInput = document.getElementById('end_time');
const extraTimeInput = document.getElementById('extra_time');
const totalDurationField = document.getElementById('total_duration');
if (startInput.value && endInput.value) {
const s = startInput.value.split(':');
const e = endInput.value.split(':');
const startMin = parseInt(s[0],10)*60 + parseInt(s[1],10);
const endMin = parseInt(e[0],10)*60 + parseInt(e[1],10);
const baseDur = Math.max(0, endMin - startMin);
const extraDur = parseInt(extraTimeInput.value,10) || 0;
const totalMin = baseDur + extraDur;
const hrs = Math.floor(totalMin/60);
const mins = totalMin % 60;
const formatted = hrs + 'h' + (mins > 0 ? ' ' + mins + 'm' : '');
totalDurationField.value = formatted;
}
}
// Function to calculate KDM status
function getKdmStatus(kdmEnd) {
if (!kdmEnd) return 'no-kdm';
const now = new Date();
const kdmDate = new Date(kdmEnd);
const diffTime = kdmDate - now;
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
if (diffDays < 0) return 'expired';
if (diffDays <= 7) return 'warning';
return 'good';
}
// Function to show movie selection modal
function showMovieSelection(event) {
currentPlageId.value = event.id;
selectedMovieId = event.extendedProps.movieId || null;
const startDate = event.start.toLocaleDateString();
const startTime = event.start.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit', hour12: false});
const endTime = event.end.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit', hour12: false});
const extraName = event.extendedProps.extraName || 'None';
const currentMovie = event.extendedProps.movieName || 'No movie assigned';
// Update plage info
plageInfo.innerHTML = `
<div class="ts-plage-summary">
<h4>Plage Details</h4>
<p><strong>Date:</strong> ${startDate}</p>
<p><strong>Time:</strong> ${startTime} - ${endTime}</p>
<p><strong>Activity:</strong> ${extraName}</p>
<p><strong>Current Movie:</strong> ${currentMovie}</p>
</div>
`;
// Generate movie list
let movieHtml = '';
movies.forEach(movie => {
const kdmStatus = getKdmStatus(movie.kdmEnd);
const isDisabled = kdmStatus === 'expired';
const isSelected = selectedMovieId == movie.pk_Film;
movieHtml += `
<div class="ts-movie-option ${kdmStatus} ${isSelected ? 'selected' : ''} ${isDisabled ? 'disabled' : ''}"
data-movie-id="${movie.pk_Film}"
${!isDisabled ? 'onclick="selectMovie(' + movie.pk_Film + ')"' : ''}>
<div class="ts-movie-info">
<h5>${movie.name}</h5>
<div class="ts-kdm-info">
${movie.kdmEnd ?
`<span class="ts-kdm-date">KDM expires: ${new Date(movie.kdmEnd).toLocaleDateString()}</span>` :
'<span class="ts-kdm-date">No KDM date set</span>'
}
</div>
</div>
<div class="ts-movie-status">
${isSelected ? '<i class="fas fa-check-circle"></i>' : ''}
${isDisabled ? '<i class="fas fa-ban"></i>' : ''}
</div>
</div>
`;
});
movieList.innerHTML = movieHtml;
// Update button states
updateAssignButton();
movieModal.style.display = 'block';
movieModalBackdrop.style.display = 'block';
movieModal.style.animation = 'slideIn 0.3s forwards';
movieModalBackdrop.style.animation = 'fadeIn 0.3s forwards';
}
// Function to select a movie
function selectMovie(movieId) {
selectedMovieId = movieId;
// Update visual selection
document.querySelectorAll('.ts-movie-option').forEach(option => {
option.classList.remove('selected');
option.querySelector('.ts-movie-status').innerHTML = '';
});
const selectedOption = document.querySelector(`[data-movie-id="${movieId}"]`);
if (selectedOption) {
selectedOption.classList.add('selected');
selectedOption.querySelector('.ts-movie-status').innerHTML = '<i class="fas fa-check-circle"></i>';
}
updateAssignButton();
}
// Function to update assign button state
function updateAssignButton() {
if (selectedMovieId) {
assignMovieBtn.disabled = false;
assignMovieBtn.innerHTML = '<i class="fas fa-film"></i> Assign Movie';
} else {
assignMovieBtn.disabled = true;
assignMovieBtn.innerHTML = '<i class="fas fa-film"></i> Select a Movie';
}
}
// Function to hide movie modal
function hideMovieModal() {
movieModal.style.display = 'none';
movieModalBackdrop.style.display = 'none';
selectedMovieId = null;
}
// Function to assign movie
function assignMovie() {
if (!selectedMovieId || !currentPlageId.value) return;
const form = document.createElement('form');
form.method = 'POST';
form.action = '?page=calendar';
const actionInput = document.createElement('input');
actionInput.type = 'hidden';
actionInput.name = 'action';
actionInput.value = 'assign_movie';
form.appendChild(actionInput);
const plageIdInput = document.createElement('input');
plageIdInput.type = 'hidden';
plageIdInput.name = 'plage_id';
plageIdInput.value = currentPlageId.value;
form.appendChild(plageIdInput);
const movieIdInput = document.createElement('input');
movieIdInput.type = 'hidden';
movieIdInput.name = 'movie_id';
movieIdInput.value = selectedMovieId;
form.appendChild(movieIdInput);
document.body.appendChild(form);
form.submit();
}
// Function to remove movie assignment
function removeMovie() {
if (!currentPlageId.value) return;
const form = document.createElement('form');
form.method = 'POST';
form.action = '?page=calendar';
const actionInput = document.createElement('input');
actionInput.type = 'hidden';
actionInput.name = 'action';
actionInput.value = 'assign_movie';
form.appendChild(actionInput);
const plageIdInput = document.createElement('input');
plageIdInput.type = 'hidden';
plageIdInput.name = 'plage_id';
plageIdInput.value = currentPlageId.value;
form.appendChild(plageIdInput);
const movieIdInput = document.createElement('input');
movieIdInput.type = 'hidden';
movieIdInput.name = 'movie_id';
movieIdInput.value = '';
form.appendChild(movieIdInput);
document.body.appendChild(form);
form.submit();
}
// Hide delete confirmation modal
function hideDeleteConfirmModal() {
deleteConfirmModal.style.display = 'none';
deleteConfirmBackdrop.style.display = 'none';
}
// Event listeners
addEntryBtn.addEventListener('click', function() {
// Use today's date as default
const today = new Date().toISOString().split('T')[0];
showForm(today);
});
cancelEntryBtn.addEventListener('click', hideEntryForm);
refreshCalendarBtn.addEventListener('click', function() {
calendar.refetchEvents();
});
// Event modal listeners
closeEventModal.addEventListener('click', hideEventDetails);
closeEventModalBtn.addEventListener('click', hideEventDetails);
eventModalBackdrop.addEventListener('click', hideEventDetails);
// Delete button in event modal
deleteEventBtn.addEventListener('click', function() {
// Hide event details modal
eventModal.style.display = 'none';
// Show delete confirmation modal
deleteConfirmModal.style.display = 'block';
deleteConfirmBackdrop.style.display = 'block';
deleteConfirmModal.style.animation = 'slideIn 0.3s forwards';
deleteConfirmBackdrop.style.animation = 'fadeIn 0.3s forwards';
});
// Delete confirmation modal listeners
closeDeleteConfirmModal.addEventListener('click', hideDeleteConfirmModal);
cancelDeleteBtn.addEventListener('click', hideDeleteConfirmModal);
deleteConfirmBackdrop.addEventListener('click', hideDeleteConfirmModal);
// Confirm delete button
confirmDeleteBtn.addEventListener('click', function() {
const eventId = currentEventId.value;
if (eventId) {
// Create a hidden form that will post back to the same page
const form = document.createElement('form');
form.method = 'POST';
form.action = '?page=calendar';
const actionInput = document.createElement('input');
actionInput.type = 'hidden';
actionInput.name = 'action';
actionInput.value = 'delete_event';
form.appendChild(actionInput);
const eventIdInput = document.createElement('input');
eventIdInput.type = 'hidden';
eventIdInput.name = 'event_id';
eventIdInput.value = eventId;
form.appendChild(eventIdInput);
// Append to body and submit
document.body.appendChild(form);
form.submit();
}
});
// Form input listeners
const startTimeInput = document.getElementById('start_time');
const endTimeInput = document.getElementById('end_time');
const extraTimeInput = document.getElementById('extra_time');
const extraSelect = document.getElementById('extra_id');
startTimeInput.addEventListener('change', updateTotalDuration);
endTimeInput.addEventListener('change', updateTotalDuration);
extraTimeInput.addEventListener('input', updateTotalDuration);
extraSelect.addEventListener('change', function() {
const selected = extraSelect.options[extraSelect.selectedIndex];
if (selected && selected.value) {
const defaultTime = selected.getAttribute('data-defaulttime') || 0;
extraTimeInput.value = defaultTime;
} else {
extraTimeInput.value = 0;
}
updateTotalDuration();
});
// Form validation
document.getElementById('entryForm').addEventListener('submit', function(e) {
const startTime = document.getElementById('start_time').value;
const endTime = document.getElementById('end_time').value;
if (startTime >= endTime) {
e.preventDefault();
alert('End time must be after start time');
}
});
// Movie Modal Event Listeners
closeMovieModal.addEventListener('click', hideMovieModal);
closeMovieModalBtn.addEventListener('click', hideMovieModal);
movieModalBackdrop.addEventListener('click', hideMovieModal);
assignMovieBtn.addEventListener('click', assignMovie);
removeMovieBtn.addEventListener('click', removeMovie);
assignMovieModalBtn.addEventListener('click', function() {
// Get the current event from the stored ID
const eventId = currentEventId.value;
if (eventId) {
// Find the event data from our existing array
const eventData = existing.find(e => e.id == eventId);
if (eventData) {
// Create a mock event object with the necessary properties
const mockEvent = {
id: eventData.id,
start: new Date(eventData.start),
end: new Date(eventData.end),
extendedProps: eventData.extendedProps
};
hideEventDetails();
showMovieSelection(mockEvent);
}
}
});
// Make selectMovie function global
window.selectMovie = selectMovie;
});
</script>