import { deleteAppointment, confirmCarriedOut, getUsersByTermExcept, removeRequestAndUpdateUser, removeAppointment, makeReservation ,displayDiv} from './shared.js'; let calendar = document.querySelector('.calendar') let importantDate; const month_names = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] const modal = document.getElementById('popupModal'); const cancelBtn = document.getElementById('cancelBtn'); const approveBtn = document.getElementById('approveBtn'); const closeSpan = document.querySelector('.close'); const deleteBtn=document.getElementById("temporal-deletion"); function resetFields() { document.getElementById('start-time').selectedIndex = 0; document.getElementById('timePicker').selectedIndex=0; document.getElementById('end-time').selectedIndex=0; document.getElementById('time-interval').value = ''; document.getElementById('start-date').value = ''; document.getElementById('end-date').value=''; document.getElementById('delete-date-from').value=''; document.getElementById('delete-date-to').value=''; } function checkOverlap(existingTimes, newTime) { const [newHour, newMinutes] = newTime.split(':').map(Number); const newStartTime = new Date(0, 0, 0, newHour, newMinutes); const newEndTime = new Date(newStartTime); newEndTime.setHours(newEndTime.getHours() + 1); return existingTimes.some(existingTime => { const [existingHour, existingMinutes] = existingTime.split(':').map(Number); const existingStartTime = new Date(0, 0, 0, existingHour, existingMinutes); const existingEndTime = new Date(existingStartTime); existingEndTime.setHours(existingEndTime.getHours() + 1); return newStartTime < existingEndTime && newEndTime > existingStartTime; }); } async function getExistingAppointmentsMapped() { let existingAppointments; try { const response = await fetch(`/api/appointments/getAllAppointments`); if (!response.ok) { throw new Error('Failed to fetch appointments'); } existingAppointments = await response.json(); console.log(existingAppointments); } catch (error) { console.error(error); } const appointmentMap = new Map(); existingAppointments.forEach(appointment => { const dateTime = new Date(appointment.term); const date = dateTime.toISOString().split('T')[0]; const time = dateTime.toTimeString().substring(0, 5); if (appointmentMap.has(date)) { appointmentMap.get(date).push(time); } else { appointmentMap.set(date, [time]); } }); return appointmentMap; } function createAppointments(startDate, endDate, startTime, endTime, interval) { let appointments = []; let currentDate = new Date(startDate); let endDateObj = new Date(endDate); const [startHour, startMinute] = startTime.split(':').map(Number); const [endHour, endMinute] = endTime.split(':').map(Number); while (currentDate <= endDateObj) { let currentStartTime = new Date(currentDate); currentStartTime.setHours(startHour, startMinute, 0, 0); let currentEndTime = new Date(currentDate); currentEndTime.setHours(endHour - 1, endMinute+interval, 0, 0); while (currentStartTime < currentEndTime) { const formattedDate = currentDate.toISOString().split('T')[0]; appointments.push({ date: formattedDate, time: currentStartTime.toTimeString().substring(0, 5) }); currentStartTime.setMinutes(currentStartTime.getMinutes() + interval + 60); } currentDate.setDate(currentDate.getDate() + 1); } return appointments; } function formatConflictAlert(conflictingAppointments) { const appointmentList = Array.isArray(conflictingAppointments) ? conflictingAppointments : [conflictingAppointments]; const formattedAppointments = appointmentList.map(appointment => `Датум: ${appointment.date}, Време: ${appointment.time}` ); const alertMessage = [ "Неуспешно креирање на термини:", ...formattedAppointments ].filter(Boolean).join('\n'); return alertMessage.trim(); } async function createAutoAppointments(appointments) { const requestBody = appointments.map(appointment => ({ date: appointment.date, time: appointment.time, })); await fetch(`/api/appointments/create`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(requestBody) // Send all appointments in one request }); } document.getElementById('create-appointments').addEventListener('click', async function () { const startDate = document.getElementById('start-date').value; const endDate = document.getElementById('end-date').value; const startTime = document.getElementById('start-time').value; const endTime = document.getElementById('end-time').value; const interval = parseInt(document.getElementById('time-interval').value); if (!startDate || !endDate || !startTime || !endTime || !interval) { alert("Please fill out all the fields."); return; } const appointments = createAppointments(startDate, endDate, startTime, endTime, interval); console.log('Generated Appointments:', appointments); const existingMapped = await getExistingAppointmentsMapped(); const conflictingAppointments = []; const successfulAppointments = []; appointments.forEach(newAppointment => { const { date, time } = newAppointment; if (existingMapped.has(date)) { const existingTimes = existingMapped.get(date); if (checkOverlap(existingTimes, time)) { conflictingAppointments.push(newAppointment); // Add to conflict list if overlaps } else { successfulAppointments.push(newAppointment); } } else { successfulAppointments.push(newAppointment); } }); console.log(conflictingAppointments); console.log(successfulAppointments); if(successfulAppointments.length>0){ await createAutoAppointments(successfulAppointments); } if (conflictingAppointments.length > 0) { const alertMessage = formatConflictAlert(conflictingAppointments); alert(alertMessage); } resetFields(); }); cancelBtn.addEventListener('click', () => { modal.style.display = 'none'; }); closeSpan.addEventListener('click', () => { modal.style.display = 'none'; }); deleteBtn.addEventListener('click',()=>{ deleteAppointment(deleteBtn.getAttribute("term"),deleteBtn.getAttribute("type")); }) window.addEventListener('click', (event) => { if (event.target === modal) { modal.style.display = 'none'; } }); function cleanAssets() { const ids = ['request-assets', 'appointment-assets']; ids.forEach((id) => { const element = document.getElementById(id); if (element && element.style.display !== 'none') { element.style.display = 'none'; } }); } async function isAppointmentReserved(dateTime) { try { const response = await fetch(`/api/appointments/isReserved?term=${dateTime}`); return await response.json(); } catch (error) { console.error('Error checking if appointment reserved:', error); return false; } } async function isAppointmentEmpty(dateTime) { try { const response = await fetch(`/api/requests/isEmpty?term=${dateTime}`); return await response.json(); } catch (error) { console.error('Error checking if no requests:', error); return false; } } function cleanData(bodyId){ const element = document.getElementById(bodyId); while (element.firstChild) { element.removeChild(element.firstChild); } } function createLines(data,dateTime,whichOne){ cleanData(whichOne) if(!Array.isArray(data)){ data=[data]; } let requestedElement=document.getElementById(whichOne); data.forEach(item => { const requestedRow = document.createElement('tr'); const usernameTd = document.createElement('td'); usernameTd.textContent = item.username; requestedRow.appendChild(usernameTd); const nameTd = document.createElement('td'); nameTd.textContent = item.name; requestedRow.appendChild(nameTd); const surnameTd = document.createElement('td'); surnameTd.textContent = item.surname; requestedRow.appendChild(surnameTd); const additionalInfoTd = document.createElement('td'); additionalInfoTd.textContent = item.additionalInfo; requestedRow.appendChild(additionalInfoTd); const couponCodeTd = document.createElement('td'); couponCodeTd.textContent = item.couponCode; requestedRow.appendChild(couponCodeTd); requestedElement.appendChild(requestedRow); displayDiv(dateTime); }) } function getAllRequests(dateTime,containerId){ let url; if(containerId === "approved"){ url = `/api/appointments/listApprovedRequest?term=${dateTime}`; } else { url = `/api/requests/listRequests?term=${dateTime}`; } fetch(url) .then(response => response.json()) .then(data => { createLines(data,dateTime,containerId) }) .catch(error => { console.error('Error fetching requests:', error); }); } function createActiveAppointments(data){ const frameElement=document.getElementById("frame"); frameElement.innerHTML = ''; document.getElementById("approved-table").style.display = 'none'; document.getElementById("requested-table").style.display = 'none'; data.forEach(item => { const itemDiv = document.createElement('div'); itemDiv.style.border = '1px solid black'; itemDiv.style.padding = '20px'; itemDiv.style.display = 'inline-block'; itemDiv.style.marginRight = '10px'; const appointmentDate = new Date(item.localDateTime); const timeOptions = { hour: '2-digit', minute: '2-digit', hour12: false }; itemDiv.textContent = appointmentDate.toLocaleTimeString([], timeOptions); itemDiv.addEventListener('click', async () => { try{ const isReserved=await isAppointmentReserved(item.localDateTime); const isEmpty=await isAppointmentEmpty(item.localDateTime); cleanAssets(); cleanData("approved") cleanData("requested") if (isReserved) { document.getElementById("approved-table").style.display = 'block'; document.getElementById("requested-table").style.display = 'none'; getAllRequests(item.localDateTime,"approved",""); document.getElementById("appointment-assets").style.display='block'; deleteBtn.style.display='block'; deleteBtn.setAttribute("term",item.localDateTime); deleteBtn.setAttribute("type","cancelledAppointmentByAdmin"); //da go isprogramirash delete-approval document.getElementById("delete-approval").addEventListener('click', function() { removeAppointment(item.localDateTime,"cancelledAppointmentByAdmin"); }); document.getElementById("approve-carried-out").addEventListener('click', function() { modal.style.display = 'flex'; approveBtn.addEventListener('click', () => { const userInput = document.getElementById('userInput').value; confirmCarriedOut(item.localDateTime,userInput); modal.style.display = 'none'; }); }); } else if(!isEmpty){ document.getElementById("approved-table").style.display = 'none'; document.getElementById("requested-table").style.display = 'block'; getAllRequests(item.localDateTime,"requested",""); document.getElementById("request-assets").style.display='block'; deleteBtn.style.display='block'; deleteBtn.setAttribute("term",item.localDateTime); deleteBtn.setAttribute("type","rejected"); } else{ document.getElementById("approved-table").style.display = 'none'; document.getElementById("requested-table").style.display = 'none'; deleteBtn.style.display='block'; deleteBtn.setAttribute("term",item.localDateTime); } } catch(error){ console.error('Error checking appointment reservation:', error); } }); frameElement.appendChild(itemDiv); }); } function fetchAppointments(date){ deleteBtn.style.display='none'; fetch(`/api/appointments/listAppointments?date=${date}`) .then(response => response.json()) .then(data => { createActiveAppointments(data); }) .catch(error => { console.error('Error fetching appointments:', error); }); } const isLeapYear = (year) => { return (year % 4 === 0 && year % 100 !== 0 && year % 400 !== 0) || (year % 100 === 0 && year % 400 ===0) } const getFebDays = (year) => { return isLeapYear(year) ? 29 : 28 } const generateCalendar = (month, year) => { let calendar_days = calendar.querySelector('.calendar-days') let calendar_header_year = calendar.querySelector('#year') let days_of_month = [31, getFebDays(year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] calendar_days.innerHTML = '' let currDate = new Date() // if (!month) month = currDate.getMonth() console.log(month); if (typeof month !== 'number') month = currDate.getMonth(); if (!year) year = currDate.getFullYear() let curr_month = `${month_names[month]}` month_picker.innerHTML = curr_month calendar_header_year.innerHTML = year // get first day of month let first_day = new Date(year, month, 1) for (let i = 0; i <= days_of_month[month] + first_day.getDay() - 1; i++) { let day = document.createElement('div') if (i >= first_day.getDay()) { day.classList.add('calendar-day-hover') day.innerHTML = i - first_day.getDay() + 1; day.innerHTML += ` `; let selectedDate = `${year}-${(month + 1).toString().padStart(2, '0')}-${(i - first_day.getDay() + 1).toString().padStart(2, '0')}`; if (i - first_day.getDay() + 1 === currDate.getDate() && year === currDate.getFullYear() && month === currDate.getMonth()) { day.classList.add('curr-date') importantDate=selectedDate; document.getElementById("insert-date").innerText=importantDate; fetchAppointments(importantDate); } day.addEventListener('click', () => { let temp=document.getElementsByClassName('curr-date'); Array.from(temp).forEach(element => { element.classList.remove('curr-date'); }); importantDate=selectedDate; let daySpan= document.getElementById("insert-date"); daySpan.innerText=""; daySpan.innerText=importantDate; day.classList.add('curr-date'); fetchAppointments(importantDate); cleanAssets(); cleanData("approved") cleanData("requested") resetFields(); }); } calendar_days.appendChild(day) } } let month_list = calendar.querySelector('.month-list') month_names.forEach((e, index) => { let month = document.createElement('div') month.innerHTML = `