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/history.php
<?php
define('DS_APP', true);
require_once dirname(__DIR__) . '/includes/init.php';

$user = auth_require();

// ── Paramètres ────────────────────────────────────────────────────────────────
$year  = (int)($_GET['year']  ?? date('Y'));
$month = (int)($_GET['month'] ?? date('n'));
if ($month < 1) { $month = 12; $year--; }
if ($month > 12){ $month = 1;  $year++; }

$monthStart = sprintf('%04d-%02d-01', $year, $month);
$monthEnd   = date('Y-m-t', strtotime($monthStart));
$today      = date('Y-m-d');

$jours  = ['Lun','Mar','Mer','Jeu','Ven','Sam','Dim'];
$moisFR = ['','Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'];

// ── Données du mois ───────────────────────────────────────────────────────────
$monthEntries = db_fetch_all(
    "SELECT je.*, COUNT(ei.id) as item_count
     FROM journal_entries je
     LEFT JOIN entry_items ei ON je.id = ei.entry_id
     WHERE je.user_id = ? AND je.entry_date BETWEEN ? AND ?
     GROUP BY je.id
     ORDER BY je.entry_date DESC",
    [$user['id'], $monthStart, $monthEnd]
);

// Index par date pour le calendrier
$entriesByDate = [];
foreach ($monthEntries as $e) {
    $entriesByDate[$e['entry_date']] = $e;
}

// Stats du mois
$avgScore    = $monthEntries ? round(array_sum(array_column($monthEntries, 'skin_score')) / count($monthEntries), 1) : null;
$crisisCount = count(array_filter($monthEntries, fn($e) => $e['is_crisis']));
$entryCount  = count($monthEntries);
$daysInMonth = (int)date('t', strtotime($monthStart));
$fillRate    = round(($entryCount / $daysInMonth) * 100);

// Entrée sélectionnée (pour le détail)
$selectedDate  = $_GET['date'] ?? null;
$selectedEntry = null;
$selectedItems = [];
if ($selectedDate && preg_match('/^\d{4}-\d{2}-\d{2}$/', $selectedDate)) {
    $selectedEntry = db_fetch(
        "SELECT * FROM journal_entries WHERE user_id = ? AND entry_date = ?",
        [$user['id'], $selectedDate]
    );
    if ($selectedEntry) {
        $selectedItems = db_fetch_all(
            "SELECT ei.*, i.name, i.category, i.brand, i.warning_ingredients
             FROM entry_items ei
             JOIN items i ON ei.item_id = i.id
             WHERE ei.entry_id = ?
             ORDER BY i.category, i.name",
            [$selectedEntry['id']]
        );
    }
}

// Navigation prev/next mois
$prevMonth = $month - 1 < 1  ? 12 : $month - 1;
$prevYear  = $month - 1 < 1  ? $year - 1 : $year;
$nextMonth = $month + 1 > 12 ? 1  : $month + 1;
$nextYear  = $month + 1 > 12 ? $year + 1 : $year;
$canGoNext = "$year-" . sprintf('%02d', $month) . "-01" < date('Y-m-01');

// Helpers
function skinEmoji(int $s): string {
    return match(true) { $s>=5=>'😊', $s>=4=>'🙂', $s>=3=>'😐', $s>=2=>'😕', default=>'😞' };
}
function skinBg(int $s): string {
    return match(true) { $s>=4=>'rgba(0,232,122,0.12)', $s>=3=>'rgba(255,181,71,0.08)', default=>'rgba(255,107,138,0.1)' };
}
function skinBorder(int $s): string {
    return match(true) { $s>=4=>'rgba(0,232,122,0.3)', $s>=3=>'rgba(255,181,71,0.2)', default=>'rgba(255,107,138,0.3)' };
}
function skinColor(int $s): string {
    return match(true) { $s>=4=>'#00E87A', $s>=3=>'#FFB547', default=>'#FF6B8A' };
}

