fix bulk menu
This commit is contained in:
+12
-13
@@ -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">Av.</th>
|
<th class="col-laia-sub col-laia-av">Av.</th>
|
||||||
<th class="col-laia-sub">Use</th>
|
<th class="col-laia-sub col-laia-use">Use</th>
|
||||||
<th class="col-laia-sub">Av.</th>
|
<th class="col-laia-sub col-laia-av">Av.</th>
|
||||||
<th class="col-laia-sub">Use</th>
|
<th class="col-laia-sub col-laia-use">Use</th>
|
||||||
<th class="col-laia-sub">Av.</th>
|
<th class="col-laia-sub col-laia-av">Av.</th>
|
||||||
<th class="col-laia-sub">Use</th>
|
<th class="col-laia-sub col-laia-use">Use</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -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,11 +40,98 @@ 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 {
|
// ===================== 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);
|
http_response_code(400);
|
||||||
echo json_encode(['status' => 'error', 'message' => 'Action non valide.']);
|
echo json_encode(['status' => 'error', 'message' => 'Action non valide.']);
|
||||||
}
|
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
|
|||||||
Reference in New Issue
Block a user