84 lines
4.8 KiB
Twig
84 lines
4.8 KiB
Twig
{% set album_id = album.id|default('') %}
|
|
{% set is_external = album.source is defined and album.source == 'external' %}
|
|
{% set has_track_count = (album.total_tracks|default(0)) > 0 %}
|
|
{% set has_release_date = album.release_date is defined and album.release_date %}
|
|
{% set needs_hydration = is_external and (not has_track_count) %}
|
|
{% set show_url = path('album_show', {id: album_id}) %}
|
|
{% set review_href = needs_hydration ? '#' : show_url %}
|
|
|
|
<div class="col" data-card-col="1">
|
|
<div class="card h-100 js-album-card" data-album-id="{{ album_id }}" data-hydrate="{{ needs_hydration ? '1' : '0' }}">
|
|
{% set image = (album.images[0] ?? album.images[1] ?? null) %}
|
|
{% if image %}
|
|
{% set image_url = image.url|default('') %}
|
|
{% set preview_image_url = image_url %}
|
|
{% set highres_image_url = '' %}
|
|
{% if '/i/u/300x300/' in image_url %}
|
|
{% set preview_image_url = image_url|replace({'/i/u/300x300/': '/i/u/174s/'}) %}
|
|
{% set highres_image_url = image_url %}
|
|
{% elseif '/front-500' in image_url %}
|
|
{% set preview_image_url = image_url|replace({'/front-500': '/front-250'}) %}
|
|
{% elseif '/front-1200' in image_url %}
|
|
{% set preview_image_url = image_url|replace({'/front-1200': '/front-250'}) %}
|
|
{% elseif image_url matches '/\\/front$/' %}
|
|
{% set preview_image_url = image_url ~ '-250' %}
|
|
{% endif %}
|
|
<a href="{{ review_href }}" class="js-image-link {{ needs_hydration ? 'disabled pe-none' : '' }}" {% if needs_hydration %}aria-disabled="true"{% endif %}>
|
|
<img
|
|
class="card-img-top js-card-image"
|
|
src="{{ preview_image_url }}"
|
|
{% if highres_image_url %}data-highres="{{ highres_image_url }}"{% endif %}
|
|
alt="{{ album.name }} cover"
|
|
style="width: 100%; height: 220px; object-fit: cover; background: #f3edf0;"
|
|
loading="lazy"
|
|
decoding="async"
|
|
/>
|
|
</a>
|
|
{% elseif needs_hydration %}
|
|
<a href="#" class="js-image-link disabled pe-none" aria-disabled="true">
|
|
<div class="card-img-top js-image-shell d-flex align-items-center justify-content-center text-secondary" style="width: 100%; height: 220px; object-fit: cover; background: #f3edf0;">
|
|
Loading cover...
|
|
</div>
|
|
</a>
|
|
{% endif %}
|
|
<div class="card-body d-flex flex-column">
|
|
<h5 class="card-title"><a href="{{ review_href }}" class="text-decoration-none js-title-link {{ needs_hydration ? 'disabled pe-none' : '' }}" {% if needs_hydration %}aria-disabled="true"{% endif %}>{{ album.name }}</a></h5>
|
|
<p class="card-text text-secondary js-artist-line">{{ album.artists|map(a => a.name)|join(', ') }}</p>
|
|
<p class="card-text text-secondary js-release-line">
|
|
{% if needs_hydration %}
|
|
Loading album details...
|
|
{% else %}
|
|
{% set release_text = album.release_date is defined and album.release_date ? album.release_date : 'Unknown release date' %}
|
|
Released {{ release_text }} • {{ album.total_tracks }} tracks
|
|
{% endif %}
|
|
</p>
|
|
<p class="card-text text-secondary js-genre-line {% if album.genres is not defined or album.genres is empty %}d-none{% endif %}">
|
|
{% if album.genres is defined and album.genres is not empty %}
|
|
<small>Genre: {{ album.genres|join(', ') }}</small>
|
|
{% endif %}
|
|
</p>
|
|
{% set s = stats[album.id] ?? { 'avg': 0, 'count': 0 } %}
|
|
<p class="card-text js-score-line"><small class="text-secondary">User score: {{ s.avg }}/10 ({{ s.count }})</small></p>
|
|
<div class="mt-auto">
|
|
{% if album.external_urls.external is defined and album.external_urls.external and not needs_hydration %}
|
|
<a class="btn btn-outline-success btn-sm js-open-source" href="{{ album.external_urls.external }}" target="_blank" rel="noopener">Open Source</a>
|
|
{% endif %}
|
|
<a class="btn btn-success btn-sm js-reviews-link {{ needs_hydration ? 'disabled' : '' }}" href="{{ review_href }}" {% if needs_hydration %}aria-disabled="true"{% endif %}>Reviews</a>
|
|
{% if app.user and (album.source is not defined or album.source != 'user') %}
|
|
{% if savedIds is defined and (album.id in savedIds) %}
|
|
{# Saved indicator intentionally omitted to reduce noise #}
|
|
{% else %}
|
|
<form class="d-inline ms-2 js-save-form {{ needs_hydration ? 'd-none' : '' }}" method="post" action="{{ path('album_save', {id: album.id}) }}">
|
|
<input type="hidden" name="_token" value="{{ csrf_token('save-album-' ~ album.id) }}">
|
|
<button class="btn btn-outline-primary btn-sm" type="submit">Save</button>
|
|
</form>
|
|
{% endif %}
|
|
{% endif %}
|
|
{% if needs_hydration %}
|
|
<p class="small text-secondary mt-2 mb-0 js-hydration-status">Loading details...</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|