Initial dev export (exclude uploads/runtime)

This commit is contained in:
AudioCore Bot
2026-03-04 20:46:11 +00:00
commit b2afadd539
120 changed files with 20410 additions and 0 deletions

View File

@@ -0,0 +1,366 @@
<?php
$pageTitle = $title ?? 'Releases';
$releases = is_array($releases ?? null) ? $releases : [];
$releaseCount = (int)($total_releases ?? count($releases));
$artistFilter = trim((string)($artist_filter ?? ''));
$artistOptions = is_array($artist_options ?? null) ? $artist_options : [];
$search = trim((string)($search ?? ''));
$sort = trim((string)($sort ?? 'newest'));
$currentPage = max(1, (int)($current_page ?? 1));
$totalPages = max(1, (int)($total_pages ?? 1));
$buildReleaseUrl = static function (int $page) use ($search, $artistFilter, $sort): string {
$params = [];
if ($search !== '') {
$params['q'] = $search;
}
if ($artistFilter !== '') {
$params['artist'] = $artistFilter;
}
if ($sort !== 'newest') {
$params['sort'] = $sort;
}
if ($page > 1) {
$params['p'] = $page;
}
$qs = http_build_query($params);
return '/releases' . ($qs !== '' ? ('?' . $qs) : '');
};
ob_start();
?>
<div class="ac-releases-page">
<section class="card ac-releases-shell">
<div class="ac-releases-header">
<div class="badge">Releases</div>
<h1>Latest Drops</h1>
<p>Singles, EPs, and albums from the AudioCore catalog.</p>
</div>
<form method="get" action="/releases" class="ac-release-controls">
<div class="ac-search-wrap">
<span class="ac-search-icon"><i class="fa-solid fa-magnifying-glass"></i></span>
<input class="ac-search-input" type="text" name="q" value="<?= htmlspecialchars($search, ENT_QUOTES, 'UTF-8') ?>" placeholder="Search releases, artists, catalog number">
</div>
<select class="ac-control-input" name="artist">
<option value="">All artists</option>
<?php foreach ($artistOptions as $artist): ?>
<option value="<?= htmlspecialchars((string)$artist, ENT_QUOTES, 'UTF-8') ?>" <?= $artistFilter === (string)$artist ? 'selected' : '' ?>>
<?= htmlspecialchars((string)$artist, ENT_QUOTES, 'UTF-8') ?>
</option>
<?php endforeach; ?>
</select>
<select class="ac-control-input" name="sort">
<option value="newest" <?= $sort === 'newest' ? 'selected' : '' ?>>Newest first</option>
<option value="oldest" <?= $sort === 'oldest' ? 'selected' : '' ?>>Oldest first</option>
<option value="title_asc" <?= $sort === 'title_asc' ? 'selected' : '' ?>>Title A-Z</option>
<option value="title_desc" <?= $sort === 'title_desc' ? 'selected' : '' ?>>Title Z-A</option>
</select>
<button type="submit" class="ac-btn ac-btn-primary">Apply</button>
<a href="/releases" class="ac-btn ac-btn-ghost">Reset</a>
</form>
<?php if ($artistFilter !== '' || $search !== '' || $sort !== 'newest'): ?>
<div class="ac-active-filters">
<?php if ($artistFilter !== ''): ?><div class="ac-chip">Artist: <?= htmlspecialchars($artistFilter, ENT_QUOTES, 'UTF-8') ?></div><?php endif; ?>
<?php if ($search !== ''): ?><div class="ac-chip">Search: <?= htmlspecialchars($search, ENT_QUOTES, 'UTF-8') ?></div><?php endif; ?>
<?php if ($sort !== 'newest'): ?><div class="ac-chip">Sort: <?= htmlspecialchars(str_replace('_', ' ', $sort), ENT_QUOTES, 'UTF-8') ?></div><?php endif; ?>
</div>
<?php endif; ?>
<?php if (!$releases): ?>
<div class="ac-empty">No releases published yet.</div>
<?php else: ?>
<div class="ac-release-grid">
<?php foreach ($releases as $release): ?>
<a class="ac-release-card" href="/release?slug=<?= htmlspecialchars((string)$release['slug'], ENT_QUOTES, 'UTF-8') ?>">
<div class="ac-release-cover">
<?php if (!empty($release['cover_url'])): ?>
<img src="<?= htmlspecialchars((string)$release['cover_url'], ENT_QUOTES, 'UTF-8') ?>" alt="">
<?php else: ?>
<div class="ac-release-placeholder">AC</div>
<?php endif; ?>
<?php if (!empty($release['release_date'])): ?>
<span class="ac-release-date"><?= htmlspecialchars((string)$release['release_date'], ENT_QUOTES, 'UTF-8') ?></span>
<?php endif; ?>
</div>
<div class="ac-release-meta">
<div class="ac-release-title"><?= htmlspecialchars((string)$release['title'], ENT_QUOTES, 'UTF-8') ?></div>
<?php if (!empty($release['artist_name'])): ?>
<div class="ac-release-artist"><?= htmlspecialchars((string)$release['artist_name'], ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
</div>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($totalPages > 1): ?>
<nav class="ac-release-pagination">
<?php $prevPage = max(1, $currentPage - 1); ?>
<?php $nextPage = min($totalPages, $currentPage + 1); ?>
<a class="ac-btn ac-btn-ghost<?= $currentPage <= 1 ? ' is-disabled' : '' ?>" href="<?= $currentPage <= 1 ? '#' : htmlspecialchars($buildReleaseUrl($prevPage), ENT_QUOTES, 'UTF-8') ?>">Prev</a>
<div class="ac-pagination-meta">Page <?= $currentPage ?> of <?= $totalPages ?> · <?= $releaseCount ?> total</div>
<a class="ac-btn ac-btn-ghost<?= $currentPage >= $totalPages ? ' is-disabled' : '' ?>" href="<?= $currentPage >= $totalPages ? '#' : htmlspecialchars($buildReleaseUrl($nextPage), ENT_QUOTES, 'UTF-8') ?>">Next</a>
</nav>
<?php endif; ?>
</section>
</div>
<style>
.ac-releases-page .ac-releases-shell {
margin-top: 14px;
display: grid;
gap: 14px;
}
.ac-releases-page .ac-releases-header {
border-bottom: 1px solid rgba(255,255,255,0.06);
padding-bottom: 10px;
}
.ac-releases-page .ac-releases-header h1 {
margin: 8px 0 0;
font-size: 52px;
line-height: 1.05;
letter-spacing: -0.02em;
}
.ac-releases-page .ac-releases-header p {
margin: 8px 0 0;
color: var(--muted);
font-size: 14px;
}
.ac-releases-page .ac-release-controls {
display: grid;
grid-template-columns: minmax(260px, 1fr) 180px 180px auto auto;
gap: 10px;
align-items: center;
padding: 8px;
border: 1px solid rgba(255,255,255,0.07);
border-radius: 14px;
background: rgba(8, 12, 19, 0.16);
}
.ac-releases-page .ac-search-wrap {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
border: 1px solid rgba(255,255,255,0.07);
border-radius: 10px;
background: rgba(7,10,16,0.10);
height: 36px;
padding: 0 10px;
}
.ac-releases-page .ac-search-icon {
color: rgba(255,255,255,0.72);
font-size: 12px;
width: 16px;
display: inline-flex;
justify-content: center;
}
.ac-releases-page .ac-search-input,
.ac-releases-page .ac-control-input {
width: 100%;
height: 36px;
border-radius: 10px;
border: 1px solid rgba(255,255,255,0.07);
background: rgba(7,10,16,0.10);
color: rgba(233,237,247,0.94);
padding: 0 10px;
font-size: 13px;
outline: none;
}
.ac-releases-page .ac-search-input {
border: 0;
background: transparent;
padding: 0;
min-width: 0;
}
.ac-releases-page .ac-search-input::placeholder {
color: rgba(220,228,245,.45);
}
.ac-releases-page .ac-search-input:focus,
.ac-releases-page .ac-control-input:focus {
box-shadow: 0 0 0 2px rgba(34,242,165,.12);
border-color: rgba(34,242,165,.38);
}
.ac-releases-page .ac-btn {
display: inline-flex;
align-items: center;
justify-content: center;
height: 36px;
padding: 0 14px;
border-radius: 10px;
border: 1px solid rgba(255,255,255,.10);
text-decoration: none;
font-size: 10px;
text-transform: uppercase;
letter-spacing: .12em;
font-weight: 700;
cursor: pointer;
transition: all .2s ease;
}
.ac-releases-page .ac-btn-primary {
background: rgba(34,242,165,.14);
color: #87f2cb;
border-color: rgba(34,242,165,.34);
}
.ac-releases-page .ac-btn-primary:hover {
background: rgba(34,242,165,.20);
}
.ac-releases-page .ac-btn-ghost {
color: #a1acc4;
background: transparent;
border-color: rgba(255,255,255,.10);
}
.ac-releases-page .ac-btn-ghost:hover {
color: #e5ebf7;
border-color: rgba(255,255,255,.18);
}
.ac-releases-page .ac-btn.is-disabled {
opacity: .45;
pointer-events: none;
}
.ac-releases-page .ac-active-filters {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.ac-releases-page .ac-chip {
border-radius: 999px;
padding: 6px 10px;
border: 1px solid rgba(255,255,255,.12);
font-size: 10px;
letter-spacing: .12em;
text-transform: uppercase;
color: var(--muted);
font-family: 'IBM Plex Mono', monospace;
}
.ac-releases-page .ac-release-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 240px));
justify-content: start;
gap: 16px;
}
.ac-releases-page .ac-release-card {
display: grid;
gap: 10px;
color: inherit;
text-decoration: none;
padding: 10px;
border-radius: 18px;
border: 1px solid rgba(255,255,255,.08);
background: rgba(0,0,0,.14);
transition: border-color .2s ease, transform .2s ease;
}
.ac-releases-page .ac-release-card:hover {
border-color: rgba(255,255,255,.18);
transform: translateY(-2px);
}
.ac-releases-page .ac-release-cover {
width: 100%;
aspect-ratio: 1 / 1;
border-radius: 16px;
overflow: hidden;
position: relative;
background: rgba(255,255,255,.03);
}
.ac-releases-page .ac-release-cover img {
width: 100%;
height: 100%;
object-fit: cover;
}
.ac-releases-page .ac-release-date {
position: absolute;
left: 10px;
bottom: 10px;
border-radius: 999px;
padding: 6px 10px;
font-size: 11px;
color: #fff;
background: rgba(0,0,0,.56);
border: 1px solid rgba(255,255,255,.18);
}
.ac-releases-page .ac-release-placeholder {
width: 100%;
height: 100%;
display: grid;
place-items: center;
color: var(--muted);
letter-spacing: .16em;
}
.ac-releases-page .ac-release-meta {
display: grid;
gap: 6px;
}
.ac-releases-page .ac-release-title {
font-weight: 600;
font-size: 18px;
line-height: 1.2;
}
.ac-releases-page .ac-release-artist {
font-size: 13px;
color: var(--muted);
}
.ac-releases-page .ac-empty {
padding: 16px;
border: 1px solid rgba(255,255,255,.08);
border-radius: 12px;
color: var(--muted);
}
.ac-releases-page .ac-release-pagination {
margin-top: 2px;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
flex-wrap: wrap;
}
.ac-releases-page .ac-pagination-meta {
font-size: 12px;
color: var(--muted);
}
@media (max-width: 1180px) {
.ac-releases-page .ac-release-controls {
grid-template-columns: 1fr 160px 160px auto auto;
}
.ac-releases-page .ac-release-grid {
grid-template-columns: repeat(auto-fill, minmax(210px, 230px));
}
}
@media (max-width: 900px) {
.ac-releases-page .ac-release-controls {
grid-template-columns: 1fr 1fr 1fr;
}
.ac-releases-page .ac-release-controls .ac-search-wrap {
grid-column: 1 / -1;
}
}
@media (max-width: 760px) {
.ac-releases-page .ac-releases-header h1 {
font-size: 40px;
}
.ac-releases-page .ac-release-controls {
grid-template-columns: 1fr;
}
.ac-releases-page .ac-release-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
justify-content: stretch;
}
}
@media (max-width: 520px) {
.ac-releases-page .ac-release-grid {
grid-template-columns: 1fr;
}
}
</style>
<?php
$content = ob_get_clean();
require __DIR__ . '/../../../../views/site/layout.php';