feat: gestion des modules actifs par famille dans settings.php
Deploy to Pacha Family / deploy (push) Failing after 3s
Deploy to Pacha Family / deploy (push) Failing after 3s
- families.enabled_modules (JSON) en BDD + init schema - login.php charge les modules actifs en session - header.php affiche uniquement les modules actifs (nav desktop + mobile) - settings.php : section Modules avec toggles visuels (partagé par famille) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
4b2ab275bc
commit
3077db5b98
@@ -8,8 +8,9 @@ CREATE TABLE IF NOT EXISTS families (
|
|||||||
name VARCHAR(100) NOT NULL,
|
name VARCHAR(100) NOT NULL,
|
||||||
db_name VARCHAR(64) NOT NULL UNIQUE,
|
db_name VARCHAR(64) NOT NULL UNIQUE,
|
||||||
invite_code VARCHAR(32) NOT NULL UNIQUE,
|
invite_code VARCHAR(32) NOT NULL UNIQUE,
|
||||||
is_active TINYINT(1) DEFAULT 1,
|
is_active TINYINT(1) DEFAULT 1,
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
enabled_modules JSON DEFAULT NULL,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
|||||||
+8
-7
@@ -43,12 +43,13 @@ $currentLang = $_SESSION['app_lang'] ?? 'fr';
|
|||||||
<a href="/index.php" class="pf-logo">HouseHub</a>
|
<a href="/index.php" class="pf-logo">HouseHub</a>
|
||||||
|
|
||||||
<?php if (isset($_SESSION['user'])): ?>
|
<?php if (isset($_SESSION['user'])): ?>
|
||||||
|
<?php $mods = $_SESSION['enabled_modules'] ?? ['calendar','budget','holidays','gifts']; ?>
|
||||||
<nav class="pf-nav">
|
<nav class="pf-nav">
|
||||||
<a href="/index.php" class="pf-nav-link <?= $activePage === 'home' ? 'pf-nav-link--active' : '' ?>"><?= tr('menu_home') ?></a>
|
<a href="/index.php" class="pf-nav-link <?= $activePage === 'home' ? 'pf-nav-link--active' : '' ?>"><?= tr('menu_home') ?></a>
|
||||||
<a href="/family-calendar.php" class="pf-nav-link <?= $activePage === 'family-calendar' ? 'pf-nav-link--active' : '' ?>"><?= tr('menu_calendar') ?></a>
|
<?php if (in_array('calendar', $mods)): ?><a href="/family-calendar.php" class="pf-nav-link <?= $activePage === 'family-calendar' ? 'pf-nav-link--active' : '' ?>"><?= tr('menu_calendar') ?></a><?php endif; ?>
|
||||||
<a href="/budget.php" class="pf-nav-link <?= $activePage === 'budget' ? 'pf-nav-link--active' : '' ?>"><?= tr('menu_budget') ?></a>
|
<?php if (in_array('budget', $mods)): ?><a href="/budget.php" class="pf-nav-link <?= $activePage === 'budget' ? 'pf-nav-link--active' : '' ?>"><?= tr('menu_budget') ?></a><?php endif; ?>
|
||||||
<a href="/holidays.php" class="pf-nav-link <?= $activePage === 'holidays' ? 'pf-nav-link--active' : '' ?>"><?= tr('menu_holidays') ?></a>
|
<?php if (in_array('holidays', $mods)): ?><a href="/holidays.php" class="pf-nav-link <?= $activePage === 'holidays' ? 'pf-nav-link--active' : '' ?>"><?= tr('menu_holidays') ?></a><?php endif; ?>
|
||||||
<a href="/gift-list.php" class="pf-nav-link <?= $activePage === 'gift-list' ? 'pf-nav-link--active' : '' ?>"><?= tr('menu_gifts') ?></a>
|
<?php if (in_array('gifts', $mods)): ?><a href="/gift-list.php" class="pf-nav-link <?= $activePage === 'gift-list' ? 'pf-nav-link--active' : '' ?>"><?= tr('menu_gifts') ?></a><?php endif; ?>
|
||||||
</nav>
|
</nav>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
@@ -86,9 +87,9 @@ $currentLang = $_SESSION['app_lang'] ?? 'fr';
|
|||||||
<div class="pf-mobile-menu-body">
|
<div class="pf-mobile-menu-body">
|
||||||
<a href="/index.php" class="pf-mobile-nav-link">🏠 <?= tr('menu_home') ?></a>
|
<a href="/index.php" class="pf-mobile-nav-link">🏠 <?= tr('menu_home') ?></a>
|
||||||
<a href="/family-calendar.php" class="pf-mobile-nav-link">📅 <?= tr('menu_calendar') ?></a>
|
<a href="/family-calendar.php" class="pf-mobile-nav-link">📅 <?= tr('menu_calendar') ?></a>
|
||||||
<a href="/budget.php" class="pf-mobile-nav-link">💰 <?= tr('menu_budget') ?></a>
|
<?php if (in_array('budget', $mods)): ?><a href="/budget.php" class="pf-mobile-nav-link">💰 <?= tr('menu_budget') ?></a><?php endif; ?>
|
||||||
<a href="/holidays.php" class="pf-mobile-nav-link">🏖️ <?= tr('menu_holidays') ?></a>
|
<?php if (in_array('holidays', $mods)): ?><a href="/holidays.php" class="pf-mobile-nav-link">🏖️ <?= tr('menu_holidays') ?></a><?php endif; ?>
|
||||||
<a href="/gift-list.php" class="pf-mobile-nav-link">🎁 <?= tr('menu_gifts') ?></a>
|
<?php if (in_array('gifts', $mods)): ?><a href="/gift-list.php" class="pf-mobile-nav-link">🎁 <?= tr('menu_gifts') ?></a><?php endif; ?>
|
||||||
<a href="/settings.php" class="pf-mobile-nav-link">⚙️ Paramètres</a>
|
<a href="/settings.php" class="pf-mobile-nav-link">⚙️ Paramètres</a>
|
||||||
<?php if (!empty($_SESSION['user']['is_admin'])): ?>
|
<?php if (!empty($_SESSION['user']['is_admin'])): ?>
|
||||||
<a href="/admin/" class="pf-mobile-nav-link" style="color:#2563eb">🛡️ Admin</a>
|
<a href="/admin/" class="pf-mobile-nav-link" style="color:#2563eb">🛡️ Admin</a>
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$error = tr('error_missing_fields');
|
$error = tr('error_missing_fields');
|
||||||
} else {
|
} else {
|
||||||
$stmt = $meta_pdo->prepare("
|
$stmt = $meta_pdo->prepare("
|
||||||
SELECT u.id, u.username, u.password_hash, u.display_name, u.family_id, u.is_admin, u.is_active, u.lang, f.db_name, f.is_active as family_active
|
SELECT u.id, u.username, u.password_hash, u.display_name, u.family_id, u.is_admin, u.is_active, u.lang,
|
||||||
|
f.db_name, f.is_active as family_active, f.enabled_modules
|
||||||
FROM users u
|
FROM users u
|
||||||
LEFT JOIN families f ON f.id = u.family_id
|
LEFT JOIN families f ON f.id = u.family_id
|
||||||
WHERE u.username = ?
|
WHERE u.username = ?
|
||||||
@@ -42,8 +43,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
'family_id' => (int)$user['family_id'],
|
'family_id' => (int)$user['family_id'],
|
||||||
'is_admin' => (bool)$user['is_admin'],
|
'is_admin' => (bool)$user['is_admin'],
|
||||||
];
|
];
|
||||||
$_SESSION['family_db'] = $user['db_name'];
|
$_SESSION['family_db'] = $user['db_name'];
|
||||||
$_SESSION['app_lang'] = $user['lang'] ?? 'fr';
|
$_SESSION['app_lang'] = $user['lang'] ?? 'fr';
|
||||||
|
$_SESSION['enabled_modules'] = json_decode($user['enabled_modules'] ?? '["calendar","budget","holidays","gifts"]', true);
|
||||||
$redirectTo = $_GET['redirect'] ?? '/index.php';
|
$redirectTo = $_GET['redirect'] ?? '/index.php';
|
||||||
header('Location: ' . $redirectTo);
|
header('Location: ' . $redirectTo);
|
||||||
exit;
|
exit;
|
||||||
|
|||||||
@@ -14,6 +14,16 @@ $success = null;
|
|||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$action = $_POST['action'] ?? '';
|
$action = $_POST['action'] ?? '';
|
||||||
|
|
||||||
|
if ($action === 'set_modules' && $family_id) {
|
||||||
|
$all = ['calendar', 'budget', 'holidays', 'gifts'];
|
||||||
|
$enabled = array_values(array_filter($all, fn($m) => isset($_POST['mod_' . $m])));
|
||||||
|
if (empty($enabled)) $enabled = $all; // sécurité : garder au moins tous les modules
|
||||||
|
$meta_pdo->prepare("UPDATE families SET enabled_modules = ? WHERE id = ?")
|
||||||
|
->execute([json_encode($enabled), $family_id]);
|
||||||
|
$_SESSION['enabled_modules'] = $enabled;
|
||||||
|
$success = "Modules mis à jour.";
|
||||||
|
}
|
||||||
|
|
||||||
if ($action === 'set_lang') {
|
if ($action === 'set_lang') {
|
||||||
$lang = $_POST['lang'] ?? 'fr';
|
$lang = $_POST['lang'] ?? 'fr';
|
||||||
if (in_array($lang, ['fr', 'ca', 'en'])) {
|
if (in_array($lang, ['fr', 'ca', 'en'])) {
|
||||||
@@ -135,6 +145,38 @@ require __DIR__ . '/header.php';
|
|||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<!-- ── Modules ────────────────────────────────────────────────────────── -->
|
||||||
|
<?php if ($family_id): ?>
|
||||||
|
<section style="background:white;border:1px solid #e2e8f0;border-radius:12px;padding:24px;margin-bottom:24px">
|
||||||
|
<h2 style="font-size:1rem;font-weight:700;margin-bottom:6px">🧩 Modules actifs</h2>
|
||||||
|
<p style="color:#64748b;font-size:0.85rem;margin-bottom:20px">Choisissez les modules visibles dans la navigation (partagé avec tous les membres de l'espace).</p>
|
||||||
|
<?php
|
||||||
|
$enabledMods = $_SESSION['enabled_modules'] ?? ['calendar','budget','holidays','gifts'];
|
||||||
|
$allModules = [
|
||||||
|
'calendar' => ['icon' => '📅', 'label' => tr('menu_calendar')],
|
||||||
|
'budget' => ['icon' => '💰', 'label' => tr('menu_budget')],
|
||||||
|
'holidays' => ['icon' => '🏖️', 'label' => tr('menu_holidays')],
|
||||||
|
'gifts' => ['icon' => '🎁', 'label' => tr('menu_gifts')],
|
||||||
|
];
|
||||||
|
?>
|
||||||
|
<form method="post">
|
||||||
|
<input type="hidden" name="action" value="set_modules">
|
||||||
|
<div style="display:flex;flex-direction:column;gap:12px;margin-bottom:20px">
|
||||||
|
<?php foreach ($allModules as $key => $mod): $active = in_array($key, $enabledMods); ?>
|
||||||
|
<label style="display:flex;align-items:center;gap:14px;padding:14px 16px;border:2px solid <?= $active ? '#2563eb' : '#e2e8f0' ?>;border-radius:10px;cursor:pointer;background:<?= $active ? '#eff6ff' : '#f8fafc' ?>;transition:all .15s">
|
||||||
|
<input type="checkbox" name="mod_<?= $key ?>" <?= $active ? 'checked' : '' ?>
|
||||||
|
style="width:18px;height:18px;accent-color:#2563eb;cursor:pointer"
|
||||||
|
onchange="this.closest('label').style.borderColor=this.checked?'#2563eb':'#e2e8f0';this.closest('label').style.background=this.checked?'#eff6ff':'#f8fafc'">
|
||||||
|
<span style="font-size:1.3rem"><?= $mod['icon'] ?></span>
|
||||||
|
<span style="font-weight:600;font-size:0.95rem"><?= $mod['label'] ?></span>
|
||||||
|
</label>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="pf-btn">Enregistrer</button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<!-- ── Profil ──────────────────────────────────────────────────────────── -->
|
<!-- ── Profil ──────────────────────────────────────────────────────────── -->
|
||||||
<section style="background:white;border:1px solid #e2e8f0;border-radius:12px;padding:24px;margin-bottom:24px">
|
<section style="background:white;border:1px solid #e2e8f0;border-radius:12px;padding:24px;margin-bottom:24px">
|
||||||
<h2 style="font-size:1rem;font-weight:700;margin-bottom:20px">👤 Mon profil</h2>
|
<h2 style="font-size:1rem;font-weight:700;margin-bottom:20px">👤 Mon profil</h2>
|
||||||
|
|||||||
Reference in New Issue
Block a user