var year = 2025 var month = 8 const monthNames = ["", "January", "February", "March", "April", "May", "June","July", "August", "September", "October", "November", "December"]; var eventsByDay = { 3: ["Chicken Stir Fry", "Salad"], 8: ["Spaghetti Bolognese"], 12: ["Fish Tacos", "Rice", "Beans"], 31: ['Brats'] }; async function changeSite(site){ console.log(site) const response = await fetch(`/changeSite`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ site: site, }), }); data = await response.json(); transaction_status = "success" if (data.error){ transaction_status = "danger" } UIkit.notification({ message: data.message, status: transaction_status, pos: 'top-right', timeout: 5000 }); location.reload(true) } async function getEventsByMonth() { const url = new URL('/planner/api/getEventsByMonth', window.location.origin); url.searchParams.append('year', year); url.searchParams.append('month', month); const response = await fetch(url); data = await response.json(); return data.events; } async function getEventByUUID(event_uuid) { const url = new URL('/planner/api/getEventByUUID', window.location.origin); url.searchParams.append('event_uuid', event_uuid); const response = await fetch(url); data = await response.json(); return data.event; } async function parseEvents(events) { eventsByDay = {} for (let i = 0; i < events.length; i++){ console.log(`new event -- ${events[i].event_shortname}`) let event_date_start = new Date(events[i].event_date_start) let event_date_end = new Date(events[i].event_date_end) let this_month = month let start_day = event_date_start.getUTCDate() let start_month = event_date_start.getUTCMonth() + 1 let end_day = event_date_end.getUTCDate() let end_month = event_date_end.getUTCMonth() + 1 if(start_month !== this_month){ start_day = 1 } if(end_month !== this_month){ end_day = new Date(year, month, 0).getUTCDate(); } for (let y = start_day; y <= end_day; y++){ if (!eventsByDay[y]) { eventsByDay[y] = []; } let dayarray = eventsByDay[y] dayarray.push(events[i]) eventsByDay[y] = dayarray } } console.log(eventsByDay) } document.addEventListener('DOMContentLoaded', async function() { let today = new Date(); year = today.getFullYear(); month = today.getMonth() + 1; await setupCalendarAndEvents() }) async function setupCalendarAndEvents(){ console.log(year, month) events = await getEventsByMonth() await parseEvents(events) await createCalender() document.getElementById('calender_table').addEventListener('contextmenu', function(e) { e.preventDefault(); let recipeLabel = e.target.closest('.recipe-label'); let calendarCell = e.target.closest('.calendar-cell'); let customLabel = e.target.closest('.custom-label'); if (recipeLabel) { recipeLabel.classList.add('recipe-label-selected') let rect = recipeLabel.getBoundingClientRect(); let scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; let scrollTop = window.pageYOffset || document.documentElement.scrollTop; let menuX = rect.left + scrollLeft; let menuY = rect.bottom + scrollTop; showContextMenuForEvent(recipeLabel, menuX, menuY); } else if (customLabel) { customLabel.classList.add('custom-label-selected') let rect = customLabel.getBoundingClientRect(); let scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; let scrollTop = window.pageYOffset || document.documentElement.scrollTop; let menuX = rect.left + scrollLeft; let menuY = rect.bottom + scrollTop; showContextMenuForEvent(customLabel, menuX, menuY); } else if (calendarCell) { calendarCell.classList.add('calendar-cell-selected') let rect = calendarCell.getBoundingClientRect(); let scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; let scrollTop = window.pageYOffset || document.documentElement.scrollTop; let menuX = rect.left + scrollLeft; let menuY = rect.bottom + scrollTop; showContextMenuForCell(calendarCell, menuX, menuY); } else { hideContextMenu(); } }); } async function createCalender() { let calender_container = document.getElementById('calendar_container') calender_container.innerHTML = "" let firstDay = new Date(year, month - 1, 1); let numDays = new Date(year, month, 0).getDate(); let startDay = firstDay.getDay(); let calender_table = document.createElement('table') calender_table.setAttribute('id', 'calender_table') calender_table.setAttribute('class', 'uk-table uk-table-middle uk-table-large uk-table-responsive') let table_headers = document.createElement('thead') table_headers.innerHTML = `SundayMondayTuesdayWednesdayThursdayFridaySaturday` calender_table.append(table_headers) let tableRow = document.createElement('tr') for (let i = 0; i < startDay; i++){ let table_cell = document.createElement('td') table_cell.setAttribute('class', 'uk-table-expand uk-visible@m calendar-cell-empty') tableRow.append(table_cell) } console.log(eventsByDay) for (let day = 1; day <= numDays; day++) { let table_cell = document.createElement('td') let eventsHTML = ""; if (eventsByDay[day]) { eventsByDay[day].forEach(event => { if(event.event_type==="recipe" && event.has_missing_ingredients){ eventsHTML += `
${event.event_shortname}
`; } else if (event.event_type==="recipe" && !event.has_missing_ingredients){ eventsHTML += `
${event.event_shortname}
`; } else { eventsHTML += `
${event.event_shortname}
`; } }); } table_cell.innerHTML = `
${day}
${eventsHTML}
`; table_cell.classList.add("calendar-cell"); table_cell.dataset.day = day; tableRow.append(table_cell) if ((startDay + day) % 7 === 0 && day !== numDays){ calender_table.append(tableRow) tableRow = document.createElement('tr') }; } let lastDayOfWeek = (startDay + numDays - 1) % 7; for (let i = lastDayOfWeek + 1; i <= 6; i++) { let table_cell = document.createElement('td') table_cell.setAttribute('class', 'uk-visible@m calendar-cell-empty') tableRow.append(table_cell) } calender_table.append(tableRow) let table_footer = document.createElement('tr') table_footer.innerHTML = `` calender_table.append(table_footer) calender_container.append(calender_table) document.getElementById("month-year-title").innerHTML = `${monthNames[month]} ${year}`; } function showContextMenuForEvent(eventLabel, x, y) { const menu = document.getElementById('calendarContextMenu'); // Set only "Edit" and "Remove" (and optionally "Add Another") menu.className = "uk-dropdown uk-open"; menu.innerHTML = ` `; menu.style.display = 'block'; menu.style.left = x + 'px'; menu.style.top = y + 'px'; } function showContextMenuForCell(calendarCell, x, y) { const menu = document.getElementById('calendarContextMenu'); // Only "Add Event" menu.className = "uk-dropdown uk-open"; menu.innerHTML = ` `; menu.style.display = 'block'; menu.style.left = x + 'px'; menu.style.top = y + 'px'; } window.addEventListener('click', function() { document.getElementById('calendarContextMenu').style.display = 'none'; document.querySelectorAll('.calendar-cell-selected').forEach(el => el.classList.remove('calendar-cell-selected')); document.querySelectorAll('.custom-label-selected').forEach(el => el.classList.remove('custom-label-selected')); document.querySelectorAll('.recipe-label-selected').forEach(el => el.classList.remove('recipe-label-selected')); }); async function addEvent(day) { let menu = document.getElementById('calendarContextMenu'); //let day = menu.getAttribute('data-day') console.log(year, month, day) let customDate = new Date(year, month-1, day); document.getElementById('event_date_start').value = customDate.toISOString().split('T')[0]; document.getElementById('event_date_end').value = customDate.toISOString().split('T')[0]; UIkit.modal(document.getElementById('eventModal')).show(); } async function editEvent(event_uuid) { console.log(event_uuid) let event = await getEventByUUID(event_uuid) console.log(event) document.getElementById('event_uuid_edit').value = event_uuid let event_date_start = new Date(event.event_date_start) let y = event_date_start.getFullYear(); let m = event_date_start.getUTCMonth(); let d = event_date_start.getUTCDate(); event_date_start = new Date(y, m, d); let event_date_end = new Date(event.event_date_end) let end_y = event_date_end.getFullYear(); let end_m = event_date_end.getUTCMonth(); let end_d = event_date_end.getUTCDate(); event_date_end = new Date(end_y, end_m, end_d); document.getElementById('event_date_edit_start').value = event_date_start.toISOString().split('T')[0] document.getElementById('event_date_edit_end').value = event_date_end.toISOString().split('T')[0] document.getElementById('event_type_edit').value = event.event_type document.getElementById('recipe_label_modal_edit').value = event.recipe_uuid document.getElementById('event_description_edit').value = event.event_description document.getElementById('event_name_edit').value = event.event_shortname if(event.event_type==="recipe"){ document.getElementById('event_name_edit').classList.add('uk-disabled') document.getElementById('event_name_edit').classList.add('uk-form-blank') document.getElementById('recipe_label_edit_parent').hidden = false } else { document.getElementById('event_name_edit').classList.remove('uk-disabled') document.getElementById('event_name_edit').classList.remove('uk-form-blank') document.getElementById('recipe_label_edit_parent').hidden = true } UIkit.modal(document.getElementById('eventEditModal')).show(); } async function postNewEvent(){ let event_shortname = document.getElementById('event_name').value let event_description = document.getElementById('event_description').value let event_date_start = document.getElementById('event_date_start').value let event_date_end = document.getElementById('event_date_end').value let event_type = document.getElementById('event_type').value let recipe_uuid = null if (event_type === "recipe"){ recipe_uuid = document.getElementById('selected-recipe').value } const response = await fetch('/planner/api/addEvent', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ event_shortname: event_shortname, event_description: event_description, event_date_start: event_date_start, event_date_end: event_date_end, recipe_uuid: recipe_uuid, event_type: event_type }) }); data = await response.json(); response_status = 'primary' if (!data.status === 201){ response_status = 'danger' } UIkit.notification({ message: data.message, status: response_status, pos: 'top-right', timeout: 5000 }); await setupCalendarAndEvents() UIkit.modal(document.getElementById('eventModal')).hide(); } async function postEditEvent(){ let event_uuid = document.getElementById('event_uuid_edit').value let event_shortname = document.getElementById('event_name_edit').value let event_description = document.getElementById('event_description_edit').value let event_date_start = document.getElementById('event_date_edit_start').value let event_date_end = document.getElementById('event_date_edit_end').value let event_type = document.getElementById('event_type_edit').value const response = await fetch('/planner/api/saveEvent', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ event_uuid: event_uuid, update: { event_shortname: event_shortname, event_description: event_description, event_date_start: event_date_start, event_date_end: event_date_end, event_type: event_type } }) }); data = await response.json(); response_status = 'primary' if (!data.status === 201){ response_status = 'danger' } UIkit.notification({ message: data.message, status: response_status, pos: 'top-right', timeout: 5000 }); await setupCalendarAndEvents() UIkit.modal(document.getElementById('eventEditModal')).hide(); } async function postRemoveEvent(event_uuid){ const response = await fetch('/planner/api/removeEvent', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ event_uuid: event_uuid }) }); data = await response.json(); response_status = 'primary' if (!data.status === 201){ response_status = 'danger' } UIkit.notification({ message: data.message, status: response_status, pos: 'top-right', timeout: 5000 }); await setupCalendarAndEvents() } // main window functions async function backOneMonth() { if(month === 1){ year = year - 1 month = 12 } else { month = month - 1 } await setupCalendarAndEvents() } async function forwardOneMonth() { if(month === 12){ year = year + 1 month = 1 } else { month = month + 1 } await setupCalendarAndEvents() } // Main Modal Functions var eventModal_type = "recipe" async function setEventTypeForm(){ let event_type = document.getElementById('event_type').value document.getElementById('event_name').value = "" document.getElementById('event_description').value = "" document.getElementById('selected-recipe').value = "" if(event_type === "custom"){ eventModal_type = "custom" document.getElementById('recipe_button_modal').hidden = true document.getElementById('recipe_label_modal').hidden = true document.getElementById('event_name').classList.remove('uk-disabled') } else if (event_type === "recipe"){ eventModal_type = "recipe" document.getElementById('recipe_button_modal').hidden = false document.getElementById('recipe_label_modal').hidden = false document.getElementById('event_name').classList.add('uk-disabled') } } // Select Row Modal Handlers var eventModal_page = 1 var eventModal_end = 1 var eventModal_search = "" var eventModal_limit = 50 async function selectRecipeEvent() { document.getElementById('mainEventBody').hidden = true document.getElementById('paginationModalBody').hidden = false document.getElementById('eventsModalFooter').hidden = true let recipes = await fetchRecipes() await updateEventsPaginationElement() await updateEventsTableWithRecipes(recipes) } async function fetchRecipes() { const url = new URL('/planner/api/getRecipes', window.location.origin); url.searchParams.append('page', eventModal_page); url.searchParams.append('limit', eventModal_limit); url.searchParams.append('search_string', eventModal_search); const response = await fetch(url); data = await response.json(); eventModal_end = data.end return data.recipes; } async function updateEventsTableWithRecipes(recipes) { let eventsTableBody = document.getElementById('eventsTableBody') eventsTableBody.innerHTML = "" for (let i = 0; i < recipes.length; i++){ let tableRow = document.createElement('tr') let nameCell = document.createElement('td') nameCell.innerHTML = `${recipes[i].name}` let opCell = document.createElement('td') let selectButton = document.createElement('button') selectButton.setAttribute('class', 'uk-button uk-button-primary uk-button-small') selectButton.innerHTML = "Select" selectButton.onclick = async function() { document.getElementById('selected-recipe').value = recipes[i].recipe_uuid document.getElementById('event_name').value = recipes[i].name document.getElementById('mainEventBody').hidden = false document.getElementById('paginationModalBody').hidden = true document.getElementById('eventsModalFooter').hidden = false } opCell.append(selectButton) tableRow.append(nameCell, opCell) eventsTableBody.append(tableRow) } } async function setEventModalPage(pageNumber){ eventModal_page = pageNumber; if (eventModal_type == "recipe"){ let records = await fetchRecipes() } await updateItemsModalTable(records) await updateItemsPaginationElement() } async function updateEventsPaginationElement() { let paginationElement = document.getElementById('eventPage'); paginationElement.innerHTML = ""; // previous let previousElement = document.createElement('li') if(eventModal_page<=1){ previousElement.innerHTML = ``; previousElement.classList.add('uk-disabled'); }else { previousElement.innerHTML = ``; } paginationElement.append(previousElement) //first let firstElement = document.createElement('li') if(eventModal_page<=1){ firstElement.innerHTML = `1`; firstElement.classList.add('uk-disabled'); }else { firstElement.innerHTML = `1`; } paginationElement.append(firstElement) // ... if(eventModal_page-2>1){ let firstDotElement = document.createElement('li') firstDotElement.classList.add('uk-disabled') firstDotElement.innerHTML = ``; paginationElement.append(firstDotElement) } // last if(eventModal_page-2>0){ let lastElement = document.createElement('li') lastElement.innerHTML = `${eventModal_page-1}` paginationElement.append(lastElement) } // current if(eventModal_page!=1 && eventModal_page != eventModal_end){ let currentElement = document.createElement('li') currentElement.innerHTML = `
  • ${eventModal_page}
  • ` paginationElement.append(currentElement) } // next if(eventModal_page+2${eventModal_page+1}` paginationElement.append(nextElement) } // ... if(eventModal_page+2<=eventModal_end){ let secondDotElement = document.createElement('li') secondDotElement.classList.add('uk-disabled') secondDotElement.innerHTML = ``; paginationElement.append(secondDotElement) } //end let endElement = document.createElement('li') if(eventModal_page>=eventModal_end){ endElement.innerHTML = `${eventModal_end}`; endElement.classList.add('uk-disabled'); }else { endElement.innerHTML = `${eventModal_end}`; } paginationElement.append(endElement) //next button let nextElement = document.createElement('li') if(eventModal_page>=eventModal_end){ nextElement.innerHTML = ``; nextElement.classList.add('uk-disabled'); }else { nextElement.innerHTML = ``; console.log(nextElement.innerHTML) } paginationElement.append(nextElement) }