fix(calendar): reactive update of daily team members in calendar grid

This commit is contained in:
kdeterme 2026-09-11 14:06:09 +02:00
parent fdc315788f
commit 41898f211f

View file

@ -4998,11 +4998,14 @@ document.addEventListener('DOMContentLoaded', function () {
const viewMode = filterViewModeSelect?.value || 'timeline'; const viewMode = filterViewModeSelect?.value || 'timeline';
const targetDate = customDate || (viewMode === 'teams_daily' ? formatDateISO(teamsDailyActiveDate) : null); const targetDate = customDate || (viewMode === 'teams_daily' ? formatDateISO(teamsDailyActiveDate) : null);
if (targetDate) {
const urlObj = new URL(url, window.location.origin); const urlObj = new URL(url, window.location.origin);
urlObj.searchParams.set('date', targetDate); if (viewMode) {
url = urlObj.pathname + urlObj.search; urlObj.searchParams.set('view_mode', viewMode);
} }
if (targetDate) {
urlObj.searchParams.set('date', targetDate);
}
url = urlObj.pathname + urlObj.search;
return fetch(url, { cache: 'no-store' }) return fetch(url, { cache: 'no-store' })
.then(r => r.json()) .then(r => r.json())
@ -5028,6 +5031,9 @@ document.addEventListener('DOMContentLoaded', function () {
}); });
} }
window.loadCalendarData = loadCalendarData;
window.getTeamColor = getTeamColor;
// Reset filters handler // Reset filters handler
const resetFiltersBtn = document.getElementById('reset-filters'); const resetFiltersBtn = document.getElementById('reset-filters');
if (resetFiltersBtn) { if (resetFiltersBtn) {
@ -5314,6 +5320,63 @@ function openTeamDailyMembersModal(teamId, dateStr, teamName) {
loadTeamDailyMembersModalData(teamId, dateStr); loadTeamDailyMembersModalData(teamId, dateStr);
} }
function updateTeamsDailyGridCell(teamId, dateStr, currentMembers, teamObj) {
if (!teamId || !dateStr) return;
const cell = document.querySelector(`.teams-daily-grid-cell[data-team-id="${teamId}"][data-date="${dateStr}"]`);
if (!cell) return;
let membersContainer = cell.querySelector('.team-members-list');
const teamColor = typeof getTeamColor === 'function' ? getTeamColor(teamId) : (window.getTeamColor ? window.getTeamColor(teamId) : '#0d6efd');
const canEditThisTeam = (typeof canEditTeams !== 'undefined' && Boolean(canEditTeams)) && (!teamObj || teamObj.can_edit !== false);
const todayStr = new Date().toISOString().split('T')[0];
const isPastDay = dateStr < todayStr;
const titleTooltip = canEditThisTeam && !isPastDay ? gettext('Modifier la composition de l’équipe pour ce jour') : gettext('Composition de l’équipe');
const teamName = teamObj && teamObj.name ? teamObj.name : '';
if (!membersContainer) {
membersContainer = document.createElement('div');
cell.prepend(membersContainer);
}
membersContainer.setAttribute('data-team-id', teamId);
membersContainer.setAttribute('data-date', dateStr);
if (teamName) {
membersContainer.setAttribute('data-team-name', teamName);
}
membersContainer.setAttribute('title', titleTooltip);
if (currentMembers && currentMembers.length > 0) {
const formattedMembers = currentMembers.map(m => {
const name = typeof m === 'object' && m ? m.name : m;
const isAbsent = typeof m === 'object' && m ? Boolean(m.is_absent) : false;
const absenceReason = typeof m === 'object' && m ? (m.absence_reason || '') : '';
const isMultiTeam = typeof m === 'object' && m ? Boolean(m.is_multi_team) : false;
const otherTeams = typeof m === 'object' && m && m.other_teams ? m.other_teams : [];
let memberNameHtml = escapeHtml(name);
if (isMultiTeam) {
const otherNames = otherTeams.map(t => t.name).join(', ');
const tooltip = otherNames ? `${gettext('Planifié aussi dans')} : ${otherNames}` : gettext('Planifié dans plusieurs équipes ce jour');
memberNameHtml += ` <i class="bi bi-diagram-3 text-warning ms-1" style="font-size:0.75rem;" title="${escapeHtml(tooltip)}"></i>`;
}
if (isAbsent) {
return `<span class="text-decoration-line-through text-danger opacity-75" title="${escapeHtml(absenceReason || gettext('Absent'))}">${memberNameHtml}</span> <span class="badge text-bg-danger p-0 px-1 font-monospace" style="font-size:0.6rem;">${escapeHtml(absenceReason || gettext('Absent'))}</span>`;
}
return memberNameHtml;
}).join(', ');
membersContainer.className = 'team-members-list clickable-team-members text-muted small fst-italic mb-2';
membersContainer.style.borderLeft = `3px solid ${teamColor}`;
membersContainer.style.cursor = 'pointer';
membersContainer.innerHTML = `<i class="bi bi-people-fill me-1" style="color: ${teamColor};"></i>${formattedMembers}`;
} else {
membersContainer.className = 'team-members-list clickable-team-members text-muted small fst-italic mb-2 text-opacity-50';
membersContainer.style.borderLeft = '3px solid #cbd5e1';
membersContainer.style.cursor = 'pointer';
membersContainer.innerHTML = `<i class="bi bi-people me-1"></i>(${gettext('Aucun membre')})`;
}
}
function loadTeamDailyMembersModalData(teamId, dateStr) { function loadTeamDailyMembersModalData(teamId, dateStr) {
const spinner = document.getElementById('team-daily-modal-spinner'); const spinner = document.getElementById('team-daily-modal-spinner');
const content = document.getElementById('team-daily-modal-content'); const content = document.getElementById('team-daily-modal-content');
@ -5367,6 +5430,11 @@ function loadTeamDailyMembersModalData(teamId, dateStr) {
else readonlyAlert.classList.add('d-none'); else readonlyAlert.classList.add('d-none');
} }
// Update calendar cell immediately if present in the teams daily grid
if (data.current_members) {
updateTeamsDailyGridCell(teamId, dateStr, data.current_members, data.team);
}
// Render current members // Render current members
const members = data.current_members || []; const members = data.current_members || [];
if (membersCountEl) membersCountEl.textContent = members.length; if (membersCountEl) membersCountEl.textContent = members.length;
@ -5497,8 +5565,10 @@ function assignMemberToDailyTeam(memberId, teamId, dateStr, action) {
setTimeout(() => { if (succAlert) succAlert.classList.add('d-none'); }, 3000); setTimeout(() => { if (succAlert) succAlert.classList.add('d-none'); }, 3000);
} }
loadTeamDailyMembersModalData(teamId, dateStr); loadTeamDailyMembersModalData(teamId, dateStr);
if (typeof loadCalendarData === 'function') { if (typeof window.loadCalendarData === 'function') {
loadCalendarData(); window.loadCalendarData(dateStr);
} else if (typeof loadCalendarData === 'function') {
loadCalendarData(dateStr);
} }
}) })
.catch(err => { .catch(err => {
@ -5560,3 +5630,13 @@ if (_memberHistoryModalEl) {
}); });
} }
const _teamDailyMembersModalEl = document.getElementById('teamDailyMembersModal');
if (_teamDailyMembersModalEl) {
_teamDailyMembersModalEl.addEventListener('hidden.bs.modal', function () {
if (typeof window.loadCalendarData === 'function') {
window.loadCalendarData();
}
});
}