$catIcons = ['food'=>'🍽️','drink'=>'🥤','alcohol'=>'🍷','tobacco'=>'🚬','cosmetic'=>'🧴','haircare'=>'💇','medication'=>'💊','supplement'=>'🌿','other'=>'📦'];
$catLabels= ['food'=>'Alimentation','drink'=>'Boissons','alcohol'=>'Alcool','tobacco'=>'Tabac','cosmetic'=>'Cosmétiques','haircare'=>'Soins capillaires','medication'=>'Médicaments','supplement'=>'Compléments','other'=>'Autre'];

$pageTitle   = 'Historique';
$pageSubtitle= $moisFR[$month] . ' ' . $year;
$activePage  = 'history';
ob_start();
?>

<style>
.history-layout{display:grid;grid-template-columns:1fr 320px;gap:20px;align-items:start;}

/* Month nav */
.month-nav{display:flex;align-items:center;gap:12px;margin-bottom:20px;}
.mnav-btn{background:var(--surface);border:1px solid var(--border);color:var(--text);width:36px;height:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;text-decoration:none;font-size:1rem;font-weight:700;transition:all 0.2s;flex-shrink:0;}
.mnav-btn:hover{border-color:var(--cyan);color:var(--cyan);}
.mnav-btn.disabled{opacity:0.3;pointer-events:none;}
.mnav-title{flex:1;text-align:center;font-size:1.1rem;font-weight:800;letter-spacing:-0.02em;}

/* Stats bande */
.month-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:20px;}
.mstat{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:14px;text-align:center;}
.mstat-val{font-size:1.6rem;font-weight:900;letter-spacing:-0.03em;line-height:1;}
.mstat-label{font-size:0.65rem;color:var(--text-dim);text-transform:uppercase;letter-spacing:0.06em;margin-top:4px;}

/* Calendrier */
.calendar-card{background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:20px;margin-bottom:16px;}
.cal-header{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;margin-bottom:8px;}
.cal-day-name{text-align:center;font-size:0.68rem;font-weight:700;color:var(--text-dim);text-transform:uppercase;padding:4px 0;}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;}
.cal-cell{
  aspect-ratio:1;border-radius:8px;display:flex;flex-direction:column;
  align-items:center;justify-content:center;cursor:default;
  border:1px solid transparent;transition:all 0.15s;
  font-size:0.8rem;font-weight:600;position:relative;
}
.cal-cell.has-entry{cursor:pointer;}
.cal-cell.has-entry:hover{border-color:var(--border-bright);transform:scale(1.05);}
.cal-cell.selected{border-color:var(--cyan)!important;box-shadow:0 0 0 2px rgba(0,212,200,0.2);}
.cal-cell.today-cell{border-color:rgba(255,255,255,0.15);}
.cal-cell.empty{opacity:0;}
.cal-cell.future{opacity:0.25;cursor:not-allowed;}
.cal-score{font-size:0.65rem;color:rgba(255,255,255,0.5);margin-top:1px;}
.cal-crisis-dot{position:absolute;top:3px;right:3px;width:5px;height:5px;background:var(--rose);border-radius:50%;}
.cal-cell.no-entry{background:rgba(255,255,255,0.02);color:var(--text-dim);}

