HEX
Server: Apache
System: Linux info 3.0 #1337 SMP Tue Jan 01 00:00:00 CEST 2000 all GNU/Linux
User: u115237990 (7145895)
PHP: 8.3.32
Disabled: NONE
Upload Files
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';