fix bulk menu

This commit is contained in:
2026-01-07 15:32:42 +01:00
parent abe85cb5d3
commit eee36e4034
5 changed files with 2176 additions and 640 deletions
+13 -14
View File
@@ -202,20 +202,19 @@ require __DIR__ . '/header.php';
<tr> <tr>
<!-- Ligne 3 : Available / Use pour chaque type --> <!-- Ligne 3 : Available / Use pour chaque type -->
<!-- ALEX --> <!-- ALEX -->
<th class="col-alex-sub">Av.</th> <th class="col-alex-sub col-alex-av">Av.</th>
<th class="col-alex-sub">Use</th> <th class="col-alex-sub col-alex-use">Use</th>
<th class="col-alex-sub">Av.</th> <th class="col-alex-sub col-alex-av">Av.</th>
<th class="col-alex-sub">Use</th> <th class="col-alex-sub col-alex-use">Use</th>
<th class="col-alex-sub">Av.</th> <th class="col-alex-sub col-alex-av">Av.</th>
<th class="col-alex-sub">Use</th> <th class="col-alex-sub col-alex-use">Use</th>
<!-- LAIA -->
<!-- LAIA --> <th class="col-laia-sub col-laia-av">Av.</th>
<th class="col-laia-sub">Av.</th> <th class="col-laia-sub col-laia-use">Use</th>
<th class="col-laia-sub">Use</th> <th class="col-laia-sub col-laia-av">Av.</th>
<th class="col-laia-sub">Av.</th> <th class="col-laia-sub col-laia-use">Use</th>
<th class="col-laia-sub">Use</th> <th class="col-laia-sub col-laia-av">Av.</th>
<th class="col-laia-sub">Av.</th> <th class="col-laia-sub col-laia-use">Use</th>
<th class="col-laia-sub">Use</th>
</tr> </tr>
</thead> </thead>
</table> </table>
+124 -21
View File
@@ -38,6 +38,22 @@
text-overflow: ellipsis; text-overflow: ellipsis;
} }
/* Colonnes "Av." non modifiables : fond gris clair + texte un peu atténué */
#planningHeaderTable th.col-alex-av,
#planningTable td.col-alex-av,
#planningHeaderTable th.col-laia-av,
#planningTable td.col-laia-av {
background-color: #e5e7eb;
color: #4b5563;
font-weight: 600;
}
/* Optionnel : curseur "not-allowed" pour marquer le côté non éditable */
#planningTable td.col-alex-av,
#planningTable td.col-laia-av {
cursor: not-allowed;
}
/* Mois / Semaine */ /* Mois / Semaine */
#planningHeaderTable .col-month, #planningHeaderTable .col-month,
#planningTable .col-month { #planningTable .col-month {
@@ -175,48 +191,125 @@
cursor: pointer; cursor: pointer;
} }
/* Le menu contextuel flottant */ /* Conteneur du menu de sélection (hebdo & mensuel) */
.fc-selection-menu { .fc-selection-menu {
display: none; display: none;
position: absolute; position: absolute;
z-index: 100; z-index: 100;
background-color: white; background-color: #ffffff;
border: 1px solid #ccc; border: 1px solid #d1d5db; /* gris clair */
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 12px rgba(15, 23, 42, 0.18);
border-radius: 6px; border-radius: 8px;
padding: 8px; padding: 8px 10px;
font-size: 12px; font-size: 12px;
min-width: 220px;
max-width: 360px;
} }
.fc-selection-menu .fc-menu-section { /* Sections internes avec titre */
.fc-menu-section {
margin-bottom: 8px; margin-bottom: 8px;
} }
.fc-selection-menu .fc-menu-section:last-child { .fc-menu-section > strong {
margin-bottom: 0;
}
.fc-selection-menu strong {
display: block; display: block;
margin-bottom: 4px; margin-bottom: 4px;
font-weight: 600; font-weight: 600;
color: #111827; /* gris très foncé */
} }
.fc-selection-menu button { /* Grille pour disposer proprement les boutons dans une section */
.fc-menu-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4px;
}
/* Boutons génériques du menu */
.fc-selection-menu button.fc-menu-btn,
.fc-selection-menu button.fc-menu-leave-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 100%;
border-radius: 4px;
border: 1px solid #e5e7eb;
padding: 4px 6px;
font-size: 12px;
background: #f9fafb;
color: #111827;
cursor: pointer;
transition: background-color 0.15s ease, border-color 0.15s ease,
box-shadow 0.15s ease;
}
.fc-selection-menu button.fc-menu-btn:hover,
.fc-selection-menu button.fc-menu-leave-btn:hover {
background-color: #e5f0ff; /* léger bleu */
border-color: #93c5fd;
box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.3);
}
/* Variantes par type pour un léger hint visuel
.fc-menu-btn--conge {
congés Carole
}
.fc-menu-btn--garde {
mode de garde
}
.fc-menu-btn--pep {
Pep malade
} */
/* Boutons "danger" (suppression) */
.fc-selection-menu button.fc-menu-danger {
display: block; display: block;
width: 100%; width: 100%;
background: none; margin-top: 6px;
border: 1px solid #ddd; padding: 4px 6px;
border-radius: 4px; border-radius: 4px;
padding: 4px 8px; border: 1px solid #fecaca;
margin-top: 4px; background-color: #fef2f2;
text-align: left; color: #b91c1c;
font-size: 12px;
cursor: pointer; cursor: pointer;
text-align: left;
} }
.fc-selection-menu button:hover { .fc-selection-menu button.fc-menu-danger:hover {
background-color: #f0f4f8; background-color: #fee2e2;
border-color: #b0c4de; border-color: #fca5a5;
}
/* Tableau des congés Alex / Laia dans le menu */
.fc-menu-leaves-table {
margin-top: 4px;
}
.fc-menu-leaves-table table {
width: 100%;
border-collapse: collapse;
font-size: 11px;
}
.fc-menu-leaves-table th,
.fc-menu-leaves-table td {
padding: 2px;
text-align: center;
}
.fc-menu-leaves-table thead th {
font-weight: 600;
color: #374151;
border-bottom: 1px solid #e5e7eb;
}
.fc-menu-leaves-table tbody td:first-child {
text-align: left;
font-weight: 500;
color: #4b5563;
} }
/* --- Couleurs de base pour la légende et les jours --- */ /* --- Couleurs de base pour la légende et les jours --- */
@@ -422,6 +515,7 @@
.fc-calendar-and-summary { .fc-calendar-and-summary {
display: block; display: block;
position: relative;
} }
.fc-month-header { .fc-month-header {
@@ -678,6 +772,15 @@
line-height: 1; line-height: 1;
} }
/* Bordure épaisse pour délimiter les mois dans le planning hebdo */
#planningTable tr.fc-month-first-week-row td {
border-top: 2px solid #243b53; /* couleur sombre cohérente avec ta charte */
}
#planningTable tr.fc-month-last-week-row td {
border-bottom: 2px solid #243b53;
}
/* === TABLEAU RÉCAPITULATIF === */ /* === TABLEAU RÉCAPITULATIF === */
.fc-month-summary { .fc-month-summary {
File diff suppressed because it is too large Load Diff
@@ -16,3 +16,11 @@
[2026-01-06T15:17:03+01:00] RAW INPUT: [{"date":"2025-09-10","type":"CENTRE","duration":1}] [2026-01-06T15:17:03+01:00] RAW INPUT: [{"date":"2025-09-10","type":"CENTRE","duration":1}]
[2026-01-06T15:26:35+01:00] RAW INPUT: [{"date":"2025-10-06","type":"PEP_SICK","duration":1},{"date":"2025-10-07","type":"PEP_SICK","duration":1},{"date":"2025-10-08","type":"PEP_SICK","duration":1}] [2026-01-06T15:26:35+01:00] RAW INPUT: [{"date":"2025-10-06","type":"PEP_SICK","duration":1},{"date":"2025-10-07","type":"PEP_SICK","duration":1},{"date":"2025-10-08","type":"PEP_SICK","duration":1}]
[2026-01-07T10:04:23+01:00] RAW INPUT: [{"date":"2025-09-19","type":"OFF_CAROLE","person":"Carole","duration":1}] [2026-01-07T10:04:23+01:00] RAW INPUT: [{"date":"2025-09-19","type":"OFF_CAROLE","person":"Carole","duration":1}]
[2026-01-07T11:10:59+01:00] RAW INPUT: [{"date":"2025-09-04","type":"CENTRE","duration":1}]
[2026-01-07T13:33:21+01:00] RAW INPUT: [{"date":"2025-09-08","type":"CENTRE","duration":1}]
[2026-01-07T13:33:26+01:00] RAW INPUT: [{"date":"2025-09-08","type":"OFF_CAROLE","person":"Carole","duration":1}]
[2026-01-07T13:33:32+01:00] RAW INPUT: [{"date":"2025-09-08","type":"PEP_SICK","duration":1}]
[2026-01-07T13:37:27+01:00] RAW INPUT: [{"date":"2025-10-13","type":"CENTRE","duration":1}]
[2026-01-07T14:26:31+01:00] RAW INPUT: [{"date":"2025-09-08","type":"OFF_CAROLE","person":"Carole","duration":1}]
[2026-01-07T14:26:36+01:00] RAW INPUT: [{"date":"2025-09-08","type":"OFF_CAROLE","person":"Carole","duration":1},{"date":"2025-09-09","type":"OFF_CAROLE","person":"Carole","duration":1}]
[2026-01-07T14:30:24+01:00] RAW INPUT: [{"date":"2025-10-06","type":"CENTRE","duration":1},{"date":"2025-10-07","type":"CENTRE","duration":1}]
@@ -5,16 +5,23 @@ require __DIR__ . '/../../../../includes/db.php';
$input = json_decode(file_get_contents('php://input'), true); $input = json_decode(file_get_contents('php://input'), true);
if (!isset($input['action'])) { if (!is_array($input)) {
http_response_code(400);
echo json_encode(['status' => 'error', 'message' => 'JSON invalide.']);
exit;
}
$action = $input['action'] ?? null;
if (!$action) {
http_response_code(400); http_response_code(400);
echo json_encode(['status' => 'error', 'message' => 'Action manquante.']); echo json_encode(['status' => 'error', 'message' => 'Action manquante.']);
exit; exit;
} }
$action = $input['action'];
try { try {
// ===================== DELETE TOUS LES LEAVES D'UN JOUR (EXISTANT) =====================
if ($action === 'delete_day') { if ($action === 'delete_day') {
if (empty($input['date'])) { if (empty($input['date'])) {
http_response_code(400); http_response_code(400);
echo json_encode(['status' => 'error', 'message' => 'Date manquante pour delete_day.']); echo json_encode(['status' => 'error', 'message' => 'Date manquante pour delete_day.']);
@@ -33,12 +40,99 @@ try {
$stmt->execute([$leaveDate]); $stmt->execute([$leaveDate]);
echo json_encode(['status' => 'success', 'message' => 'Congés supprimés pour ce jour.']); echo json_encode(['status' => 'success', 'message' => 'Congés supprimés pour ce jour.']);
exit;
} else {
http_response_code(400);
echo json_encode(['status' => 'error', 'message' => 'Action non valide.']);
} }
// ===================== DELETE POUR UNE PERSONNE / JOUR (SINGLE) =====================
if ($action === 'delete_day_person') {
$date = $input['date'] ?? null;
$personId = $input['person_id'] ?? null;
if (empty($date) || empty($personId)) {
http_response_code(400);
echo json_encode(['status' => 'error', 'message' => 'date ou person_id manquant pour delete_day_person.']);
exit;
}
$dateObj = date_create($date);
if (!$dateObj) {
http_response_code(400);
echo json_encode(['status' => 'error', 'message' => 'Date invalide pour delete_day_person.']);
exit;
}
$leaveDate = $dateObj->format('Y-m-d');
$stmt = $pdo->prepare("
DELETE FROM pf_leaves
WHERE leave_date = :date
AND person_id = :person_id
");
$stmt->execute([
':date' => $leaveDate,
':person_id' => $personId,
]);
echo json_encode([
'status' => 'success',
'message' => 'Congés supprimés pour cette personne et ce jour.',
'deleted' => $stmt->rowCount(),
]);
exit;
}
// ===================== BULK DELETE POUR UNE PERSONNE / PLUSIEURS JOURS =====================
if ($action === 'bulk_delete_day_person') {
$dates = $input['dates'] ?? null;
$personId = $input['person_id'] ?? null;
if (!is_array($dates) || empty($dates) || empty($personId)) {
http_response_code(400);
echo json_encode(['status' => 'error', 'message' => 'dates ou person_id manquant pour bulk_delete_day_person.']);
exit;
}
// Normaliser les dates en 'Y-m-d'
$normalizedDates = [];
foreach ($dates as $d) {
$dateObj = date_create($d);
if ($dateObj) {
$normalizedDates[] = $dateObj->format('Y-m-d');
}
}
if (empty($normalizedDates)) {
echo json_encode([
'status' => 'success',
'message' => 'Aucune date valide fournie.',
'deleted' => 0,
]);
exit;
}
// Construire le IN (...)
$placeholders = implode(',', array_fill(0, count($normalizedDates), '?'));
$sql = "
DELETE FROM pf_leaves
WHERE person_id = ?
AND leave_date IN ($placeholders)
";
$stmt = $pdo->prepare($sql);
$params = array_merge([$personId], $normalizedDates);
$stmt->execute($params);
echo json_encode([
'status' => 'success',
'message' => 'Congés supprimés pour cette personne sur les dates fournies.',
'deleted' => $stmt->rowCount(),
]);
exit;
}
// ===================== ACTION NON RECONNUE =====================
http_response_code(400);
echo json_encode(['status' => 'error', 'message' => 'Action non valide.']);
} catch (PDOException $e) { } catch (PDOException $e) {
http_response_code(500); http_response_code(500);
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]); echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);