trad et modal
This commit is contained in:
+11
-8
@@ -60,9 +60,9 @@ require __DIR__ . '/header.php';
|
||||
<div class="fc-modal-header">
|
||||
<h2><?= tr('fc_modal_snap_title') ?></h2>
|
||||
<button id="btnCloseSnapshot" class="fc-modal-close">×</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fc-modal-body" style="padding: 24px;">
|
||||
<form id="formSnapshot">
|
||||
<form id="formSnapshot">
|
||||
<div style="margin-bottom: 16px;">
|
||||
<label class="pf-label"><?= tr('fc_label_person') ?></label>
|
||||
<select id="snapPerson" class="pf-input" required>
|
||||
@@ -79,18 +79,18 @@ require __DIR__ . '/header.php';
|
||||
</select>
|
||||
</div>
|
||||
<div style="margin-bottom: 16px;">
|
||||
<label class="pf-label"><?= tr('fc_label_apply_date') ?></label>
|
||||
<label class="pf-label"><?= tr('fc_label_apply_date') ?></label>
|
||||
<input type="date" id="snapDate" class="pf-input" required title="<?= tr('fc_snap_date_hint') ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 24px;">
|
||||
<label class="pf-label"><?= tr('fc_label_remaining_balance') ?></label>
|
||||
<label class="pf-label"><?= tr('fc_label_remaining_balance') ?></label>
|
||||
<input type="number" step="0.5" id="snapBalance" class="pf-input" placeholder="<?= tr('fc_placeholder_balance') ?>" required>
|
||||
</div>
|
||||
<button type="submit" class="pf-btn" style="width: 100%;"><?= tr('fc_btn_save_snap') ?></button>
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="pf-section">
|
||||
<div class="fc-month-calendar-wrapper">
|
||||
@@ -230,7 +230,10 @@ window.I18N = {
|
||||
'vac_ete': "<?= tr('vac_ete') ?>",
|
||||
'leg_school_holidays': "<?= tr('leg_school_holidays') ?>",
|
||||
'fc_school_year': "<?= tr('fc_school_year') ?>",
|
||||
'fc_modal_holidays_title': "<?= tr('fc_modal_holidays_title') ?>"
|
||||
'fc_modal_holidays_title': "<?= tr('fc_modal_holidays_title') ?>",
|
||||
'fc_alert_burn_days': "<?= tr('fc_alert_burn_days') ?>",
|
||||
'fc_alert_burn_jra': "<?= tr('fc_alert_burn_jra') ?>",
|
||||
'ANNIV': "<?= tr('ANNIV') ?>"
|
||||
};
|
||||
</script>
|
||||
<script src="/modules/family-calendar/family-calendar.js"></script>
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* PachaFamily - CSS Auditor 🦙
|
||||
* Génère un rapport complet de tous les styles (fichiers, balises, inline)
|
||||
*/
|
||||
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
|
||||
$root = __DIR__;
|
||||
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($root));
|
||||
$report = "=== 🦙 RAPPORT CSS COMPLET PACHAFAMILY ===\n";
|
||||
$report .= "Généré le : " . date('Y-m-d H:i:s') . "\n\n";
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
if ($file->isDir()) continue;
|
||||
|
||||
$filePath = $file->getPathname();
|
||||
$relativePath = str_replace($root, '', $filePath);
|
||||
$ext = pathinfo($filePath, PATHINFO_EXTENSION);
|
||||
|
||||
// 1. EXTRACTION DES FICHIERS .css
|
||||
if ($ext === 'css') {
|
||||
$report .= "/* 📄 FICHIER SOURCE : $relativePath */\n";
|
||||
$report .= file_get_contents($filePath) . "\n";
|
||||
$report .= str_repeat("-", 40) . "\n\n";
|
||||
}
|
||||
|
||||
// 2. EXTRACTION DES BALISES <style> ET ATTRIBUTS style="" DANS LES .php
|
||||
if ($ext === 'php') {
|
||||
$content = file_get_contents($filePath);
|
||||
$foundInFile = false;
|
||||
|
||||
// Extraction des blocs <style>
|
||||
if (preg_match_all('/<style[^>]*>(.*?)<\/style>/is', $content, $matches)) {
|
||||
if (!$foundInFile) { $report .= "/* 📄 FICHIER SOURCE : $relativePath */\n"; $foundInFile = true; }
|
||||
foreach ($matches[1] as $idx => $styleBlock) {
|
||||
$report .= "/* Bloc <style> #$idx */\n";
|
||||
$report .= trim($styleBlock) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Extraction des styles inline style="..."
|
||||
// On capture le tag pour donner du contexte au style inline
|
||||
if (preg_match_all('/<([a-z0-9]+)[^>]*?\sstyle=["\']([^"]*?)["\'][^>]*>/i', $content, $matches)) {
|
||||
if (!$foundInFile) { $report .= "/* 📄 FICHIER SOURCE : $relativePath */\n"; $foundInFile = true; }
|
||||
foreach ($matches[0] as $idx => $fullTag) {
|
||||
// On nettoie un peu pour ne garder que l'essentiel du tag et son style
|
||||
$report .= "/* Style Inline #$idx */\n";
|
||||
$report .= trim($fullTag) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($foundInFile) {
|
||||
$report .= str_repeat("-", 40) . "\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo $report;
|
||||
@@ -148,6 +148,9 @@ return [
|
||||
'btn_off' => 'Off',
|
||||
'btn_extra' => 'Extra',
|
||||
|
||||
'fc_alert_burn_days' => '⚠️ Risc de pèrdua : %s d a gastar abans del %s',
|
||||
'fc_alert_burn_jra' => '⚠️ JRA: Només 2d es poden reportar després de febrer!',
|
||||
|
||||
// ==========================================
|
||||
// HOLIDAYS (VOYAGES)
|
||||
// ==========================================
|
||||
|
||||
@@ -149,6 +149,9 @@ return [
|
||||
'vac_ete' => "Vacances d'Été",
|
||||
'btn_off' => 'Off',
|
||||
'btn_extra' => 'Extra',
|
||||
|
||||
'fc_alert_burn_days' => '⚠️ Risque de perte : %s j à poser avant le %s',
|
||||
'fc_alert_burn_jra' => '⚠️ JRA : Seuls 2j sont reportables après février !',
|
||||
|
||||
// ==========================================
|
||||
// HOLIDAYS (VOYAGES)
|
||||
|
||||
@@ -395,6 +395,37 @@
|
||||
box-shadow: inset 0 -8px 0 0 var(--c-school-holiday) !important;
|
||||
}
|
||||
|
||||
.fc-burn-alert {
|
||||
margin-left: 5px;
|
||||
cursor: help;
|
||||
animation: pulseBurn 2s infinite;
|
||||
font-size: 0.9rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #ef4444; /* Rouge danger */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@keyframes pulseBurn {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 0.8;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.2);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tooltip sur le chip pour l'alerte */
|
||||
.fc-min-chip[title] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
6. PLANNING HEBDOMADAIRE (Desktop Uniquement)
|
||||
========================================================= */
|
||||
|
||||
@@ -503,6 +503,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
LEAVES_CONFIG.JRA.yearlyTotals[currYear] ||
|
||||
LEAVES_CONFIG.JRA.defaultBalance;
|
||||
|
||||
// Logique de report du reliquat de l'année N-1
|
||||
if (currMonth <= LEAVES_CONFIG.JRA.toleranceMonths) {
|
||||
const prevYear = currYear - 1;
|
||||
const prevInitial =
|
||||
@@ -519,10 +520,14 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
0,
|
||||
prevInitial - usedPrevYear,
|
||||
);
|
||||
// Ajout du report plafonné à 2 jours
|
||||
initialBalance += Math.min(
|
||||
remainingPrevYear,
|
||||
LEAVES_CONFIG.JRA.maxReport,
|
||||
);
|
||||
console.log(
|
||||
`[JRA] Personne ${pid}, Année ${currYear}: Report de ${Math.min(remainingPrevYear, LEAVES_CONFIG.JRA.maxReport)}j inclus.`,
|
||||
);
|
||||
}
|
||||
} else if (type === "JA") {
|
||||
const configJA = LEAVES_CONFIG.JA[pid];
|
||||
@@ -761,14 +766,12 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
const container = document.getElementById("fc-month-balances");
|
||||
if (!container) return;
|
||||
|
||||
// 1. Déterminer les mois affichés selon la vue
|
||||
const monthsToDisplay = [];
|
||||
const y = this.currentMonth.getFullYear();
|
||||
const m = this.currentMonth.getMonth();
|
||||
|
||||
let numMonths = 1;
|
||||
if (this.viewMode === "2months") numMonths = 2;
|
||||
if (this.viewMode === "3months") numMonths = 3;
|
||||
let numMonths =
|
||||
this.viewMode === "2months" ? 2 : this.viewMode === "3months" ? 3 : 1;
|
||||
|
||||
for (let i = 0; i < numMonths; i++) {
|
||||
const d = new Date(y, m + i, 1);
|
||||
@@ -780,40 +783,69 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
container.style.display = "flex";
|
||||
let html = "";
|
||||
|
||||
// 2. Calcul dynamique pour Alex et Laia
|
||||
[FAMILY.ALEX, FAMILY.LAIA].forEach((person) => {
|
||||
html += `<div class="fc-minimal-balance-card">
|
||||
<strong class="${person.prefix}">${person.prefix.toUpperCase()}</strong>
|
||||
<div class="fc-minimal-chips">`;
|
||||
|
||||
["CP", "JRA", "JA"].forEach((type) => {
|
||||
// Solde de départ = celui du PREMIER mois affiché
|
||||
const startInfo =
|
||||
this.monthlyLeaveBalances[person.id]?.[type]?.[monthsToDisplay[0]];
|
||||
const startBal = startInfo ? startInfo.availableAtMonthStart : 0;
|
||||
|
||||
// Jours posés = Somme sur TOUS les mois affichés
|
||||
let totalUsed = 0;
|
||||
monthsToDisplay.forEach((ym) => {
|
||||
const info = this.monthlyLeaveBalances[person.id]?.[type]?.[ym];
|
||||
if (info) totalUsed += info.usedInMonth;
|
||||
});
|
||||
|
||||
// Solde de fin (théorique) à la fin de la période
|
||||
const endBal = Math.max(0, startBal - totalUsed);
|
||||
const fmt = (n) =>
|
||||
n > 0 ? (Number.isInteger(n) ? n : n.toFixed(1)) : "0";
|
||||
|
||||
// Petit badge rouge uniquement s'il y a des congés posés
|
||||
const usedHtml =
|
||||
totalUsed > 0
|
||||
? `<span class="fc-used-badge" title="Posé sur la période">-${fmt(totalUsed)}</span>`
|
||||
: "";
|
||||
|
||||
html += `<div class="fc-min-chip" title="Solde de départ: ${fmt(startBal)}">
|
||||
// --- LOGIQUE D'ALERTE FIRE 🔥 ---
|
||||
let alertHtml = "";
|
||||
const currentYm = monthsToDisplay[0];
|
||||
const [cYear, cMonth] = currentYm.split("-").map(Number);
|
||||
|
||||
if (endBal > 0) {
|
||||
if (type === "CP" && cMonth >= 6 && cMonth <= 7) {
|
||||
// CP : Alerte en Juin et Juillet uniquement
|
||||
let msg = (
|
||||
window.I18N["fc_alert_burn_days"] || "Perte: %s j avant le %s"
|
||||
)
|
||||
.replace("%s", fmt(endBal))
|
||||
.replace("%s", "31/07");
|
||||
alertHtml = `<div class="fc-burn-alert" title="${msg}">🔥</div>`;
|
||||
} else if (type === "JRA" && (cMonth === 1 || cMonth === 2)) {
|
||||
// JRA : Alerte Janvier/Février si > 2 jours
|
||||
if (endBal > 2) {
|
||||
let msg =
|
||||
window.I18N["fc_alert_burn_jra"] || "Seuls 2j reportables";
|
||||
alertHtml = `<div class="fc-burn-alert" title="${msg}">🔥 ${fmt(endBal - 2)}</div>`;
|
||||
}
|
||||
} else if (type === "JA") {
|
||||
const configJA = LEAVES_CONFIG.JA[person.id];
|
||||
let limitMonth = configJA.startMonth - 1 || 12;
|
||||
if (cMonth === limitMonth || cMonth === configJA.startMonth) {
|
||||
let msg = (window.I18N["fc_alert_burn_days"] || "Perte: %s j")
|
||||
.replace("%s", fmt(endBal))
|
||||
.replace("%s", window.I18N["ANNIV"] || "Anniv");
|
||||
alertHtml = `<div class="fc-burn-alert" title="${msg}">🔥</div>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
html += `<div class="fc-min-chip" title="Solde départ: ${fmt(startBal)}">
|
||||
<span class="type">${type}</span>
|
||||
<span class="val" title="Restant">${fmt(endBal)}</span>
|
||||
${usedHtml}
|
||||
${alertHtml}
|
||||
</div>`;
|
||||
});
|
||||
html += `</div></div>`;
|
||||
@@ -1160,7 +1192,8 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
|
||||
if (btnSnap && modalSnap) {
|
||||
btnSnap.addEventListener("click", () => {
|
||||
modalSnap.style.display = "flex";
|
||||
modalSnap.style.display = "flex"; // Utilise flex au lieu de block pour le centrage
|
||||
document.body.classList.add("no-scroll");
|
||||
// Pré-remplir la date avec le 1er jour du mois en cours
|
||||
const today = new Date();
|
||||
const y = today.getFullYear();
|
||||
|
||||
+898
-657
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user