159 lines
9.3 KiB
JavaScript
159 lines
9.3 KiB
JavaScript
(() => {
|
||
'use strict';
|
||
const PTA = window.PTA;
|
||
if (!PTA) return;
|
||
const { readJsonResponse, apiErrorMessage, escapeHtml, formatDate } = PTA.utils;
|
||
const el = (id) => document.getElementById(id);
|
||
|
||
function message(text, type = 'info') {
|
||
const box = el('team-list-message');
|
||
if (!box) return;
|
||
box.className = `message message-${type}`;
|
||
box.textContent = text;
|
||
}
|
||
|
||
async function api(url, options = {}) {
|
||
const response = await fetch(url, options);
|
||
const data = await readJsonResponse(response);
|
||
if (!response.ok) throw new Error(apiErrorMessage(data, 'Opération impossible.'));
|
||
return data;
|
||
}
|
||
|
||
function controlHtml(control) {
|
||
const level = String(control.niveau || 'INFO').toLowerCase();
|
||
return `<div class="control-item control-${escapeHtml(level)}"><strong>${escapeHtml(control.niveau)}</strong><span>${escapeHtml(control.message)}</span></div>`;
|
||
}
|
||
|
||
function teamHtml(team) {
|
||
const options = el('team-agent-options')?.innerHTML || '';
|
||
const members = (team.members || []).map((member) => `
|
||
<tr>
|
||
<td><strong>${escapeHtml(member.prenom)} ${escapeHtml(member.nom)}</strong><br><small>${escapeHtml(member.poste_libelle || 'Poste non renseigné')}</small></td>
|
||
<td>${member.est_diplome ? `Diplômé${member.diplome_libelle ? ` — ${escapeHtml(member.diplome_libelle)}` : ''}` : 'Non diplômé'}</td>
|
||
<td>${escapeHtml(member.fonction_equipe)}</td>
|
||
<td>${escapeHtml(member.structure_principale_nom || 'Sans lieu principal')}</td>
|
||
<td><button type="button" class="button button-danger remove-team-member" data-agent-id="${Number(member.id_agent)}">Retirer</button></td>
|
||
</tr>
|
||
`).join('') || '<tr><td colspan="5">Aucun agent affecté.</td></tr>';
|
||
return `
|
||
<article class="card team-card" data-team-id="${Number(team.id_equipe)}">
|
||
<div class="section-heading">
|
||
<div><h3>${escapeHtml(team.libelle)}</h3><p class="section-subtitle">${escapeHtml(team.structure_nom)} — ${formatDate(team.date_debut)} au ${formatDate(team.date_fin)} — ${escapeHtml(team.type_equipe)}</p></div>
|
||
<select class="team-status" aria-label="Statut"><option value="BROUILLON" ${team.statut === 'BROUILLON' ? 'selected' : ''}>Brouillon</option><option value="A_CONTROLER" ${team.statut === 'A_CONTROLER' ? 'selected' : ''}>À contrôler</option><option value="VALIDEE" ${team.statut === 'VALIDEE' ? 'selected' : ''}>Validée</option></select>
|
||
</div>
|
||
<div class="summary-grid compact-summary">
|
||
<article class="summary-card"><span>Agents requis</span><strong>${Number(team.agents_requis)}</strong></article>
|
||
<article class="summary-card"><span>Agents affectés</span><strong>${Number(team.agents_affectes)}</strong></article>
|
||
<article class="summary-card"><span>Diplômés</span><strong>${Number(team.agents_diplomes || 0)}</strong></article>
|
||
<article class="summary-card"><span>Enfants</span><strong>${Number(team.nombre_enfants_moins_6) + Number(team.nombre_enfants_6_plus)}</strong></article>
|
||
</div>
|
||
<div class="control-list">${(team.controls || []).map(controlHtml).join('')}</div>
|
||
<form class="team-member-form inline-form">
|
||
<label class="field"><span>Agent</span><select class="team-member-agent" required><option value="">Choisir un agent</option>${options}</select></label>
|
||
<label class="field"><span>Fonction dans l’équipe</span><select class="team-member-function"><option value="RESPONSABLE">Responsable</option><option value="ANIMATION">Animation</option><option value="RESTAURATION_ENTRETIEN">Restauration / entretien</option></select></label>
|
||
<label class="field"><span>Commentaire</span><input class="team-member-comment" type="text" maxlength="500"></label>
|
||
<button class="button button-primary" type="submit">Ajouter</button>
|
||
</form>
|
||
<div class="table-scroll"><table class="planning-table"><thead><tr><th>Agent</th><th>Qualification</th><th>Fonction</th><th>Lieu principal</th><th>Action</th></tr></thead><tbody>${members}</tbody></table></div>
|
||
</article>`;
|
||
}
|
||
|
||
async function load() {
|
||
const start = el('team-filter-start')?.value || '';
|
||
const end = el('team-filter-end')?.value || '';
|
||
const query = new URLSearchParams();
|
||
if (start) query.set('date_debut', start);
|
||
if (end) query.set('date_fin', end);
|
||
message('Chargement des équipes…');
|
||
try {
|
||
const data = await api(`api/teams.php?${query.toString()}`);
|
||
el('team-list').innerHTML = (data.teams || []).map(teamHtml).join('') || '<div class="empty-state">Aucune équipe sur cette période.</div>';
|
||
message(`${(data.teams || []).length} équipe(s) affichée(s).`, 'success');
|
||
} catch (error) { message(error.message, 'error'); }
|
||
}
|
||
|
||
async function create(event) {
|
||
event.preventDefault();
|
||
const box = el('team-create-message');
|
||
try {
|
||
const data = await api('api/teams.php', {
|
||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
csrf_token: window.PTA_CONFIG.csrfToken,
|
||
structure_id: Number(el('team-structure').value),
|
||
type_equipe: el('team-type').value,
|
||
libelle: el('team-label').value,
|
||
date_debut: el('team-start').value,
|
||
date_fin: el('team-end').value,
|
||
nombre_enfants_moins_6: Number(el('team-under-six').value),
|
||
nombre_enfants_6_plus: Number(el('team-over-six').value),
|
||
ratio_moins_6: Number(el('team-ratio-under-six').value),
|
||
ratio_6_plus: Number(el('team-ratio-over-six').value),
|
||
minimum_agents: Number(el('team-min-agents').value),
|
||
pourcentage_diplomes_min: Number(el('team-qualified-rate').value),
|
||
commentaire: el('team-comment').value,
|
||
}),
|
||
});
|
||
box.className = 'message message-success'; box.textContent = data.message;
|
||
event.currentTarget.reset();
|
||
el('team-ratio-under-six').value = '8'; el('team-ratio-over-six').value = '12'; el('team-min-agents').value = '1'; el('team-qualified-rate').value = '50';
|
||
await load();
|
||
} catch (error) { box.className = 'message message-error'; box.textContent = error.message; }
|
||
}
|
||
|
||
async function handle(event) {
|
||
const card = event.target.closest('.team-card');
|
||
if (!card) return;
|
||
const teamId = Number(card.dataset.teamId);
|
||
if (event.type === 'submit' && event.target.matches('.team-member-form')) {
|
||
event.preventDefault();
|
||
try {
|
||
await api('api/team_members.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({
|
||
csrf_token: window.PTA_CONFIG.csrfToken, team_id: teamId,
|
||
agent_id: Number(card.querySelector('.team-member-agent').value),
|
||
fonction_equipe: card.querySelector('.team-member-function').value,
|
||
commentaire: card.querySelector('.team-member-comment').value,
|
||
}) });
|
||
await load();
|
||
} catch (error) { message(error.message, 'error'); }
|
||
return;
|
||
}
|
||
const remove = event.target.closest('.remove-team-member');
|
||
if (remove) {
|
||
if (!window.confirm('Retirer cet agent de l’équipe ?')) return;
|
||
try {
|
||
await api('api/team_members.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({
|
||
csrf_token: window.PTA_CONFIG.csrfToken, action: 'REMOVE', team_id: teamId, agent_id: Number(remove.dataset.agentId),
|
||
}) });
|
||
await load();
|
||
} catch (error) { message(error.message, 'error'); }
|
||
}
|
||
}
|
||
|
||
async function status(event) {
|
||
const select = event.target.closest('.team-status');
|
||
if (!select) return;
|
||
const card = select.closest('.team-card');
|
||
try {
|
||
await api('api/team_status.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({
|
||
csrf_token: window.PTA_CONFIG.csrfToken, team_id: Number(card.dataset.teamId), statut: select.value,
|
||
}) });
|
||
await load();
|
||
} catch (error) { message(error.message, 'error'); }
|
||
}
|
||
|
||
function init() {
|
||
const params = window.PTA_PAGE_CONFIG?.params || {};
|
||
if (params.dateDebut) el('team-filter-start').value = params.dateDebut;
|
||
if (params.dateFin) el('team-filter-end').value = params.dateFin;
|
||
el('team-create-form')?.addEventListener('submit', create);
|
||
el('load-teams')?.addEventListener('click', load);
|
||
el('team-list')?.addEventListener('submit', handle);
|
||
el('team-list')?.addEventListener('click', handle);
|
||
el('team-list')?.addEventListener('change', status);
|
||
load();
|
||
}
|
||
|
||
PTA.modules.teams = { init, load };
|
||
})();
|