Files
old-zsterminator/app/javascript/controllers/main_calendar_controller.js

283 lines
8.4 KiB
JavaScript
Raw Normal View History

2024-08-11 14:18:36 +02:00
import {Controller} from "@hotwired/stimulus"
// Connects to data-controller="main-calendar"
export default class extends Controller {
static targets = ["dateDisplay", "navigation", "teamFilter"]
2025-02-27 07:45:54 +01:00
2024-08-11 14:18:36 +02:00
connect() {
2025-02-27 07:45:54 +01:00
// Set height to full viewport
document.getElementById('main-calendar').style.height = '100vh';
document.getElementById('main-calendar').style.width = '100vw';
2025-04-23 07:45:33 +02:00
// 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;
2025-04-24 07:04:42 +02:00
// 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;
2025-04-24 07:04:42 +02:00
// Initialize calendar with all team calendars
window.calendar = new tui.Calendar(document.getElementById('main-calendar'), {
2024-08-11 14:18:36 +02:00
defaultView: 'week',
usageStatistics: false,
week: {
taskView: false,
2024-08-24 07:06:09 +02:00
scheduleView: false,
eventView: ['time'],
2025-02-27 07:45:54 +01:00
startDayOfWeek: 1, // Start week on Monday
2024-08-24 07:06:09 +02:00
hourStart: 4,
hourEnd: 21,
},
timezone: {
zones: [
{
timezoneName: 'UTC',
displayLabel: 'UTC' // Optional: Label for the timezone
}
]
},
2025-02-27 07:45:54 +01:00
// This is important - set the height to 100%
height: '100%',
// Make sure it takes full width
width: '100%',
2024-08-24 07:06:09 +02:00
template: {
timegridDisplayPrimaryTime({time}) {
2025-04-23 07:45:33 +02:00
return `${time.getHours()} ${t('hours')}`;
2025-02-27 07:45:54 +01:00
},
popupDetailLocation(eventObj) {
return ''; // Empty location as requested
},
popupDetailAttendees(eventObj) {
const teamName = eventObj.attendees[0]; // Show team name
return teamName;
2025-02-27 07:45:54 +01:00
},
popupDetailState(eventObj) {
return '';
},
popupDetailBody(eventObj) {
return '';
2025-04-23 07:45:33 +02:00
},
popupEdit() {
return t('edit');
},
popupDelete() {
return t('delete');
2024-08-24 07:06:09 +02:00
}
2024-08-11 14:18:36 +02:00
},
2025-04-24 07:04:42 +02:00
calendars: teamCalendars.length > 0 ? teamCalendars : [
2024-08-11 14:18:36 +02:00
{
2025-04-24 07:04:42 +02:00
id: 'default',
name: 'Default',
2024-08-11 14:18:36 +02:00
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`;
2024-08-11 14:18:36 +02:00
});
2025-02-27 07:45:54 +01:00
// Render the calendar
window.calendar.render();
2024-08-11 14:18:36 +02:00
}
2025-04-24 07:04:42 +02:00
// Create events for all reservations
createCalendarEvents(reservations) {
if (!window.calendar) return;
2025-02-27 07:45:54 +01:00
// Process each reservation into a calendar event
reservations.forEach(reservation => {
2025-04-24 07:04:42 +02:00
const teamId = reservation.team.id;
const calendarId = `team-${teamId}`;
2025-04-24 07:04:42 +02:00
const startTime = new Date(reservation.start_time);
const endTime = new Date(reservation.end_time);
// Create the event with customer name only
const customerName = reservation.customer ? `${reservation.customer.first_name} ${reservation.customer.surname}` : '';
const event = {
id: `reservation-${reservation.id}`,
2025-04-24 07:04:42 +02:00
calendarId: calendarId,
title: customerName,
start: startTime,
end: endTime,
2025-04-24 07:04:42 +02:00
category: 'time',
isReadOnly: false,
reservation: reservation,
attendees: [reservation.team.name]
2025-04-24 07:04:42 +02:00
};
// Add event to calendar
window.calendar.createEvents([event]);
2025-04-24 07:04:42 +02:00
});
2024-08-11 14:18:36 +02:00
}
2024-08-24 07:06:09 +02:00
getCalendardata() {
2025-04-24 07:04:42 +02:00
// This method is now replaced by initialization in connect()
// and createCalendarEvents method
2024-08-24 07:06:09 +02:00
}
2025-02-27 07:45:54 +01:00
// Helper function to get CSRF token from meta tag
getCsrfToken() {
const token = document.querySelector('meta[name="csrf-token"]')?.content;
return token;
}
2025-02-27 07:45:54 +01:00
// 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();
}
}