Merge branch '8-podrska-za-boje-na-kalendaru' into 'master'
Added colours for teams Closes #8 See merge request kbr4/zsterminator!6
This commit is contained in:
@@ -2,7 +2,7 @@ import {Controller} from "@hotwired/stimulus"
|
||||
// Connects to data-controller="main-calendar"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["dateDisplay", "navigation"]
|
||||
static targets = ["dateDisplay", "navigation", "teamFilter"]
|
||||
|
||||
connect() {
|
||||
// Set height to full viewport
|
||||
@@ -18,7 +18,47 @@ export default class extends Controller {
|
||||
// Translation helper
|
||||
const t = (key) => translations[key] || key;
|
||||
|
||||
const calendar = new tui.Calendar(document.getElementById('main-calendar'), {
|
||||
// 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: {
|
||||
@@ -64,141 +104,71 @@ export default class extends Controller {
|
||||
return t('delete');
|
||||
}
|
||||
},
|
||||
calendars: [
|
||||
calendars: teamCalendars.length > 0 ? teamCalendars : [
|
||||
{
|
||||
id: 'cal1',
|
||||
name: 'Work',
|
||||
id: 'default',
|
||||
name: 'Default',
|
||||
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(t('delete_error'));
|
||||
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(t('delete_success'));
|
||||
} else {
|
||||
console.error(`Failed to delete reservation ${reservationId}. Status: ${response.status}`);
|
||||
let errorMessage = t('delete_error');
|
||||
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(t('network_error'));
|
||||
}
|
||||
|
||||
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();
|
||||
// Create calendar events
|
||||
this.createCalendarEvents(reservations);
|
||||
|
||||
// Update the date display after rendering
|
||||
// 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() {
|
||||
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
|
||||
}
|
||||
])
|
||||
});
|
||||
// This method is now replaced by initialization in connect()
|
||||
// and createCalendarEvents method
|
||||
}
|
||||
|
||||
// Helper function to get CSRF token from meta tag
|
||||
@@ -266,4 +236,44 @@ export default class extends Controller {
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user