Online Meeting Scheduling Conflict Resolver
Please fill in the meeting details and click "Find Common Slots" to see the results.
Please fill in the meeting duration and the start/end dates.
`; pdfDownloadContainer.classList.add('hidden'); changeTab(1); // Force back to input tab return; } const startDate = new Date(startDateStr + 'T00:00:00Z'); const endDate = new Date(endDateStr + 'T23:59:59Z'); if (startDate > endDate) { resultsOutput.innerHTML = `The 'From Date' cannot be after the 'To Date'.
`; pdfDownloadContainer.classList.add('hidden'); changeTab(1); return; } const attendeeElements = document.querySelectorAll('.attendee-row'); if (attendeeElements.length < 2) { resultsOutput.innerHTML = `Please add at least two attendees to find common slots.
`; pdfDownloadContainer.classList.add('hidden'); changeTab(1); return; } const attendees = Array.from(attendeeElements).map(row => ({ name: row.querySelector('.attendee-name').value || 'Unnamed Attendee', email: row.querySelector('.attendee-email').value, timezoneOffset: parseFloat(row.querySelector('.attendee-timezone').value) })); // 2. Generate potential slots in UTC // Assuming standard business hours 9 AM to 5 PM for this example const businessHoursStart = 9; const businessHoursEnd = 17; const allSlotsUTC = []; let currentDate = new Date(startDate); while (currentDate <= endDate) { for (let hour = 0; hour < 24; hour++) { for (let minute = 0; minute < 60; minute += 15) { // 15-min increments const slotStart = new Date(Date.UTC(currentDate.getUTCFullYear(), currentDate.getUTCMonth(), currentDate.getUTCDate(), hour, minute)); allSlotsUTC.push(slotStart); } } currentDate.setUTCDate(currentDate.getUTCDate() + 1); } // 3. Filter for common slots const commonSlots = allSlotsUTC.filter(utcSlot => { return attendees.every(attendee => { const localHour = utcSlot.getUTCHours() + attendee.timezoneOffset; // Normalize hour to be within 0-23 range const normalizedHour = (localHour + 24) % 24; return normalizedHour >= businessHoursStart && (normalizedHour + duration / 60) <= businessHoursEnd; }); }); // 4. Group consecutive slots const groupedSlots = []; if (commonSlots.length > 0) { let currentGroup = [commonSlots[0]]; for (let i = 1; i < commonSlots.length; i++) { const prevSlot = commonSlots[i-1]; const currentSlot = commonSlots[i]; // Check if slots are consecutive (15 minutes apart) if (currentSlot.getTime() - prevSlot.getTime() === 15 * 60 * 1000) { currentGroup.push(currentSlot); } else { groupedSlots.push(currentGroup); currentGroup = [currentSlot]; } } groupedSlots.push(currentGroup); } // 5. Filter groups by meeting duration const finalSlots = groupedSlots.filter(group => (group.length * 15) >= duration).map(group => group[0]); // 6. Display results displayResults(finalSlots, attendees, meetingTitle, duration); changeTab(2); }; /** * Renders the found slots in the results tab. */ const displayResults = (slots, attendees, meetingTitle, duration) => { if (slots.length === 0) { resultsOutput.innerHTML = `No common time slots found for all attendees within the specified window and business hours (9 AM - 5 PM local time).
`; pdfDownloadContainer.classList.add('hidden'); return; } const attendeesHeader = attendees.map(a => `${meetingTitle}
Suggested meeting times (${duration} minutes)
