279 lines
8.3 KiB
JavaScript
279 lines
8.3 KiB
JavaScript
import {Controller} from "@hotwired/stimulus"
|
|
// Connects to data-controller="main-calendar"
|
|
|
|
export default class extends Controller {
|
|
static targets = ["dateDisplay", "navigation", "teamFilter"]
|
|
|
|
connect() {
|
|
// Set height to full viewport
|
|
document.getElementById('main-calendar').style.height = '100vh';
|
|
document.getElementById('main-calendar').style.width = '100vw';
|
|
|
|
// Get current locale from html lang attribute
|
|
const currentLocale = document.documentElement.lang || 'bs';
|
|
|
|
// Get translations from data attribute
|
|
const translations = JSON.parse(document.getElementById('main-calendar').dataset.translations || '{}');
|
|
|
|
// Translation helper
|
|
const t = (key) => translations[key] || key;
|
|
|
|
// Pre-process reservations to set up team calendars
|
|
const reservations = JSON.parse(document.querySelector("#main-calendar").dataset.reservations);
|
|
window.reservations = reservations;
|
|
|
|
// Debug: Log the first reservation to inspect color format
|
|
if (reservations && reservations.length > 0) {
|
|
console.log("First reservation team color:", reservations[0].team.color);
|
|
}
|
|
|
|
// Extract unique teams and create calendar configurations
|
|
const teamCalendars = [];
|
|
const teamMap = {};
|
|
|
|
// Create calendar configs for each team
|
|
reservations.forEach(reservation => {
|
|
const teamId = reservation.team.id;
|
|
if (!teamMap[teamId]) {
|
|
const calendarId = `team-${teamId}`;
|
|
teamMap[teamId] = calendarId;
|
|
|
|
// Use color directly - it should be a hex string from the TeamSerializer
|
|
const teamColor = reservation.team.color || '#00a9ff';
|
|
|
|
teamCalendars.push({
|
|
id: calendarId,
|
|
name: reservation.team.name,
|
|
backgroundColor: teamColor,
|
|
borderColor: teamColor
|
|
});
|
|
}
|
|
});
|
|
|
|
// Store team calendars for filtering
|
|
this.teamCalendars = teamCalendars;
|
|
this.allCalendars = [...teamCalendars];
|
|
|
|
// Store all reservations for filtering
|
|
this.allReservations = reservations;
|
|
|
|
// Initialize calendar with all team calendars
|
|
window.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
|
|
}
|
|
]
|
|
},
|
|
// This is important - set the height to 100%
|
|
height: '100%',
|
|
// Make sure it takes full width
|
|
width: '100%',
|
|
template: {
|
|
timegridDisplayPrimaryTime({time}) {
|
|
return `${time.getHours()} ${t('hours')}`;
|
|
},
|
|
popupDetailLocation(eventObj) {
|
|
return ''; // Empty location as requested
|
|
},
|
|
popupDetailAttendees(eventObj) {
|
|
return eventObj.attendees[0]; // Show team name
|
|
},
|
|
popupDetailState(eventObj) {
|
|
return '';
|
|
},
|
|
popupDetailBody(eventObj) {
|
|
return '';
|
|
},
|
|
popupEdit() {
|
|
return t('edit');
|
|
},
|
|
popupDelete() {
|
|
return t('delete');
|
|
}
|
|
},
|
|
calendars: teamCalendars.length > 0 ? teamCalendars : [
|
|
{
|
|
id: 'default',
|
|
name: 'Default',
|
|
backgroundColor: '#00a9ff',
|
|
}
|
|
]
|
|
});
|
|
|
|
// Create calendar events
|
|
this.createCalendarEvents(reservations);
|
|
|
|
// Set up initial date display
|
|
this.updateDateDisplay();
|
|
|
|
// Handle calendar navigation
|
|
window.calendar.on('beforeUpdateDay', (date) => {
|
|
this.updateDateDisplay();
|
|
});
|
|
|
|
// Handle edit and delete actions
|
|
window.calendar.on('clickEvent', (event) => {
|
|
const reservation = event.event.reservation;
|
|
|
|
// Redirect to edit page
|
|
window.location.href = `/reservations/${reservation.id}/edit`;
|
|
});
|
|
|
|
// Render the calendar
|
|
window.calendar.render();
|
|
}
|
|
|
|
// Create events for all reservations
|
|
createCalendarEvents(reservations) {
|
|
if (!window.calendar) return;
|
|
|
|
// Process each reservation into a calendar event
|
|
reservations.forEach(reservation => {
|
|
const teamId = reservation.team.id;
|
|
const calendarId = `team-${teamId}`;
|
|
|
|
const startTime = new Date(reservation.start_time);
|
|
const endTime = new Date(reservation.end_time);
|
|
|
|
// Create the event
|
|
const event = {
|
|
id: `reservation-${reservation.id}`,
|
|
calendarId: calendarId,
|
|
title: reservation.customer ? `${reservation.customer.first_name} ${reservation.customer.surname}` : '',
|
|
start: startTime,
|
|
end: endTime,
|
|
category: 'time',
|
|
isReadOnly: false,
|
|
reservation: reservation,
|
|
attendees: [reservation.team.name]
|
|
};
|
|
|
|
// Add event to calendar
|
|
window.calendar.createEvents([event]);
|
|
});
|
|
}
|
|
|
|
getCalendardata() {
|
|
// This method is now replaced by initialization in connect()
|
|
// and createCalendarEvents method
|
|
}
|
|
|
|
// 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'
|
|
});
|
|
}
|
|
|
|
// Method for team filtering
|
|
filterByTeam(event) {
|
|
const selectedTeamId = event.target.value;
|
|
|
|
// Store last value for test verification
|
|
window.lastTeamFilterValue = selectedTeamId;
|
|
|
|
console.log(`Filtering by team: ${selectedTeamId}`);
|
|
|
|
if (!window.calendar) return;
|
|
|
|
// Clear existing events
|
|
window.calendar.clear();
|
|
|
|
// Process reservations based on filter
|
|
let filteredReservations = this.allReservations;
|
|
|
|
// If not "all", filter by team
|
|
if (selectedTeamId !== 'all') {
|
|
// Extract numeric ID if the value is in "team-{id}" format
|
|
const teamId = selectedTeamId.toString().startsWith('team-')
|
|
? selectedTeamId.toString().replace('team-', '')
|
|
: selectedTeamId.toString();
|
|
|
|
console.log(`Using team ID for filtering: ${teamId}`);
|
|
|
|
filteredReservations = this.allReservations.filter(reservation =>
|
|
reservation.team.id.toString() === teamId
|
|
);
|
|
|
|
console.log(`Found ${filteredReservations.length} reservations for team ${teamId}`);
|
|
}
|
|
|
|
// Create and add calendar events based on filtered reservations
|
|
this.createCalendarEvents(filteredReservations);
|
|
|
|
// Update calendar display
|
|
window.calendar.render();
|
|
}
|
|
} |