/
TorX
/
rasp
Обзор
Документация
Войти
/
TorX
/
rasp
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
includes/layout.php
245 строк
9 KB
tormovies
Add a posted flag for upcoming releases in admin and public lists.
07 авг 2026, 15:02
07 авг 2026, 15:02
3708742
Код
Авторство
О чём код?
<?php declare(strict_types=1); require_once __DIR__ . '/helpers.php'; require_once __DIR__ . '/auth.php'; function render_header(string $title, bool $isAdmin = false): void { $flash = flash_get(); ?> <!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title><?= e($title) ?></title> <link rel="stylesheet" href="/assets/style.css"> </head> <body> <?php if ($isAdmin): ?> <header class="topbar"> <div class="wrap topbar-inner"> <a class="brand" href="/admin/">Расписание · админ</a> <nav> <a href="/admin/">Обзор</a> <a href="/admin/releases.php">Релизы</a> <a href="/admin/artists.php">Артисты</a> <a href="/admin/export.php">Импорт / экспорт</a> </nav> <div class="topbar-right"> <a href="/">Публичный календарь</a> <a href="/admin/logout.php">Выйти</a> </div> </div> </header> <?php endif; ?> <main class="wrap"> <?php if ($flash): ?> <p class="flash flash-<?= e($flash['type']) ?>"><?= e($flash['message']) ?></p> <?php endif; ?> <?php } function render_footer(): void { ?> </main> </body> </html> <?php } function render_pitch_mark(bool $hasPitch): void { if ($hasPitch) { echo '<span class="pitch yes" title="Есть питчинг">✓</span>'; } else { echo '<span class="pitch no" title="Без питчинга"></span>'; } } function render_label_chip(?string $label): void { $label = trim((string) $label); if ($label === '') { return; } $c = label_color($label); printf( '<span class="chip" style="background:%s;color:%s;border-color:%s" title="%s">%s</span>', e($c['bg']), e($c['fg']), e($c['border']), e($label), e($label) ); } function render_label_initial(?string $label): void { $label = trim((string) $label); if ($label === '') { return; } $letter = mb_strtoupper(mb_substr($label, 0, 1)); $c = label_color($label); printf( '<span class="label-initial" style="background:%s;color:%s;border-color:%s" title="%s">%s</span>', e($c['bg']), e($c['fg']), e($c['border']), e($label), e($letter) ); } function render_calendar(int $year, int $month, array $releases, string $prevHref, string $nextHref, string $title, bool $admin = false): void { $byDate = []; foreach ($releases as $r) { $byDate[$r['release_date']][] = $r; } $first = new DateTime(sprintf('%04d-%02d-01', $year, $month)); $daysInMonth = (int) $first->format('t'); $startOffset = ((int) $first->format('N')) - 1; // Monday=1 $cells = []; for ($i = 0; $i < $startOffset; $i++) { $cells[] = null; } for ($d = 1; $d <= $daysInMonth; $d++) { $cells[] = sprintf('%04d-%02d-%02d', $year, $month, $d); } while (count($cells) % 7 !== 0) { $cells[] = null; } $weekdays = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс']; ?> <div class="calendar"> <div class="cal-nav"> <a class="btn btn-secondary" href="<?= e($prevHref) ?>">←</a> <h2><?= e($title) ?></h2> <a class="btn btn-secondary" href="<?= e($nextHref) ?>">→</a> </div> <div class="cal-grid"> <?php foreach ($weekdays as $w): ?> <div class="cal-head"><?= e($w) ?></div> <?php endforeach; ?> <?php foreach ($cells as $index => $dateKey): ?> <?php $isThursday = $index % 7 === 3; $dayReleases = $dateKey ? ($byDate[$dateKey] ?? []) : []; ?> <div class="cal-cell<?= $dateKey === null ? ' empty' : '' ?><?= $isThursday && $dateKey ? ' thursday' : '' ?>"> <?php if ($dateKey !== null): ?> <div class="cal-day"> <span><?= (int) substr($dateKey, 8, 2) ?></span> <?php if ($admin): ?> <a href="/admin/release-edit.php?date=<?= e($dateKey) ?>">+</a> <?php endif; ?> </div> <ul class="cal-items"> <?php foreach ($dayReleases as $r): ?> <?php $itemClass = 'cal-item' . (!empty($r['has_pitch']) ? ' has-pitch' : ''); ?> <li> <?php if ($admin): ?> <a class="<?= e($itemClass) ?>" href="/admin/release-edit.php?id=<?= (int) $r['id'] ?>"> <?php else: ?> <div class="<?= e($itemClass) ?>"> <?php endif; ?> <?php if (empty($r['has_pitch'])): ?> <?php render_pitch_mark(false); ?> <?php endif; ?> <span class="cal-item-text"><strong><?= e($r['artist_name']) ?></strong> — <?= e($r['title']) ?><?php if (!empty($r['has_pitch'])) { echo ' '; $label = trim((string) ($r['label'] ?? '')); if ($label !== '') { render_label_initial($label); } else { render_pitch_mark(true); } } ?></span> <?php if ($admin): ?></a><?php else: ?></div><?php endif; ?> </li> <?php endforeach; ?> </ul> <?php endif; ?> </div> <?php endforeach; ?> </div> <div class="legend"> <span><?php render_pitch_mark(true); ?> есть питчинг</span> <span><?php render_pitch_mark(false); ?> без питчинга</span> <span>Четверги подсвечены</span> </div> </div> <?php } function render_posted_mark(bool $isPosted, bool $editable = false, int $id = 0, string $returnTo = '/admin/'): void { $title = $isPosted ? 'Выложено' : 'Не выложено'; $class = 'posted-flag' . ($isPosted ? ' is-on' : ''); if ($editable) { $parts = parse_url($returnTo); $action = ($parts['path'] ?? '/admin/'); $query = []; if (!empty($parts['query'])) { parse_str($parts['query'], $query); } echo '<form method="post" action="' . e($action) . '" class="' . e($class) . '" title="' . e($title) . '">'; foreach ($query as $key => $value) { echo '<input type="hidden" name="' . e((string) $key) . '" value="' . e((string) $value) . '">'; } echo '<input type="hidden" name="action" value="toggle_posted">'; echo '<input type="hidden" name="id" value="' . (int) $id . '">'; echo '<input type="hidden" name="is_posted" value="' . ($isPosted ? '0' : '1') . '">'; echo '<button type="submit" class="posted-check" aria-label="' . e($title) . '">'; echo '<span class="posted-box">' . ($isPosted ? '✓' : '') . '</span>'; echo '<span class="posted-label">выложено</span>'; echo '</button></form>'; return; } echo '<span class="' . e($class) . '" title="' . e($title) . '">'; echo '<span class="posted-box">' . ($isPosted ? '✓' : '') . '</span>'; echo '<span class="posted-label">выложено</span>'; echo '</span>'; } function render_release_list( array $releases, bool $admin = false, string $empty = 'Нет релизов', bool $editablePosted = false, string $postedReturnTo = '/admin/' ): void { echo '<ul class="list">'; if (!$releases) { echo '<li class="list-item"><div class="list-main muted">' . e($empty) . '</div></li>'; } foreach ($releases as $r) { $posted = !empty($r['is_posted']); echo '<li class="list-item' . ($posted ? ' is-posted' : '') . '">'; render_posted_mark($posted, $editablePosted, (int) $r['id'], $postedReturnTo); if ($admin) { echo '<a class="list-main" href="/admin/release-edit.php?id=' . (int) $r['id'] . '">'; } else { echo '<div class="list-main">'; } render_pitch_mark((bool) $r['has_pitch']); echo '<div>'; echo '<div class="list-title">' . e(format_release_date($r['release_date'])) . ' — ' . e($r['artist_name']) . ' — ' . e($r['title']) . '</div>'; echo '<div class="list-meta">'; render_label_chip($r['label'] ?? ''); echo '<span>' . e($r['genre']) . ' · ' . e(release_type_label($r['type'])) . ' · текст ' . e($r['lyric_author']) . '</span>'; echo '</div></div>'; echo $admin ? '</a>' : '</div>'; echo '</li>'; } echo '</ul>'; }