File: /homepages/35/d993672390/htdocs/dermiteseborrheique/app/notifications.php
<?php
define('DS_APP', true);
require_once dirname(__DIR__) . '/includes/init.php';
$user = auth_require();
// Marquer tout comme lu si demandé
if ($_GET['action'] ?? '' === 'read_all') {
csrf_verify();
db_execute("UPDATE notifications SET is_read = 1 WHERE user_id = ?", [$user['id']]);
flash('success', 'Toutes les notifications marquées comme lues.');
redirect('app/notifications.php');
}
// Marquer une notif comme lue (AJAX)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && is_ajax()) {
csrf_verify();
$id = (int)($_POST['id'] ?? 0);
if ($id) {
db_execute(
"UPDATE notifications SET is_read = 1 WHERE id = ? AND user_id = ?",
[$id, $user['id']]
);
}
json_response(['success' => true]);
exit;
}
// Récupération
$page = max(1, (int)($_GET['page'] ?? 1));
$perPage = 20;
$offset = ($page - 1) * $perPage;
$total = db_count("SELECT COUNT(*) FROM notifications WHERE user_id = ?", [$user['id']]);
$unread = db_count("SELECT COUNT(*) FROM notifications WHERE user_id = ? AND is_read = 0", [$user['id']]);
$notifs = db_fetch_all(
"SELECT * FROM notifications WHERE user_id = ?
ORDER BY created_at DESC LIMIT ? OFFSET ?",
[$user['id'], $perPage, $offset]
);
$typeConfig = [
'new_suspect' => ['icon'=>'🔍','color'=>'var(--amber)','label'=>'Nouveau suspect'],
'confirmed_trigger' => ['icon'=>'✅','color'=>'var(--emerald)','label'=>'Déclencheur confirmé'],
'known_trigger' => ['icon'=>'⚠️','color'=>'var(--rose)','label'=>'Déclencheur connu'],
'streak' => ['icon'=>'🔥','color'=>'var(--amber)','label'=>'Streak'],
'badge' => ['icon'=>'🏆','color'=>'var(--cyan)','label'=>'Badge'],
'reminder' => ['icon'=>'📔','color'=>'var(--text-mid)','label'=>'Rappel'],
'default' => ['icon'=>'🔔','color'=>'var(--text-mid)','label'=>'Notification'],
];
$pageTitle = 'Notifications';
$activePage = '';
ob_start();
?>
<style>
.notif-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;flex-wrap:wrap;gap:10px;}
.notif-title{font-size:1.2rem;font-weight:800;letter-spacing:-0.02em;}
.notif-actions{display:flex;gap:10px;}
.notif-action-btn{background:var(--surface);border:1px solid var(--border);color:var(--text-mid);padding:7px 14px;border-radius:8px;text-decoration:none;font-size:0.78rem;font-weight:600;transition:all 0.2s;cursor:pointer;font-family:inherit;}
.notif-action-btn:hover{border-color:var(--cyan);color:var(--cyan);}
.notif-list{display:flex;flex-direction:column;gap:8px;}
.notif-item{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:16px;display:flex;align-items:flex-start;gap:12px;transition:all 0.2s;cursor:pointer;}
.notif-item:hover{border-color:var(--border-bright);transform:translateX(2px);}
.notif-item.unread{border-color:rgba(0,212,200,0.15);background:rgba(0,212,200,0.02);}
.notif-icon{width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:1.1rem;flex-shrink:0;}
.notif-content{flex:1;min-width:0;}
.notif-item-title{font-size:0.88rem;font-weight:700;color:var(--text);margin-bottom:3px;}
.notif-body{font-size:0.78rem;color:var(--text-mid);line-height:1.5;}
.notif-time{font-size:0.68rem;color:var(--text-dim);margin-top:5px;}
.notif-dot{width:7px;height:7px;border-radius:50%;background:var(--cyan);flex-shrink:0;margin-top:6px;}
.notif-empty{text-align:center;padding:60px 20px;}
.notif-empty-icon{font-size:3rem;margin-bottom:14px;}
.pagination{display:flex;gap:6px;justify-content:center;margin-top:24px;}
.page-btn{background:var(--surface);border:1px solid var(--border);color:var(--text-mid);padding:7px 14px;border-radius:8px;text-decoration:none;font-size:0.82rem;font-weight:600;transition:all 0.2s;}
.page-btn:hover,.page-btn.active{background:var(--cyan-dim);border-color:rgba(0,212,200,0.3);color:var(--cyan);}
</style>
<div class="notif-header">
<div>
<div class="notif-title">Notifications</div>
<?php if ($unread > 0): ?>
<div style="font-size:0.75rem;color:var(--cyan);margin-top:2px;"><?= $unread ?> non lue<?= $unread>1?'s':'' ?></div>
<?php endif; ?>
</div>
<?php if ($unread > 0): ?>
<div class="notif-actions">
<a href="?action=read_all&_csrf=<?= csrf_token() ?>" class="notif-action-btn">✓ Tout marquer comme lu</a>
</div>
<?php endif; ?>
</div>
<?php if (empty($notifs)): ?>
<div class="notif-empty">
<div class="notif-empty-icon">🔔</div>
<div style="font-size:1rem;font-weight:700;margin-bottom:8px;">Aucune notification</div>
<div style="font-size:0.82rem;color:var(--text-mid);">Les alertes de suspects, badges et rappels apparaîtront ici.</div>
</div>
<?php else: ?>
<div class="notif-list" id="notifList">
<?php foreach ($notifs as $n):
$cfg = $typeConfig[$n['type']] ?? $typeConfig['default'];
?>
<div class="notif-item <?= !$n['is_read'] ? 'unread' : '' ?>"
data-id="<?= $n['id'] ?>"
onclick="markRead(<?= $n['id'] ?>, this)">
<div class="notif-icon" style="background:<?= str_replace('var(--','rgba(',str_replace(')',',0.12)',$cfg['color'])) ?>">
<?= $cfg['icon'] ?>
</div>
<div class="notif-content">
<div class="notif-item-title"><?= e($n['title']) ?></div>
<?php if ($n['body']): ?>
<div class="notif-body"><?= e($n['body']) ?></div>
<?php endif; ?>
<div class="notif-time"><?= time_ago($n['created_at']) ?></div>
</div>
<?php if (!$n['is_read']): ?>
<div class="notif-dot"></div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php if ($total > $perPage): ?>
<div class="pagination">
<?php for ($p = 1; $p <= ceil($total / $perPage); $p++): ?>
<a href="?page=<?= $p ?>" class="page-btn <?= $p === $page ? 'active' : '' ?>"><?= $p ?></a>
<?php endfor; ?>
</div>
<?php endif; ?>
<?php endif; ?>
<script>
const csrf = document.querySelector('meta[name="csrf-token"]').content;
async function markRead(id, el) {
if (el.classList.contains('unread')) {
el.classList.remove('unread');
el.querySelector('.notif-dot')?.remove();
const fd = new FormData();
fd.append('id', id);
fd.append('_csrf', csrf);
await fetch('', {method:'POST',body:fd,headers:{'X-Requested-With':'XMLHttpRequest'}});
}
}
</script>
<?php
$content = ob_get_clean();
require DS_VIEWS . 'layouts/app.php';