185 lines
9.5 KiB
JavaScript
185 lines
9.5 KiB
JavaScript
(() => {
|
|
'use strict';
|
|
|
|
const PTA = window.PTA;
|
|
if (!PTA) return;
|
|
const { readJsonResponse, apiErrorMessage, escapeHtml, formatDuration, formatDate } = PTA.utils;
|
|
let current = null;
|
|
|
|
const el = (id) => document.getElementById(id);
|
|
const selectedAgentId = () => Number(el('pta-agent')?.value || 0);
|
|
|
|
function show(text, type = 'info') {
|
|
const box = el('pta-message');
|
|
if (!box) return;
|
|
box.className = `message message-${type}`;
|
|
box.textContent = text;
|
|
}
|
|
|
|
function card(label, value, detail = '') {
|
|
return `<article class="summary-card"><span>${escapeHtml(label)}</span><strong>${escapeHtml(value)}</strong>${detail ? `<small>${escapeHtml(detail)}</small>` : ''}</article>`;
|
|
}
|
|
|
|
function renderSummary(data) {
|
|
current = data;
|
|
const agent = data.agent || {};
|
|
const quota = data.quota || {};
|
|
const counters = data.counters || {};
|
|
el('pta-content').hidden = false;
|
|
el('pta-agent-name').textContent = `${agent.prenom || ''} ${agent.nom || ''}`.trim();
|
|
el('pta-agent-meta').textContent = [
|
|
agent.matricule,
|
|
agent.poste_libelle || 'Poste non renseigné',
|
|
agent.structure_principale_nom || 'Sans lieu principal',
|
|
agent.type_contrat === 'PERMANENT' ? 'Contrat permanent' : 'Contrat non permanent',
|
|
].filter(Boolean).join(' — ');
|
|
|
|
el('pta-summary-cards').innerHTML = [
|
|
card('Année civile PTA', `${formatDate(quota.date_debut_periode)} → ${formatDate(quota.date_fin_periode)}`),
|
|
card('Quotité', `${Number(quota.quotite_travail || 0).toLocaleString('fr-FR')} %`, `Référence : ${formatDuration(Number(quota.quota_reference_minutes || 96420))}`),
|
|
card('Quota à réaliser', quota.quota_cible || formatDuration(Number(quota.quota_cible_minutes || 0))),
|
|
card('Déjà affecté', quota.affectees || formatDuration(Number(quota.minutes_affectees || 0))),
|
|
card('Reste à affecter', quota.restantes || formatDuration(Number(quota.minutes_restantes || 0))),
|
|
card('Formation', `${counters.formation_duree || '0 h 00'} / ${counters.formation_cible_duree || '0 h 00'}`),
|
|
card('Congés annuels', `${Number(counters.conges_annuels_jours || 0)} / ${Number(counters.conges_annuels_cible || 25)} jours`),
|
|
card('Fractionnement', `${Number(counters.jours_fractionnement || 0)} / ${Number(counters.jours_fractionnement_cible || 2)} jours`),
|
|
].join('');
|
|
|
|
el('pta-category-body').innerHTML = (data.categories || []).map((category) => `
|
|
<tr><td><strong>${escapeHtml(category.libelle)}</strong></td><td>${escapeHtml(category.duree)}</td><td>${Number(category.jours || 0)}</td></tr>
|
|
`).join('') || '<tr><td colspan="3">Aucune affectation sur la période.</td></tr>';
|
|
|
|
el('pta-controls').innerHTML = (data.controls || []).map((control) => {
|
|
const level = String(control.niveau || 'INFO').toLowerCase();
|
|
return `<article class="control-item control-${escapeHtml(level)}"><strong>${escapeHtml(control.niveau || 'INFO')}</strong><span>${escapeHtml(control.message || '')}</span></article>`;
|
|
}).join('') || '<div class="empty-state">Aucun contrôle disponible.</div>';
|
|
|
|
renderConstraints(data.constraints || []);
|
|
renderWishes(data.wishes || []);
|
|
|
|
const refDate = el('pta-reference-date').value;
|
|
el('pta-open-agent-view').href = `agents.php?agent_id=${Number(agent.id_agent)}&month=${encodeURIComponent(refDate.slice(0, 7))}`;
|
|
el('pta-open-planning').href = `planning.php?agent_id=${Number(agent.id_agent)}`;
|
|
el('pta-constraint-start').value ||= quota.date_debut_periode || '';
|
|
el('pta-constraint-end').value ||= quota.date_fin_periode || '';
|
|
}
|
|
|
|
function renderConstraints(items) {
|
|
el('pta-constraint-list').innerHTML = items.map((item) => `
|
|
<article class="stack-item">
|
|
<div><strong>${item.type_contrainte === 'TEMPS_PARTIEL_THERAPEUTIQUE' ? 'Temps partiel thérapeutique' : 'Préconisation médicale'}</strong>
|
|
<p>${escapeHtml(formatDate(item.date_debut))} → ${item.date_fin ? escapeHtml(formatDate(item.date_fin)) : 'sans fin'} — ${escapeHtml(item.commentaire)}</p></div>
|
|
<button class="button button-danger pta-delete-constraint" type="button" data-id="${Number(item.id_contrainte)}">Supprimer</button>
|
|
</article>
|
|
`).join('') || '<div class="empty-state">Aucune contrainte active sur cette période.</div>';
|
|
}
|
|
|
|
function renderWishes(items) {
|
|
el('pta-wish-list').innerHTML = items.map((item) => `
|
|
<article class="stack-item">
|
|
<div><strong>${item.type_souhait === 'INTERDICTION' ? 'Interdiction' : 'Préférence'} — ${escapeHtml(item.structure_nom)}</strong>
|
|
<p>Priorité ${Number(item.priorite)}${item.distance_km !== null ? ` — ${Number(item.distance_km).toLocaleString('fr-FR')} km` : ''}${item.commentaire ? ` — ${escapeHtml(item.commentaire)}` : ''}</p></div>
|
|
<button class="button button-danger pta-delete-wish" type="button" data-id="${Number(item.id_souhait)}">Supprimer</button>
|
|
</article>
|
|
`).join('') || '<div class="empty-state">Aucune préférence ou interdiction enregistrée.</div>';
|
|
}
|
|
|
|
async function load() {
|
|
const agentId = selectedAgentId();
|
|
const date = el('pta-reference-date')?.value;
|
|
if (!agentId || !date) {
|
|
show('Choisissez un agent et une date de référence.', 'error');
|
|
return;
|
|
}
|
|
show('Calcul du PTA en cours…');
|
|
try {
|
|
const response = await fetch(`api/pta_summary.php?agent_id=${agentId}&date=${encodeURIComponent(date)}`);
|
|
const data = await readJsonResponse(response);
|
|
if (!response.ok) throw new Error(apiErrorMessage(data, 'Impossible de charger le PTA.'));
|
|
renderSummary(data);
|
|
show('PTA actualisé.', 'success');
|
|
} catch (error) {
|
|
show(error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async function post(url, payload) {
|
|
const response = await fetch(url, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ csrf_token: window.PTA_CONFIG.csrfToken, ...payload }),
|
|
});
|
|
const data = await readJsonResponse(response);
|
|
if (!response.ok) throw new Error(apiErrorMessage(data, 'Opération impossible.'));
|
|
return data;
|
|
}
|
|
|
|
async function saveConstraint(event) {
|
|
event.preventDefault();
|
|
if (!selectedAgentId()) return;
|
|
try {
|
|
await post('api/pta_constraint.php', {
|
|
agent_id: selectedAgentId(),
|
|
type_contrainte: el('pta-constraint-type').value,
|
|
date_debut: el('pta-constraint-start').value,
|
|
date_fin: el('pta-constraint-end').value,
|
|
quotite_temporaire: el('pta-constraint-rate').value,
|
|
maximum_heures_jour: el('pta-constraint-day-max').value,
|
|
maximum_heures_semaine: el('pta-constraint-week-max').value,
|
|
interdit_matin: el('pta-forbid-morning').checked,
|
|
interdit_midi: el('pta-forbid-midday').checked,
|
|
interdit_soir: el('pta-forbid-evening').checked,
|
|
commentaire: el('pta-constraint-comment').value,
|
|
});
|
|
event.currentTarget.reset();
|
|
await load();
|
|
} catch (error) { show(error.message, 'error'); }
|
|
}
|
|
|
|
async function saveWish(event) {
|
|
event.preventDefault();
|
|
if (!selectedAgentId()) return;
|
|
try {
|
|
await post('api/pta_wish.php', {
|
|
agent_id: selectedAgentId(),
|
|
structure_id: Number(el('pta-wish-structure').value),
|
|
type_souhait: el('pta-wish-type').value,
|
|
priorite: Number(el('pta-wish-priority').value),
|
|
distance_km: el('pta-wish-distance').value,
|
|
commentaire: el('pta-wish-comment').value,
|
|
});
|
|
event.currentTarget.reset();
|
|
el('pta-wish-priority').value = '1';
|
|
await load();
|
|
} catch (error) { show(error.message, 'error'); }
|
|
}
|
|
|
|
async function handleDelete(event) {
|
|
const constraint = event.target.closest('.pta-delete-constraint');
|
|
const wish = event.target.closest('.pta-delete-wish');
|
|
if (!constraint && !wish) return;
|
|
if (!window.confirm('Confirmer la suppression ?')) return;
|
|
try {
|
|
if (constraint) {
|
|
await post('api/pta_constraint.php', { action: 'DELETE', agent_id: selectedAgentId(), constraint_id: Number(constraint.dataset.id) });
|
|
} else {
|
|
await post('api/pta_wish.php', { action: 'DELETE', agent_id: selectedAgentId(), wish_id: Number(wish.dataset.id) });
|
|
}
|
|
await load();
|
|
} catch (error) { show(error.message, 'error'); }
|
|
}
|
|
|
|
function init() {
|
|
el('load-pta')?.addEventListener('click', load);
|
|
el('pta-constraint-form')?.addEventListener('submit', saveConstraint);
|
|
el('pta-wish-form')?.addEventListener('submit', saveWish);
|
|
el('pta-content')?.addEventListener('click', handleDelete);
|
|
const params = window.PTA_PAGE_CONFIG?.params || {};
|
|
if (params.agentId) el('pta-agent').value = String(params.agentId);
|
|
if (params.date) el('pta-reference-date').value = params.date;
|
|
if (params.agentId) load();
|
|
}
|
|
|
|
PTA.modules.pta = { init, load };
|
|
})();
|