responsive

This commit is contained in:
2026-05-04 15:41:35 +02:00
parent 8c4c402f5b
commit 1babf4c52e
5 changed files with 254 additions and 68 deletions
+22
View File
@@ -63,4 +63,26 @@ require __DIR__ . '/header.php';
?>
</section>
</div>
<script>
// --- AUTO-SCROLL DES ONGLETS MOBILES ---
document.addEventListener('DOMContentLoaded', () => {
const tabsContainer = document.querySelector('.budget-tabs-container');
const activeTab = document.querySelector('.tab-item.active');
// Si on a bien un conteneur d'onglets ET un onglet actif
if (tabsContainer && activeTab) {
// On vérifie si le conteneur a un scroll horizontal possible
if (tabsContainer.scrollWidth > tabsContainer.clientWidth) {
// On calcule la position pour centrer l'onglet à l'écran
const scrollPos = activeTab.offsetLeft - (tabsContainer.offsetWidth / 2) + (activeTab.offsetWidth / 2);
// On fait glisser le menu doucement
tabsContainer.scrollTo({
left: scrollPos,
behavior: 'smooth'
});
}
}
});
</script>
<?php require __DIR__ . '/footer.php'; ?>
+26 -12
View File
@@ -13,12 +13,22 @@
--shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
}
* {
/* 🛡️ RESET MOBILE UNIVERSEL */
*,
*::before,
*::after {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
max-width: 100vw;
overflow-x: hidden; /* Empêche le site entier de glisser de gauche à droite */
}
body {
font-family:
"Inter",
-apple-system,
@@ -33,6 +43,14 @@ body {
flex-direction: column;
}
/* Images et médias responsive par défaut */
img,
svg,
video {
max-width: 100%;
height: auto;
}
/* === HEADER === */
.pf-header {
background: white;
@@ -120,14 +138,14 @@ body {
color: var(--text-main);
}
.pf-mobile-menu {
display: none; /* caché par défaut */
display: none;
position: fixed;
top: 64px;
left: 0;
right: 0;
height: calc(100vh - 64px); /* Remplace le bottom: 0 pour éviter le bug iOS */
overflow-y: auto; /* Permet le scroll si le menu contient beaucoup d'items */
-webkit-overflow-scrolling: touch; /* Fluidité sur iOS */
height: calc(100vh - 64px);
overflow-y: auto;
-webkit-overflow-scrolling: touch;
background: white;
padding: 20px;
flex-direction: column;
@@ -225,7 +243,6 @@ p {
.pf-module-card:hover .pf-card-cta::after {
transform: translateX(4px);
}
.pf-card--disabled {
opacity: 0.6;
pointer-events: none;
@@ -320,20 +337,17 @@ body.no-scroll {
.pf-burger-btn {
display: block;
}
/* Ajustements d'espacement pour petits écrans */
.pf-main {
padding: 16px;
}
padding: 16px 10px;
} /* Moins de padding latéral sur mobile */
.pf-modules-grid {
/* Sécurité : force 1 colonne sur mobile au lieu du auto-fill */
grid-template-columns: 1fr;
gap: 16px;
}
.pf-login-container {
margin: 30px 16px; /* Évite de toucher les bords de l'écran */
margin: 30px 16px;
padding: 24px;
}
+1 -1
View File
@@ -21,7 +21,7 @@ $currentLang = $_SESSION['app_lang'] ?? 'fr';
<html lang="<?= htmlspecialchars($currentLang) ?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title><?= htmlspecialchars($pageTitle) ?></title>
<link rel="icon" type="image/png" href="/favicon.png">
<link rel="apple-touch-icon" href="/favicon.png">
+202 -52
View File
@@ -178,6 +178,8 @@
text-decoration: none;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
transition: all 0.2s ease;
white-space: nowrap;
flex-shrink: 0;
}
.pf-btn:hover {
@@ -223,7 +225,7 @@
/* Sécurité de clic asynchrone */
.btn-safe-click {
position: relative;
z-index: 50 !important;
z-index: 10 !important;
pointer-events: auto !important;
}
@@ -312,13 +314,17 @@
overflow-x: auto;
}
.sticky-col {
position: sticky;
left: 0;
background: var(--bg-card);
z-index: 2;
position: sticky !important;
left: 0 !important;
background: var(--bg-card) !important;
z-index: 20 !important;
border-right: 1px solid var(--bg-page);
min-width: 150px;
}
th.sticky-col {
z-index: 30 !important;
background: #f8fafc !important;
}
.cell-amount {
font-family: "Consolas", "Monaco", monospace;
@@ -960,68 +966,212 @@ th.col-laia {
border: none;
}
/* --- 12. OPTIMISATIONS MOBILES PREVISIONNEL --- */
/* --- 12. OPTIMISATIONS MOBILES PREVISIONNEL & SUIVI (V6) --- */
@media (max-width: 768px) {
/* 1. ANTI-DÉBORDEMENT GLOBAL */
html,
body {
min-width: 680px !important;
overflow-x: auto !important;
position: relative;
}
header,
footer,
.navbar,
.site-header,
.site-footer {
min-width: 680px !important;
width: 100% !important;
box-sizing: border-box;
overflow-x: hidden !important;
width: 100vw !important;
}
.budget-view {
min-width: 680px !important;
width: 100%;
padding-right: 10px;
}
.prev-salary-table {
min-width: 100%;
width: 100%;
}
.prev-timeline-wrapper {
width: 100%;
overflow-x: auto !important;
display: block;
padding: 10px !important;
max-width: 100vw !important;
box-sizing: border-box;
}
/* Sur mobile, on garde les actions visibles sans hover */
.row-actions {
/* 2. ONGLETS PRINCIPAUX (Scroll horizontal fluide) */
.budget-tabs-container {
display: flex !important;
flex-wrap: nowrap !important;
overflow-x: auto !important;
justify-content: flex-start !important; /* Aligne à gauche pour scroller */
-webkit-overflow-scrolling: touch;
width: 100%;
padding-bottom: 5px;
/* Masque la barre de défilement inesthétique */
scrollbar-width: none;
}
.budget-tabs-container::-webkit-scrollbar {
display: none;
}
.tab-item {
flex: 0 0 auto !important; /* Interdit l'écrasement du texte */
padding: 8px 16px !important;
}
/* 3. RÉDUCTION DES ENCADRÉS DE SOLDES */
.budget-view > div[style*="display:grid"] {
gap: 10px !important;
margin-bottom: 15px !important;
}
.budget-view > div[style*="display:grid"] > div {
padding: 12px 10px !important;
}
/* 4. EN-TÊTES EPARGNE (Titre isolé, boutons 50/50 en dessous) */
.budget-view
> div[style*="justify-content: space-between"]:not(.view-header) {
flex-direction: column !important;
align-items: stretch !important;
gap: 12px !important;
margin-top: 20px !important;
}
/* Le titre (Nens/Pol/Pep) prend toute la ligne */
.budget-view
> div[style*="justify-content: space-between"]:not(.view-header)
> div:first-child {
width: 100% !important;
}
/* Les boutons se partagent la ligne suivante (50/50) */
.budget-view
> div[style*="justify-content: space-between"]:not(.view-header)
> div:last-child {
display: flex !important;
flex-direction: row !important;
flex-wrap: nowrap !important;
width: 100% !important;
gap: 10px !important;
}
.budget-view
> div[style*="justify-content: space-between"]:not(.view-header)
> div:last-child
.pf-btn {
flex: 1 1 50% !important;
padding: 0 5px !important;
font-size: 0.8rem !important;
justify-content: center;
}
/* 5. EN-TÊTES PRÉVISIONNEL (Répartition, Revenus) */
.prev-section-header {
flex-direction: column !important;
align-items: stretch !important;
gap: 12px !important;
}
.prev-section-header > div {
display: flex !important;
flex-direction: row !important; /* On permet l'alignement horizontal */
flex-wrap: wrap !important; /* On permet le passage à la ligne */
width: 100% !important;
gap: 10px !important;
}
.prev-section-header .nav-group {
display: flex !important;
width: 100% !important; /* La navigation prend toute la ligne du haut */
justify-content: space-between !important;
}
.prev-section-header .nav-group .btn-nav {
flex: 1;
text-align: center;
}
.prev-section-header .pf-btn {
flex: 1 1 calc(50% - 10px) !important; /* 50/50 pour les boutons du bas */
width: auto !important;
padding: 0 5px !important;
margin: 0 !important;
font-size: 0.85rem !important;
}
/* 6. TOUS LES TABLEAUX DEVIENNENT SCROLLABLES */
.prev-salary-table,
.prev-alloc-table,
.pf-table,
.savings-table,
.recap-wrapper {
display: block !important;
width: 100% !important;
overflow-x: auto !important;
-webkit-overflow-scrolling: touch;
white-space: nowrap;
border-radius: 8px !important;
margin-bottom: 15px;
}
/* 6b. COMPRESSION DU TABLEAU VIREMENTS POUR ÉVITER LE SCROLL */
.recap-card {
min-width: 100% !important; /* Retire le blocage à 600px */
width: 100% !important;
}
.recap-table th,
.recap-table td {
padding: 8px 4px !important; /* Réduit drastiquement l'espace vide horizontal */
font-size: 0.8rem !important; /* Réduit un poil la taille du texte */
}
.recap-header {
font-size: 0.9rem !important;
padding: 8px 10px !important;
}
/* On permet au texte "Grand Total" de s'ajuster si besoin */
.row-grand-total td {
padding: 10px 4px !important;
}
/* 7. BOUTONS D'ÉDITION/SUPPRESSION (FINI LE CHEVAUCHEMENT) */
.row-actions {
position: static !important;
display: inline-flex !important;
opacity: 1 !important;
position: absolute;
right: 0;
top: 0;
bottom: 0;
background: #ffffff;
box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1);
padding: 0 10px;
align-items: center;
gap: 10px;
z-index: 50;
border-left: 1px solid #e2e8f0;
box-shadow: none !important;
background: transparent !important;
border-left: none !important;
padding: 1px 0 !important;
transform: none !important;
justify-content: flex-start;
width: auto !important;
}
.btn-icon-action {
font-size: 1.2rem;
padding: 5px;
width: 34px;
height: 34px;
font-size: 1.1rem !important;
padding: 4px !important;
width: 20px !important;
height: 20px !important;
background: #f1f5f9 !important;
border-radius: 6px;
margin-right: 2px;
}
.col-sticky {
min-width: 180px !important;
/* 8. COLONNE STICKY */
.col-sticky,
.sticky-col {
min-width: 120px !important;
position: sticky !important;
left: 0;
z-index: 20 !important;
white-space: normal !important;
background: white !important;
}
.prev-section-header {
flex-direction: row;
align-items: center;
th.sticky-col,
th.col-sticky {
z-index: 30 !important;
background: #f8fafc !important;
}
/* 9. TOOLBAR SUIVI ET MODALES */
.action-toolbar {
flex-wrap: wrap !important;
width: 100% !important;
}
.suivi-nav-group {
width: 100%;
justify-content: space-between;
}
.suivi-btn-nav {
flex: 1;
text-align: center;
}
.pf-modal-content {
padding: 20px 15px !important;
width: 95% !important;
}
.modal-footer {
flex-wrap: wrap !important;
}
.modal-footer .pf-btn {
width: 100% !important;
margin-left: 0 !important;
margin-bottom: 10px !important;
}
}
+3 -3
View File
@@ -341,8 +341,8 @@ $monthName = $monthNames[(int)$viewM] . ' ' . $viewY;
<h2 style="margin:0; font-size:1.3rem; color:#0f172a; text-transform:capitalize;"><?= tr('bud_budget_of') ?> <?= $monthName ?></h2>
</div>
<div style="display:flex; gap:10px;">
<?php if (!$isClosed): ?>
<div class="action-toolbar" style="display:flex; gap:10px; flex-wrap:wrap; align-items:center;">
<?php if (!$isClosed): ?>
<button type="button" class="pf-btn btn-secondary" onclick="openSuiviModal('importCsvModal')" style="padding:6px 12px; height:auto; width:auto; font-size:0.85rem;">
📂 <?= tr('bud_import_csv') ?? 'Importer CSV' ?>
</button>
@@ -460,7 +460,7 @@ $monthName = $monthNames[(int)$viewM] . ' ' . $viewY;
<div style="position: absolute; left: <?= $posTheorique ?>%; top: 54px; transform: translateX(-50%); font-size: 0.85rem; font-weight: bold; color: <?= $solde_theorique >= 0 ? '#8b5cf6' : '#ef4444' ?>; white-space: nowrap;"><?= tr('bud_bar_theoretical') ?? 'Théorique' ?></div>
<?php
$overlapMax = abs($posMax - $posActuel) < 25;
$overlapMax = abs($posMax - $posActuel) < 35;
$topMaxText = $overlapMax ? '-60px' : '-35px';
$heightMaxLine = $overlapMax ? '65px' : '40px';
$topMaxLine = $overlapMax ? '-40px' : '-15px';