/* Liste entrées */
.entries-list{display:flex;flex-direction:column;gap:8px;}
.entry-item{
  background:var(--surface);border:1px solid var(--border);
  border-radius:12px;padding:14px 16px;
  display:flex;align-items:center;gap:14px;
  cursor:pointer;transition:all 0.2s;text-decoration:none;
}
.entry-item:hover{border-color:var(--border-bright);transform:translateX(2px);}
.entry-item.selected{border-color:rgba(0,212,200,0.3);background:var(--cyan-glow);}
.entry-item.is-crisis{border-color:rgba(255,107,138,0.25);}
.ei-date{font-size:0.78rem;color:var(--text-mid);width:80px;flex-shrink:0;line-height:1.3;}
.ei-score{width:36px;height:36px;border-radius:9px;display:flex;align-items:center;justify-content:center;font-size:1.1rem;flex-shrink:0;}
.ei-info{flex:1;min-width:0;}
.ei-score-text{font-size:0.82rem;font-weight:700;}
.ei-items{font-size:0.75rem;color:var(--text-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.ei-crisis{font-size:0.65rem;font-weight:700;color:var(--rose);background:rgba(255,107,138,0.1);padding:2px 7px;border-radius:100px;flex-shrink:0;}
.ei-arrow{color:var(--text-dim);font-size:0.85rem;flex-shrink:0;}

/* Détail entrée */
.detail-card{background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:20px;position:sticky;top:80px;}
.detail-header{display:flex;align-items:center;gap:12px;margin-bottom:16px;padding-bottom:14px;border-bottom:1px solid var(--border);}
.detail-score-big{font-size:2.4rem;font-weight:900;letter-spacing:-0.04em;line-height:1;}
.detail-date{font-size:0.82rem;color:var(--text-mid);margin-top:2px;}
.detail-section{margin-bottom:16px;}
.detail-section-title{font-size:0.68rem;font-weight:700;color:var(--text-dim);text-transform:uppercase;letter-spacing:0.08em;margin-bottom:8px;}
.detail-item-chip{display:inline-flex;align-items:center;gap:5px;background:var(--surface2);border:1px solid var(--border);border-radius:7px;padding:4px 9px;margin:2px;font-size:0.75rem;color:var(--text-mid);}
.detail-item-chip.warn{border-color:rgba(255,181,71,0.3);color:var(--amber);}
.detail-lifestyle{display:grid;grid-template-columns:1fr 1fr;gap:8px;}
.ls-item{background:var(--surface2);border-radius:8px;padding:8px 10px;}
.ls-item-label{font-size:0.65rem;color:var(--text-dim);text-transform:uppercase;letter-spacing:0.06em;}
.ls-item-val{font-size:0.88rem;font-weight:700;color:var(--text);margin-top:2px;}
.detail-zones{display:flex;flex-wrap:wrap;gap:4px;}
.zone-chip{font-size:0.72rem;padding:3px 8px;border-radius:6px;font-weight:500;}
.zone-chip.s1{background:rgba(255,181,71,0.1);color:var(--amber);}
.zone-chip.s2{background:rgba(255,107,138,0.1);color:var(--rose);}
.zone-chip.s3{background:rgba(255,107,138,0.2);color:var(--rose);font-weight:700;}
.detail-notes{font-size:0.82rem;color:var(--text-mid);line-height:1.6;font-style:italic;}
.detail-edit-btn{display:flex;align-items:center;justify-content:center;gap:6px;background:var(--cyan);color:var(--bg);padding:9px;border-radius:8px;text-decoration:none;font-size:0.82rem;font-weight:800;transition:all 0.2s;margin-top:14px;}
.detail-edit-btn:hover{background:#fff;}
.no-selection{text-align:center;padding:30px 20px;color:var(--text-dim);font-size:0.85rem;}

@media(max-width:900px){
  .history-layout{grid-template-columns:1fr;}
  .detail-card{position:static;}
  .month-stats{grid-template-columns:repeat(2,1fr);}
}
</style>

<!-- Navigation mois -->
<div class="month-nav">
  <a href="?year=<?= $prevYear ?>&month=<?= $prevMonth ?>" class="mnav-btn">←</a>
  <div class="mnav-title"><?= $moisFR[$month] ?> <?= $year ?></div>
  <a href="?year=<?= $nextYear ?>&month=<?= $nextMonth ?>"
     class="mnav-btn <?= !$canGoNext ? 'disabled' : '' ?>">→</a>
</div>

<!-- Stats du mois -->
<div class="month-stats">
  <div class="mstat">
    <div class="mstat-val" style="color:var(--cyan)"><?= $entryCount ?><span style="font-size:1rem;opacity:0.5">/<?= $daysInMonth ?></span></div>
    <div class="mstat-label">Entrées</div>
  </div>
  <div class="mstat">
    <div class="mstat-val" style="color:<?= $avgScore >= 4 ? 'var(--emerald)' : ($avgScore >= 3 ? 'var(--amber)' : 'var(--rose)') ?>"><?= $avgScore ?? '—' ?></div>
    <div class="mstat-label">Score moyen</div>
  </div>
  <div class="mstat">
    <div class="mstat-val" style="color:var(--rose)"><?= $crisisCount ?></div>
    <div class="mstat-label">Crises</div>
  </div>
  <div class="mstat">
    <div class="mstat-val" style="color:var(--amber)"><?= $fillRate ?>%</div>
    <div class="mstat-label">Taux de remplissage</div>
  </div>
</div>

<div class="history-layout">
<!-- ── Colonne principale ── -->
<div>

  <!-- Calendrier -->
  <div class="calendar-card">
    <div class="cal-header">
      <?php foreach ($jours as $j): ?>
        <div class="cal-day-name"><?= $j ?></div>
      <?php endforeach; ?>
    </div>

    <div class="cal-grid">
      <?php
      $firstDow = (int)date('N', strtotime($monthStart)); // 1=Lun, 7=Dim
      // Cases vides avant le 1er
      for ($i = 1; $i < $firstDow; $i++):
      ?>
        <div class="cal-cell empty"></div>
      <?php endfor;

      for ($day = 1; $day <= $daysInMonth; $day++):
        $dateStr = sprintf('%04d-%02d-%02d', $year, $month, $day);
        $entry   = $entriesByDate[$dateStr] ?? null;
        $isToday = $dateStr === $today;
        $isFuture= $dateStr > $today;
        $isSelected = $dateStr === $selectedDate;

        $cls = '';
        $bg = $brd = $color = '';

        if ($isFuture) {
          $cls = 'future';
        } elseif ($entry) {
          $s    = (int)$entry['skin_score'];
          $bg   = skinBg($s);
          $brd  = skinBorder($s);
          $color= skinColor($s);
          $cls  = 'has-entry' . ($isSelected ? ' selected' : '') . ($isToday ? ' today-cell' : '');
        } else {
          $cls = 'no-entry' . ($isToday ? ' today-cell' : '');
        }
      ?>
        <div class="cal-cell <?= $cls ?>"
             style="background:<?= $bg ?>;border-color:<?= $brd ?: 'transparent' ?>;color:<?= $color ?: 'inherit' ?>;"
             <?= ($entry && !$isFuture) ? "onclick=\"selectDate('{$dateStr}')\"" : '' ?>>
          <?= $day ?>
          <?php if ($entry): ?>
            <div class="cal-score"><?= $entry['skin_score'] ?>/5</div>
            <?php if ($entry['is_crisis']): ?>
              <div class="cal-crisis-dot"></div>
            <?php endif; ?>
          <?php endif; ?>
        </div>
      <?php endfor; ?>
    </div>

    <div style="display:flex;gap:16px;margin-top:14px;padding-top:14px;border-top:1px solid var(--border);flex-wrap:wrap;">
      <div style="display:flex;align-items:center;gap:6px;font-size:0.72rem;color:var(--text-dim);">
        <div style="width:12px;height:12px;border-radius:3px;background:rgba(0,232,122,0.12);border:1px solid rgba(0,232,122,0.3);"></div> Bonne journée (4-5)
      </div>
      <div style="display:flex;align-items:center;gap:6px;font-size:0.72rem;color:var(--text-dim);">
        <div style="width:12px;height:12px;border-radius:3px;background:rgba(255,181,71,0.08);border:1px solid rgba(255,181,71,0.2);"></div> Journée moyenne (3)
      </div>
      <div style="display:flex;align-items:center;gap:6px;font-size:0.72rem;color:var(--text-dim);">
        <div style="width:12px;height:12px;border-radius:3px;background:rgba(255,107,138,0.1);border:1px solid rgba(255,107,138,0.3);"></div> Mauvaise journée (1-2)
      </div>
      <div style="display:flex;align-items:center;gap:6px;font-size:0.72rem;color:var(--text-dim);">
        <div style="width:5px;height:5px;border-radius:50%;background:var(--rose);"></div> Crise
      </div>
    </div>
  </div>

  <!-- Liste des entrées du mois -->
  <?php if (!empty($monthEntries)): ?>
  <div class="entries-list">
    <?php
    $jFR = ['','lundi','mardi','mercredi','jeudi','vendredi','samedi','dimanche'];
    $mFR = ['','jan','fév','mar','avr','mai','juin','juil','août','sep','oct','nov','déc'];
    foreach ($monthEntries as $e):
      $d   = new DateTime($e['entry_date']);
      $dow = (int)$d->format('N');
      $dm  = (int)$d->format('j');
      $mn  = (int)$d->format('n');
      $dateLabel = $jFR[$dow] . ' ' . $dm . ' ' . $mFR[$mn];
      $s   = (int)$e['skin_score'];
      $isSel = $e['entry_date'] === $selectedDate;
    ?>
    <a href="?year=<?= $year ?>&month=<?= $month ?>&date=<?= $e['entry_date'] ?>"
       class="entry-item <?= $e['is_crisis'] ? 'is-crisis' : '' ?> <?= $isSel ? 'selected' : '' ?>">
      <div class="ei-date"><?= $dateLabel ?></div>
      <div class="ei-score" style="background:<?= skinBg($s) ?>;border:1px solid <?= skinBorder($s) ?>">
        <?= skinEmoji($s) ?>
      </div>
      <div class="ei-info">
        <div class="ei-score-text" style="color:<?= skinColor($s) ?>">Score <?= $s ?>/5</div>
        <div class="ei-items"><?= $e['item_count'] ?> item<?= $e['item_count'] > 1 ? 's' : '' ?> enregistré<?= $e['item_count'] > 1 ? 's' : '' ?></div>
      </div>
      <?php if ($e['is_crisis']): ?>
        <div class="ei-crisis">⚠ Crise</div>
      <?php endif; ?>
      <div class="ei-arrow">→</div>
    </a>
    <?php endforeach; ?>
  </div>
  <?php else: ?>
    <div style="text-align:center;padding:40px;color:var(--text-dim);font-size:0.85rem;">
      Aucune entrée ce mois-ci.<br>
      <a href="<?= url('app/journal.php') ?>" style="color:var(--cyan);text-decoration:none;font-weight:600;">Commencer le journal →</a>
    </div>
  <?php endif; ?>

</div><!-- /colonne principale -->

<!-- ── Détail (sidebar) ── -->
<div>
  <div class="detail-card">
    <?php if ($selectedEntry):
      $s = (int)$selectedEntry['skin_score'];
      $d = new DateTime($selectedEntry['entry_date']);
      $dow = (int)$d->format('N');
      $dm  = (int)$d->format('j');
      $mn  = (int)$d->format('n');
      $moisLong = ['','janvier','février','mars','avril','mai','juin','juillet','août','septembre','octobre','novembre','décembre'];
      $jLong = ['','lundi','mardi','mercredi','jeudi','vendredi','samedi','dimanche'];
      $dateLabelFull = $jLong[$dow] . ' ' . $dm . ' ' . $moisLong[$mn];

      $zones = json_decode($selectedEntry['skin_zones'] ?? '{}', true) ?? [];
      $zoneNames = ['scalp'=>'Cuir chevelu','face'=>'Visage','eyebrows'=>'Sourcils','nose'=>'Nez','ears'=>'Oreilles','chest'=>'Poitrine'];
      $sevLabels = ['','Léger','Modéré','Sévère'];

      // Grouper items par catégorie
      $itemsByCat = [];
      foreach ($selectedItems as $item) $itemsByCat[$item['category']][] = $item;
    ?>
      <div class="detail-header">
        <div>
          <div class="detail-score-big" style="color:<?= skinColor($s) ?>"><?= skinEmoji($s) ?> <?= $s ?><span style="font-size:1rem;opacity:0.4">/5</span></div>
          <div class="detail-date"><?= $dateLabelFull ?></div>
          <?php if ($selectedEntry['is_crisis']): ?>
            <div style="font-size:0.72rem;color:var(--rose);font-weight:700;margin-top:4px;">
              ⚠ Crise <?= $selectedEntry['crisis_severity'] ? ['','légère','modérée','sévère'][$selectedEntry['crisis_severity']] : '' ?>
            </div>
          <?php endif; ?>
        </div>
      </div>

      <?php if (!empty($zones)): ?>
      <div class="detail-section">
        <div class="detail-section-title">Zones touchées</div>
        <div class="detail-zones">
          <?php foreach ($zones as $zone => $sev):
            if ($sev === 0) continue;
          ?>
            <span class="zone-chip s<?= $sev ?>"><?= $zoneNames[$zone] ?? $zone ?> — <?= $sevLabels[$sev] ?></span>
          <?php endforeach; ?>
        </div>
      </div>
      <?php endif; ?>

      <?php if (!empty($selectedItems)): ?>
      <div class="detail-section">
        <div class="detail-section-title">Aliments & produits (<?= count($selectedItems) ?>)</div>
        <?php foreach ($itemsByCat as $cat => $items): ?>
          <div style="margin-bottom:6px;">
            <div style="font-size:0.65rem;color:var(--text-dim);margin-bottom:3px;"><?= $catLabels[$cat] ?? $cat ?></div>
            <?php foreach ($items as $item):
              $hasWarn = !empty($item['warning_ingredients']);
            ?>
              <span class="detail-item-chip <?= $hasWarn ? 'warn' : '' ?>">
                <?= $catIcons[$cat] ?? '📦' ?>
                <?= e($item['name']) ?>
                <?php if ($hasWarn): ?> ⚠<?php endif; ?>
              </span>
            <?php endforeach; ?>
          </div>
        <?php endforeach; ?>
      </div>
      <?php endif; ?>

      <?php
      $hasLifestyle = $selectedEntry['sleep_hours'] || $selectedEntry['sleep_quality'] ||
                     $selectedEntry['stress_level'] || $selectedEntry['exercise_mins'] ||
                     $selectedEntry['water_liters'];
      ?>
      <?php if ($hasLifestyle): ?>
      <div class="detail-section">
        <div class="detail-section-title">Facteurs du jour</div>
        <div class="detail-lifestyle">
          <?php if ($selectedEntry['sleep_hours']): ?>
          <div class="ls-item">
            <div class="ls-item-label">😴 Sommeil</div>
            <div class="ls-item-val"><?= $selectedEntry['sleep_hours'] ?>h</div>
          </div>
          <?php endif; ?>
          <?php if ($selectedEntry['sleep_quality']): ?>
          <div class="ls-item">
            <div class="ls-item-label">⭐ Qualité sommeil</div>
            <div class="ls-item-val"><?= str_repeat('⭐', (int)$selectedEntry['sleep_quality']) ?></div>
          </div>
          <?php endif; ?>
          <?php if ($selectedEntry['stress_level']): ?>
          <div class="ls-item">
            <div class="ls-item-label">😰 Stress</div>
            <div class="ls-item-val"><?= str_repeat('🔥', (int)$selectedEntry['stress_level']) ?></div>
          </div>
          <?php endif; ?>
          <?php if ($selectedEntry['water_liters']): ?>
          <div class="ls-item">
            <div class="ls-item-label">💧 Eau</div>
            <div class="ls-item-val"><?= $selectedEntry['water_liters'] ?>L</div>
          </div>
          <?php endif; ?>
          <?php if ($selectedEntry['exercise_mins']): ?>
          <div class="ls-item">
            <div class="ls-item-label">🏃 Exercice</div>
            <div class="ls-item-val"><?= $selectedEntry['exercise_mins'] ?> min</div>
          </div>
          <?php endif; ?>
        </div>
      </div>
      <?php endif; ?>

      <?php if ($selectedEntry['notes']): ?>
      <div class="detail-section">
        <div class="detail-section-title">Notes</div>
        <div class="detail-notes">"<?= e($selectedEntry['notes']) ?>"</div>
      </div>
      <?php endif; ?>

      <a href="<?= url('app/journal.php?date=' . $selectedEntry['entry_date']) ?>" class="detail-edit-btn">
        ✏️ Modifier cette entrée
      </a>

    <?php else: ?>
      <div class="no-selection">
        <div style="font-size:2rem;margin-bottom:10px;">📅</div>
        Cliquez sur un jour du calendrier ou une entrée de la liste pour voir le détail.
      </div>
    <?php endif; ?>
  </div>
</div>

</div><!-- /layout -->

<script>
function selectDate(date) {
  const url = new URL(window.location);
  url.searchParams.set('date', date);
  window.location = url;
}
</script>

<?php
$content = ob_get_clean();
require DS_VIEWS . 'layouts/app.php';