layout
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
require __DIR__ . '/../includes/db.php';
|
||||
|
||||
try {
|
||||
$stmt = $pdo->query("SELECT id, event_date AS date, event_type AS type, person_id, duration FROM pf_events ORDER BY event_date");
|
||||
$events = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'events' => $events,
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'Erreur lors de la récupération des événements : ' . $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
// api/get-leaves.php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
require __DIR__ . '/../includes/db.php';
|
||||
|
||||
try {
|
||||
$stmt = $pdo->query("
|
||||
SELECT
|
||||
l.id,
|
||||
l.person_id,
|
||||
p.name AS person_name,
|
||||
l.leave_type,
|
||||
l.leave_date,
|
||||
l.duration
|
||||
FROM pf_leaves l
|
||||
JOIN pf_people p ON p.id = l.person_id
|
||||
ORDER BY l.leave_date, l.person_id
|
||||
");
|
||||
|
||||
$leaves = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'leaves' => $leaves,
|
||||
]);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require __DIR__ . '/../includes/db.php';
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (!isset($input['action'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Action manquante.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$action = $input['action'];
|
||||
|
||||
try {
|
||||
if ($action === 'delete') {
|
||||
// Suppression d'un seul événement
|
||||
if (!isset($input['event_id'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'ID manquant pour la suppression.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$eventId = (int)$input['event_id'];
|
||||
$stmt = $pdo->prepare("DELETE FROM pf_events WHERE id = ?");
|
||||
$stmt->execute([$eventId]);
|
||||
|
||||
echo json_encode(['status' => 'success', 'message' => 'Événement supprimé.']);
|
||||
|
||||
} elseif ($action === 'update') {
|
||||
// Mise à jour d'un seul événement
|
||||
if (!isset($input['event_id'], $input['new_type'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'ID ou nouveau type manquant pour la mise à jour.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$eventId = (int)$input['event_id'];
|
||||
$newType = $input['new_type'];
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE pf_events SET event_type = ? WHERE id = ?");
|
||||
$stmt->execute([$newType, $eventId]);
|
||||
|
||||
echo json_encode(['status' => 'success', 'message' => 'Événement mis à jour.']);
|
||||
|
||||
} elseif ($action === 'bulk_delete') {
|
||||
// Suppression en masse
|
||||
if (empty($input['event_ids']) || !is_array($input['event_ids'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Liste event_ids manquante pour bulk_delete.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$eventIds = array_map('intval', $input['event_ids']);
|
||||
$eventIds = array_filter($eventIds, fn($id) => $id > 0);
|
||||
|
||||
if (empty($eventIds)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Aucun ID valide pour bulk_delete.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$placeholders = implode(',', array_fill(0, count($eventIds), '?'));
|
||||
$stmt = $pdo->prepare("DELETE FROM pf_events WHERE id IN ($placeholders)");
|
||||
$stmt->execute($eventIds);
|
||||
|
||||
echo json_encode(['status' => 'success', 'message' => 'Événements supprimés en masse.']);
|
||||
|
||||
} elseif ($action === 'bulk_update') {
|
||||
// Mise à jour en masse
|
||||
if (empty($input['event_ids']) || !is_array($input['event_ids']) || !isset($input['new_type'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'event_ids ou new_type manquant pour bulk_update.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$eventIds = array_map('intval', $input['event_ids']);
|
||||
$eventIds = array_filter($eventIds, fn($id) => $id > 0);
|
||||
$newType = $input['new_type'];
|
||||
|
||||
if (empty($eventIds)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Aucun ID valide pour bulk_update.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$placeholders = implode(',', array_fill(0, count($eventIds), '?'));
|
||||
$params = array_merge([$newType], $eventIds);
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE pf_events SET event_type = ? WHERE id IN ($placeholders)");
|
||||
$stmt->execute($params);
|
||||
|
||||
echo json_encode(['status' => 'success', 'message' => 'Événements mis à jour en masse.']);
|
||||
|
||||
} else {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Action non valide.']);
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
// api/manage-leaf.php
|
||||
header('Content-Type: application/json');
|
||||
require __DIR__ . '/../includes/db.php';
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (!isset($input['action'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Action manquante.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$action = $input['action'];
|
||||
|
||||
try {
|
||||
if ($action === 'delete_day') {
|
||||
if (empty($input['date'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Date manquante pour delete_day.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$dateObj = date_create($input['date']);
|
||||
if (!$dateObj) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Date invalide.']);
|
||||
exit;
|
||||
}
|
||||
$leaveDate = $dateObj->format('Y-m-d');
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM pf_leaves WHERE leave_date = ?");
|
||||
$stmt->execute([$leaveDate]);
|
||||
|
||||
echo json_encode(['status' => 'success', 'message' => 'Congés supprimés pour ce jour.']);
|
||||
|
||||
} else {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Action non valide.']);
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require __DIR__ . '/../includes/db.php';
|
||||
|
||||
$eventsToSave = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (empty($eventsToSave) || !is_array($eventsToSave)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Aucune donnée d\'événement reçue.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$inserted = [];
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
$sql = "INSERT INTO pf_events (event_date, event_type, person_id, duration)
|
||||
VALUES (:event_date, :event_type, :person_id, :duration)";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
foreach ($eventsToSave as $event) {
|
||||
$person_id = null;
|
||||
|
||||
// Si un nom de personne est fourni
|
||||
if (!empty($event['person'])) {
|
||||
$personStmt = $pdo->prepare("SELECT id FROM pf_people WHERE name = ?");
|
||||
$personStmt->execute([$event['person']]);
|
||||
$personRow = $personStmt->fetch();
|
||||
if ($personRow) {
|
||||
$person_id = $personRow['id'];
|
||||
}
|
||||
}
|
||||
|
||||
$stmt->execute([
|
||||
':event_date' => $event['date'],
|
||||
':event_type' => $event['type'],
|
||||
':person_id' => $person_id,
|
||||
':duration' => $event['duration'] ?? 1.0,
|
||||
]);
|
||||
|
||||
$inserted[] = [
|
||||
'id' => $pdo->lastInsertId(),
|
||||
'date' => $event['date'],
|
||||
'type' => $event['type'],
|
||||
'duration' => $event['duration'] ?? 1.0,
|
||||
'person_id' => $person_id,
|
||||
];
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'inserted' => $inserted,
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
$pdo->rollBack();
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Erreur lors de la sauvegarde : ' . $e->getMessage()]);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
// api/save-leaves.php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
require __DIR__ . '/../includes/db.php';
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (!is_array($input) || empty($input)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Données invalides (attendu tableau JSON).']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Exemple d'élément attendu :
|
||||
// { date: '2025-09-01', person_id: 2, leave_type: 'CP', duration: 1.0 }
|
||||
|
||||
$validLeaveTypes = ['CP', 'JRA', 'JA'];
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
$stmtInsert = $pdo->prepare("
|
||||
INSERT INTO pf_leaves (person_id, leave_type, leave_date, duration)
|
||||
VALUES (:person_id, :leave_type, :leave_date, :duration)
|
||||
");
|
||||
|
||||
foreach ($input as $item) {
|
||||
$date = $item['date'] ?? null;
|
||||
$personId = $item['person_id'] ?? null;
|
||||
$leaveType = $item['leave_type'] ?? null;
|
||||
$duration = isset($item['duration']) ? (float)$item['duration'] : 1.0;
|
||||
|
||||
if (!$date || !$personId || !$leaveType) {
|
||||
continue; // on ignore les lignes incomplètes
|
||||
}
|
||||
|
||||
if (!in_array($leaveType, $validLeaveTypes, true)) {
|
||||
continue; // leave_type invalide
|
||||
}
|
||||
|
||||
// Normalisation de la date
|
||||
$dateObj = date_create($date);
|
||||
if (!$dateObj) {
|
||||
continue;
|
||||
}
|
||||
$leaveDate = $dateObj->format('Y-m-d');
|
||||
|
||||
$stmtInsert->execute([
|
||||
':person_id' => (int)$personId,
|
||||
':leave_type' => $leaveType,
|
||||
':leave_date' => $leaveDate,
|
||||
':duration' => $duration,
|
||||
]);
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'message' => 'Congés enregistrés.',
|
||||
]);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
$pdo->rollBack();
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
@@ -0,0 +1,726 @@
|
||||
/* === TABLES SPÉCIFIQUES AU FAMILY CALENDAR === */
|
||||
|
||||
/* Tableau des vacances scolaires */
|
||||
#schoolHolidaysTable {
|
||||
width: auto;
|
||||
table-layout: auto;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.pf-card.pf-card--wide .pf-table-wrapper {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
/* En-têtes et cellules sans retour à la ligne */
|
||||
#schoolHolidaysTable th,
|
||||
#schoolHolidaysTable td {
|
||||
white-space: nowrap;
|
||||
overflow: visible;
|
||||
padding: 4px 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Planning hebdomadaire principal */
|
||||
#planningTable {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#planningTable th,
|
||||
#planningTable td {
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* Colonnes "Mois" et "Semaine" plus étroites */
|
||||
#planningTable th:nth-child(1),
|
||||
#planningTable td:nth-child(1),
|
||||
#planningTable th:nth-child(2),
|
||||
#planningTable td:nth-child(2) {
|
||||
width: 2%;
|
||||
}
|
||||
|
||||
/* Colonnes jours (Lundi à Vendredi) */
|
||||
#planningTable th:nth-child(3),
|
||||
#planningTable td:nth-child(3),
|
||||
#planningTable th:nth-child(4),
|
||||
#planningTable td:nth-child(4),
|
||||
#planningTable th:nth-child(5),
|
||||
#planningTable td:nth-child(5),
|
||||
#planningTable th:nth-child(6),
|
||||
#planningTable td:nth-child(6),
|
||||
#planningTable th:nth-child(7),
|
||||
#planningTable td:nth-child(7) {
|
||||
width: 2%;
|
||||
}
|
||||
|
||||
/* Colonnes de totaux */
|
||||
#planningTable th:nth-child(8),
|
||||
#planningTable td:nth-child(8),
|
||||
#planningTable th:nth-child(9),
|
||||
#planningTable td:nth-child(9),
|
||||
#planningTable th:nth-child(10),
|
||||
#planningTable td:nth-child(10),
|
||||
#planningTable th:nth-child(11),
|
||||
#planningTable td:nth-child(11) {
|
||||
width: 4%;
|
||||
}
|
||||
|
||||
/* === COLOR CODING / LÉGENDE === */
|
||||
|
||||
.fc-row--carole-off {
|
||||
background: #ffe0e0;
|
||||
}
|
||||
|
||||
.fc-row--bank-holiday {
|
||||
background: #d9f7be;
|
||||
}
|
||||
|
||||
/* Tableau recap vacances scolaires */
|
||||
.fc-holidays-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.fc-holidays-table th,
|
||||
.fc-holidays-table td {
|
||||
border: none;
|
||||
padding: 4px 4px;
|
||||
}
|
||||
|
||||
.fc-holidays-table thead th {
|
||||
background: none;
|
||||
font-weight: 600;
|
||||
color: #243b53;
|
||||
padding-bottom: 4px;
|
||||
border-bottom: 1px solid #d9e2ec;
|
||||
}
|
||||
|
||||
.fc-holidays-table tbody tr:nth-child(odd) td {
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.fc-holidays-table tbody tr:nth-child(even) td {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Cellule de jour sélectionnée dans le calendrier */
|
||||
.fc-day--selected {
|
||||
background-color: #bde4ff !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Le menu contextuel flottant */
|
||||
.fc-selection-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
border-radius: 6px;
|
||||
padding: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.fc-selection-menu .fc-menu-section {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.fc-selection-menu .fc-menu-section:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.fc-selection-menu strong {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.fc-selection-menu button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
background: none;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
padding: 4px 8px;
|
||||
margin-top: 4px;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fc-selection-menu button:hover {
|
||||
background-color: #f0f4f8;
|
||||
border-color: #b0c4de;
|
||||
}
|
||||
|
||||
/* --- Couleurs de base pour la légende et les jours --- */
|
||||
.fc-day--school-holiday {
|
||||
background-color: #e5d9f2;
|
||||
}
|
||||
.fc-day--public-holiday {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
.fc-day--off-carole {
|
||||
background-color: #ffe9a7;
|
||||
}
|
||||
.fc-day--extra-off-carole {
|
||||
background-color: #ffd59b;
|
||||
}
|
||||
.fc-day--has-guard {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Picto pour Centre */
|
||||
.fc-day--has-guard.fc-day--centre {
|
||||
position: relative;
|
||||
}
|
||||
.fc-day--has-guard.fc-day--centre::after {
|
||||
content: "🏫";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Combinaisons avec dégradés */
|
||||
.fc-day--school-holiday.fc-day--off-carole {
|
||||
background-image: linear-gradient(45deg, #e5d9f2 49%, #ffe9a7 51%);
|
||||
}
|
||||
.fc-day--school-holiday.fc-day--extra-off-carole {
|
||||
background-image: linear-gradient(45deg, #e5d9f2 49%, #ffd59b 51%);
|
||||
}
|
||||
|
||||
/* Légende */
|
||||
.pf-legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.pf-legend-color {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #d9e2ec;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.pf-legend-item span {
|
||||
font-size: 12px;
|
||||
color: #334e68;
|
||||
}
|
||||
|
||||
.fc-legend-school-holiday {
|
||||
background-color: #e5d9f2;
|
||||
}
|
||||
|
||||
.fc-legend-public-holiday {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.fc-legend-off-carole {
|
||||
background-color: #ffe9a7;
|
||||
}
|
||||
|
||||
.fc-legend-extra-off-carole {
|
||||
background-color: #ffd59b;
|
||||
}
|
||||
|
||||
.fc-legend-centre {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.fc-legend-centre::before {
|
||||
content: "🏫";
|
||||
}
|
||||
|
||||
/* Avis indicateur */
|
||||
.fc-legend-avis {
|
||||
border-radius: 2px;
|
||||
width: 24px;
|
||||
height: 16px;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
#ffcc00 0%,
|
||||
#ffcc00 11%,
|
||||
#c8102e 11%,
|
||||
#c8102e 22%,
|
||||
#ffcc00 22%,
|
||||
#ffcc00 33%,
|
||||
#c8102e 33%,
|
||||
#c8102e 44%,
|
||||
#ffcc00 44%,
|
||||
#ffcc00 55%,
|
||||
#c8102e 55%,
|
||||
#c8102e 66%,
|
||||
#ffcc00 66%,
|
||||
#ffcc00 77%,
|
||||
#c8102e 77%,
|
||||
#c8102e 88%,
|
||||
#ffcc00 88%,
|
||||
#ffcc00 100%
|
||||
);
|
||||
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* === CALENDRIER MENSUEL === */
|
||||
|
||||
.fc-day--has-guard.fc-day--avis {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fc-day--has-guard.fc-day--avis::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
width: 14px;
|
||||
height: 8px;
|
||||
border-radius: 2px;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
#ffcc00 0%,
|
||||
#ffcc00 11%,
|
||||
#c8102e 11%,
|
||||
#c8102e 22%,
|
||||
#ffcc00 22%,
|
||||
#ffcc00 33%,
|
||||
#c8102e 33%,
|
||||
#c8102e 44%,
|
||||
#ffcc00 44%,
|
||||
#ffcc00 55%,
|
||||
#c8102e 55%,
|
||||
#c8102e 66%,
|
||||
#ffcc00 66%,
|
||||
#ffcc00 77%,
|
||||
#c8102e 77%,
|
||||
#c8102e 88%,
|
||||
#ffcc00 88%,
|
||||
#ffcc00 100%
|
||||
);
|
||||
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.fc-month-calendar-wrapper {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||
border: 1px solid #d9e2ec;
|
||||
}
|
||||
|
||||
.fc-calendar-and-summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.fc-month-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 2px solid #d9e2ec;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.fc-view-controls {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.fc-view-button {
|
||||
background: #f0f4f8;
|
||||
border: 1px solid #d9e2ec;
|
||||
border-radius: 4px;
|
||||
padding: 6px 12px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
color: #243b53;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.fc-view-button:hover {
|
||||
background: #d9e2ec;
|
||||
border-color: #bcccdc;
|
||||
}
|
||||
|
||||
.fc-view-button--active {
|
||||
background: #243b53;
|
||||
color: #fff;
|
||||
border-color: #243b53;
|
||||
}
|
||||
|
||||
.fc-view-button--active:hover {
|
||||
background: #102a43;
|
||||
border-color: #102a43;
|
||||
}
|
||||
|
||||
.fc-nav-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.fc-month-header h3 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #243b53;
|
||||
min-width: 200px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fc-nav-button {
|
||||
background: #f0f4f8;
|
||||
border: 1px solid #d9e2ec;
|
||||
border-radius: 4px;
|
||||
padding: 6px 12px;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
color: #243b53;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.fc-nav-button:hover {
|
||||
background: #d9e2ec;
|
||||
border-color: #bcccdc;
|
||||
}
|
||||
|
||||
.fc-month-calendar {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fc-month-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.fc-month-table thead th {
|
||||
background: #f0f4f8;
|
||||
padding: 8px 4px;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
color: #243b53;
|
||||
border: 1px solid #d9e2ec;
|
||||
}
|
||||
|
||||
.fc-month-table tbody td {
|
||||
border: 1px solid #d9e2ec;
|
||||
padding: 8px 4px;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
min-height: 60px;
|
||||
height: 60px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.fc-month-summary-inline {
|
||||
margin-top: 8px;
|
||||
background: #f8fafc;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #d9e2ec;
|
||||
font-size: 12px;
|
||||
padding: 6px 8px;
|
||||
}
|
||||
|
||||
.fc-month-summary-inline table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.fc-month-summary-inline th,
|
||||
.fc-month-summary-inline td {
|
||||
padding: 4px 6px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fc-month-summary-inline th {
|
||||
font-weight: 600;
|
||||
color: #243b53;
|
||||
border-bottom: 1px solid #d9e2ec;
|
||||
}
|
||||
|
||||
.fc-month-summary-inline td:first-child {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.fc-month-day {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.fc-month-day:hover {
|
||||
background: #f8fafc !important;
|
||||
}
|
||||
|
||||
.fc-day--other-month {
|
||||
background: #f0f4f8;
|
||||
color: #9fb3c8;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.fc-day--weekend {
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.fc-day--weekend.fc-day--school-holiday,
|
||||
.fc-day--weekend.fc-day--public-holiday,
|
||||
.fc-day--weekend.fc-day--off-carole,
|
||||
.fc-day--weekend.fc-day--extra-off-carole {
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
/* Application des couleurs existantes au calendrier mensuel */
|
||||
.fc-month-table .fc-day--school-holiday {
|
||||
background-color: #e5d9f2;
|
||||
}
|
||||
|
||||
.fc-month-table .fc-day--public-holiday {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.fc-month-table .fc-day--off-carole {
|
||||
background-color: #ffe9a7;
|
||||
}
|
||||
|
||||
.fc-month-table .fc-day--extra-off-carole {
|
||||
background-color: #ffd59b;
|
||||
}
|
||||
|
||||
.fc-month-table .fc-day--has-guard {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.fc-month-table .fc-day--has-guard.fc-day--centre {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fc-month-table .fc-day--has-guard.fc-day--centre::after {
|
||||
content: "🏫";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.fc-month-table .fc-day--has-guard.fc-day--avis {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fc-month-table .fc-day--has-guard.fc-day--avis::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
width: 12px;
|
||||
height: 7px;
|
||||
border-radius: 2px;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
#ffcc00 0%,
|
||||
#ffcc00 11%,
|
||||
#c8102e 11%,
|
||||
#c8102e 22%,
|
||||
#ffcc00 22%,
|
||||
#ffcc00 33%,
|
||||
#c8102e 33%,
|
||||
#c8102e 44%,
|
||||
#ffcc00 44%,
|
||||
#ffcc00 55%,
|
||||
#c8102e 55%,
|
||||
#c8102e 66%,
|
||||
#ffcc00 66%,
|
||||
#ffcc00 77%,
|
||||
#c8102e 77%,
|
||||
#c8102e 88%,
|
||||
#ffcc00 88%,
|
||||
#ffcc00 100%
|
||||
);
|
||||
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.fc-month-table .fc-day--selected {
|
||||
background-color: #bde4ff !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fc-leaves-label-container {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 2px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.fc-leaves-label {
|
||||
font-size: 8px;
|
||||
font-weight: 600;
|
||||
color: #1f2933;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* === TABLEAU RÉCAPITULATIF === */
|
||||
|
||||
.fc-month-summary {
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.fc-summary-table-wrapper {
|
||||
background: #f8fafc;
|
||||
border-radius: 10px;
|
||||
padding: 10px 10px 12px;
|
||||
border: 1px solid #d9e2ec;
|
||||
box-shadow: 0 4px 10px rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.fc-summary-table {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.fc-summary-table thead th {
|
||||
background: transparent;
|
||||
border-bottom: 1px solid #d9e2ec;
|
||||
}
|
||||
|
||||
.fc-summary-table tbody td {
|
||||
border: none;
|
||||
border-bottom: 1px solid #edf2f7;
|
||||
}
|
||||
|
||||
.fc-summary-table tbody tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.fc-summary-total-row {
|
||||
background: #f0f4f8 !important;
|
||||
border-top: 2px solid #243b53;
|
||||
}
|
||||
|
||||
.fc-summary-total-row td {
|
||||
background: #f0f4f8 !important;
|
||||
font-weight: 600;
|
||||
color: #243b53;
|
||||
}
|
||||
|
||||
/* Responsive pour le calendrier et le récapitulatif */
|
||||
@media (max-width: 1200px) {
|
||||
.fc-calendar-and-summary {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.fc-month-summary {
|
||||
min-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* === VUE 2 MOIS === */
|
||||
.fc-two-months-container {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.fc-month-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fc-month-title {
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
color: #243b53;
|
||||
margin-bottom: 12px;
|
||||
text-align: center;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #d9e2ec;
|
||||
}
|
||||
|
||||
/* === VUE ANNÉE === */
|
||||
.fc-year-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.fc-year-month {
|
||||
background: #f8fafc;
|
||||
border: 1px solid #d9e2ec;
|
||||
border-radius: 6px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.fc-year-month-title {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
color: #243b53;
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #d9e2ec;
|
||||
}
|
||||
|
||||
.fc-year-month .fc-month-table {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.fc-year-month .fc-month-table thead th {
|
||||
padding: 4px 2px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.fc-year-month .fc-month-table tbody td {
|
||||
padding: 4px 2px;
|
||||
height: 32px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* Responsive pour la vue année */
|
||||
@media (max-width: 1200px) {
|
||||
.fc-year-container {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.fc-two-months-container {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.fc-year-container {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.fc-month-header {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.fc-view-controls {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.fc-nav-controls {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user