pour prod
This commit is contained in:
158
assets/js/teams.js
Normal file
158
assets/js/teams.js
Normal file
@@ -0,0 +1,158 @@
|
||||
(() => {
|
||||
'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 };
|
||||
})();
|
||||
Reference in New Issue
Block a user