import {Controller} from "@hotwired/stimulus" // Connects to data-controller="main-calendar" export default class extends Controller { static targets = ["dateDisplay", "navigation"] connect() { // Set height to full viewport document.getElementById('main-calendar').style.height = '100vh'; document.getElementById('main-calendar').style.width = '100vw'; const calendar = new tui.Calendar(document.getElementById('main-calendar'), { defaultView: 'week', usageStatistics: false, week: { taskView: false, scheduleView: false, eventView: ['time'], startDayOfWeek: 1, // Start week on Monday hourStart: 4, hourEnd: 21, }, timezone: { zones: [ { timezoneName: 'UTC', displayLabel: 'UTC' // Optional: Label for the timezone } ] // You might need `primaryTimezone: 'UTC'` here as well, // depending on the exact library version and desired behavior. // Let's start with just zones. }, // This is important - set the height to 100% height: '100%', // Make sure it takes full width width: '100%', template: { timegridDisplayPrimaryTime({time}) { return `${time.getHours()} sati`; }, popupDetailLocation(eventObj) { return ''; // Empty location as requested }, popupDetailAttendees(eventObj) { return eventObj.attendees[0]; // Show team name }, popupDetailState(eventObj) { return ''; }, popupDetailBody(eventObj) { return ''; } }, calendars: [ { id: 'cal1', name: 'Work', backgroundColor: '#00a9ff', }, ], // Enable the built-in popup useDetailPopup: true, }); // Listener for clicks on empty time slots calendar.on('selectDateTime', (eventData) => { const startTime = new Date(eventData.start); const endTime = new Date(startTime.getTime() + 30 * 60000); // Add 30 minutes const formatForUrl = (date) => { const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0'); const hours = date.getHours().toString().padStart(2, '0'); const minutes = date.getMinutes().toString().padStart(2, '0'); return `${year}-${month}-${day}T${hours}:${minutes}:00`; }; const startTimeParam = formatForUrl(startTime); const endTimeParam = formatForUrl(endTime); const newReservationUrl = `/reservations/new?start_time=${encodeURIComponent(startTimeParam)}&end_time=${encodeURIComponent(endTimeParam)}`; if (window.Turbo) { Turbo.visit(newReservationUrl); } else { window.location.href = newReservationUrl; // Fallback: Full page reload } // Prevent TUI Calendar from creating its default event/guide element return false; }); // Listener for delete button in popup calendar.on('beforeDeleteEvent', async (eventObj) => { const reservationId = eventObj.id; const calendarId = eventObj.calendarId; if (!reservationId) { console.error("Reservation ID not found in event object."); return false; } const csrfToken = this.getCsrfToken(); if (!csrfToken) { console.error("CSRF token not found."); alert("Error: Could not verify request security token."); return false; } try { const response = await fetch(`/reservations/${reservationId}`, { method: 'DELETE', headers: { 'X-CSRF-Token': csrfToken, 'Accept': 'application/json' } }); if (response.ok) { calendar.deleteEvent(reservationId, calendarId); alert('Reservation deleted.'); } else { console.error(`Failed to delete reservation ${reservationId}. Status: ${response.status}`); let errorMessage = 'Error deleting reservation.'; try { const errorData = await response.json(); errorMessage += ` Server says: ${errorData.error || JSON.stringify(errorData)}`; } catch (e) { /* Ignore */ } alert(errorMessage); } } catch (error) { console.error("Network error or exception during delete:", error); alert("Error deleting reservation due to a network or script issue."); } return false; // Prevent TUI default delete handling }); // Listener for edit button in popup (or drag/resize completion) calendar.on('beforeUpdateEvent', (eventInfo) => { const eventId = eventInfo.event?.id; if (!eventId) { console.error("Cannot edit: Event ID not found."); return false; } // Navigate to edit page for both edit clicks and drag/resize events const editUrl = `/reservations/${eventId}/edit`; if (window.Turbo) { Turbo.visit(editUrl); } else { window.location.href = editUrl; } // Prevent TUI's default update action return false; }); window.calendar = calendar; this.getCalendardata(); calendar.render(); // Update the date display after rendering this.updateDateDisplay(); } getCalendardata() { var reservations = JSON.parse(document.querySelector("#main-calendar").dataset.reservations); window.reservations = reservations; reservations.forEach(reservation => { window.calendar.createEvents([ { id: reservation.id, calendarId: 'cal1', title: reservation.customer.first_name + ' ' + reservation.customer.surname + ' (' + reservation.customer.phone + ')', category: 'time', dueDateClass: reservation.dueDateClass, location: '', // Empty location as requested attendees: [reservation.team.name], // Team name as attendee start: reservation.start_time, end: reservation.end_time } ]) }); } // Helper function to get CSRF token from meta tag getCsrfToken() { const token = document.querySelector('meta[name="csrf-token"]')?.content; return token; } // Navigation methods - using the global window.calendar prev() { window.calendar.prev(); this.updateDateDisplay(); } next() { window.calendar.next(); this.updateDateDisplay(); } today() { window.calendar.today(); this.updateDateDisplay(); } // Helper for updating the date display updateDateDisplay() { if (this.hasDateDisplayTarget) { const calendar = window.calendar; const currentDate = calendar.getDate(); // Format the date range based on the current view const view = calendar.getViewName(); if (view === 'day') { this.dateDisplayTarget.textContent = this.formatDate(currentDate); } else if (view === 'week') { // For week view, show range (e.g., "Aug 1 - 7, 2023") const weekStart = new Date(currentDate); weekStart.setDate(weekStart.getDate() - weekStart.getDay() + (weekStart.getDay() === 0 ? -6 : 1)); const weekEnd = new Date(weekStart); weekEnd.setDate(weekStart.getDate() + 6); this.dateDisplayTarget.textContent = `${this.formatDateShort(weekStart)} - ${this.formatDateShort(weekEnd)}`; } else if (view === 'month') { // For month view, show month and year (e.g., "August 2023") this.dateDisplayTarget.textContent = currentDate.toLocaleString('default', { month: 'long', year: 'numeric' }); } } } // Helper for formatting dates formatDate(date) { return date.toLocaleDateString('default', { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric' }); } formatDateShort(date) { return date.toLocaleDateString('default', { month: 'short', day: 'numeric' }); } }