453 lines
17 KiB
HTML
453 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="{{ language() }}">
|
|
|
|
<head>
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
<meta
|
|
name="viewport"
|
|
content="width=device-width, initial-scale=1.0"
|
|
>
|
|
|
|
<title>{{ concert.artist }} | MetalCircle</title>
|
|
<link rel="icon" type="image/png" href="/static/images/metalcircle-circle.png">
|
|
|
|
<link
|
|
rel="stylesheet"
|
|
href="/static/css/style.css"
|
|
>
|
|
|
|
<style>
|
|
.detail-topbar { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }
|
|
.event-type-badge { display: inline-block; margin-bottom: 8px; padding: 4px 9px; border: 1px solid #4b5563; border-radius: 999px; color: #c4b5fd; font-size: .8rem; font-weight: 700; text-transform: uppercase; }
|
|
.parent-event-link { color: #c4b5fd; }
|
|
.flyer-source { display: block; width: 100%; flex: 0 0 100%; margin: 10px 0 0; color: #a8a29e; font-size: .85rem; text-align: center; }
|
|
.flyer-source a { color: #f87171; text-decoration: underline; }
|
|
.flyer-disclaimer { display: block; margin-top: 4px; font-size: .75rem; }
|
|
.follow-actions { display:flex; flex-wrap:wrap; justify-content:center; gap:8px; margin:0 0 20px; }
|
|
.follow-actions form { margin:0; }
|
|
.follow-button { padding:8px 11px; color:#fca5a5; background:#171212; border:1px solid var(--border); border-radius:9px; cursor:pointer; }
|
|
.follow-button.is-following { color:#fff; border-color:#dc2626; background:#7f1d1d; }
|
|
.diary-section { margin-top:26px; padding-top:22px; border-top:1px solid var(--border); }
|
|
.diary-form { max-width:none; }
|
|
.diary-form select, .diary-form input, .diary-form textarea { width:100%; }
|
|
.diary-form textarea { min-height:130px; resize:vertical; }
|
|
</style>
|
|
|
|
<link rel="stylesheet" href="/static/css/language.css">
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div class="container">
|
|
|
|
<div class="detail-topbar">
|
|
<a href="/" class="back-link">{{ _('← Zurück zum Kalender') }}</a>
|
|
{% include '_header_controls.html' %}
|
|
</div>
|
|
|
|
<article class="concert-detail">
|
|
|
|
{% if concert.flyer_url or concert.flyer_path %}
|
|
|
|
<div class="flyer-container">
|
|
|
|
<img
|
|
src="{{ concert.flyer_url or concert.flyer_path }}"
|
|
alt="Flyer {{ concert.artist }}"
|
|
class="concert-flyer"
|
|
referrerpolicy="no-referrer"
|
|
{% if concert.flyer_url and concert.flyer_path %}onerror="this.onerror=null;this.src='{{ concert.flyer_path }}'"{% endif %}
|
|
>
|
|
|
|
{% if concert.flyer_url %}
|
|
<p class="flyer-source"><a href="{{ concert.flyer_url }}" target="_blank" rel="noopener noreferrer nofollow external">{{ _('Quelle') }}</a><span class="flyer-disclaimer">{{ _('Extern eingebundener Flyer. Rechte liegen beim jeweiligen Veranstalter bzw. Rechteinhaber. Hinweise zur Entfernung bitte an die Administration.') }}</span></p>
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
|
<div class="concert-content">
|
|
|
|
<span class="event-type-badge">{{ concert.event_type_label | t }}</span>
|
|
{% if concert.visibility == 'friends' %}<span class="event-type-badge">{{ _('🔒 Nur Freunde') }}</span>{% elif concert.visibility == 'private' %}<span class="event-type-badge">{{ _('🔐 Privat / eingeladen') }}</span>{% endif %}
|
|
|
|
<h1>
|
|
{{ concert.artist }}
|
|
</h1>
|
|
|
|
<div class="follow-actions" id="following">
|
|
{% for band in concert_bands %}<form method="post" action="/concerts/{{ concert.id }}/follow-band">
|
|
<input type="hidden" name="band_key" value="{{ band.key }}">
|
|
<input type="hidden" name="action" value="{% if band.is_following %}unfollow{% else %}follow{% endif %}">
|
|
<button class="follow-button {% if band.is_following %}is-following{% endif %}" type="submit">{% if band.is_following %}★ {{ band.name }} {{ _('gefolgt') }}{% else %}☆ {{ band.name }} {{ _('folgen') }}{% endif %}</button>
|
|
</form>{% endfor %}
|
|
{% if concert.venue.id %}<form method="post" action="/concerts/{{ concert.id }}/follow-venue">
|
|
<input type="hidden" name="action" value="{% if follows_venue %}unfollow{% else %}follow{% endif %}">
|
|
<button class="follow-button {% if follows_venue %}is-following{% endif %}" type="submit">{% if follows_venue %}{{ _('★ Location gefolgt') }}{% else %}{{ _('☆ Location folgen') }}{% endif %}</button>
|
|
</form>{% endif %}
|
|
<a class="follow-button" href="/following">{{ _('Meine gefolgten Inhalte') }}</a>
|
|
</div>
|
|
|
|
|
|
<div class="concert-info">
|
|
|
|
<div class="info-item">
|
|
|
|
<span class="info-icon">
|
|
📅
|
|
</span>
|
|
|
|
<div>
|
|
|
|
<strong>
|
|
{{ concert.date }}
|
|
</strong>
|
|
|
|
<br>
|
|
|
|
{{ concert.time }} {{ _('Uhr') }}
|
|
|
|
{% if concert.event_type == 'festival' and concert.end_date %}
|
|
<br>
|
|
{{ _('bis') }} {{ concert.end_date }}{% if concert.end_time %}, {{ concert.end_time }} {{ _('Uhr') }}{% endif %}
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
<div class="info-item">
|
|
|
|
<span class="info-icon">
|
|
📍
|
|
</span>
|
|
|
|
<div>
|
|
|
|
<strong>
|
|
{{ concert.venue.name }}
|
|
</strong>
|
|
|
|
{% if concert.venue.street %}
|
|
|
|
<br>
|
|
|
|
{{ concert.venue.street }}
|
|
|
|
{% endif %}
|
|
|
|
|
|
{% if concert.venue.postal_code
|
|
or concert.venue.city
|
|
or (concert.venue.country
|
|
and concert.venue.country not in ('Deutschland', 'Germany')) %}
|
|
|
|
<br>
|
|
|
|
{{ concert.venue.postal_code }}
|
|
{{ concert.venue.city }}
|
|
{% if concert.venue.country
|
|
and concert.venue.country not in ('Deutschland', 'Germany') %}
|
|
{% if concert.venue.postal_code or concert.venue.city %} · {% endif %}
|
|
{{ concert.venue.country }}
|
|
{% endif %}
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
{% if concert.ticket_price %}
|
|
|
|
<div class="info-item">
|
|
|
|
<span class="info-icon">
|
|
🎟️
|
|
</span>
|
|
|
|
<div>
|
|
|
|
<strong>
|
|
Ticket
|
|
</strong>
|
|
|
|
<br>
|
|
|
|
{{ concert.ticket_price }} €
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
{% if concert.parent_event %}
|
|
<p>
|
|
{{ _('Gehört zu:') }}
|
|
<a class="parent-event-link" href="/concerts/{{ concert.parent_event.id }}">
|
|
{{ concert.parent_event.event_type_label | t }} · {{ concert.parent_event.title }}
|
|
</a>
|
|
</p>
|
|
{% endif %}
|
|
|
|
|
|
{% if concert.description %}
|
|
|
|
<section class="description">
|
|
|
|
<h2>
|
|
{{ _('Über die Veranstaltung') }}
|
|
</h2>
|
|
|
|
<p>
|
|
{{ concert.description }}
|
|
</p>
|
|
|
|
</section>
|
|
|
|
{% endif %}
|
|
|
|
|
|
<div class="event-actions">
|
|
{% if concert.ticket_url %}
|
|
|
|
<div class="ticket-button-container">
|
|
|
|
<a
|
|
href="{{ concert.ticket_url }}"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
class="ticket-button"
|
|
>
|
|
🎟️ Tickets
|
|
</a>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
<div class="calendar-export"><a href="/concerts/{{ concert.id }}.ics" class="concert-action">{{ _('📅 In Kalender speichern (.ics)') }}</a></div>
|
|
|
|
{% if can_edit %}
|
|
|
|
<div class="detail-actions" aria-label="{{ _('Veranstaltung verwalten') }}">
|
|
<a href="/concerts/{{ concert.id }}/edit" class="concert-action concert-action-edit">
|
|
{{ _('✏️ Veranstaltung bearbeiten') }}
|
|
</a>
|
|
|
|
{% if user.is_admin and can_delete %}
|
|
|
|
<form
|
|
method="post"
|
|
action="/concerts/{{ concert.id }}/delete"
|
|
onsubmit="return confirm({{ _('Diese Veranstaltung wirklich löschen?') | tojson | forceescape }});"
|
|
>
|
|
<button type="submit" class="concert-action concert-action-delete">
|
|
{{ _('🗑️ Veranstaltung löschen') }}
|
|
</button>
|
|
</form>
|
|
|
|
{% endif %}
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
|
</div>
|
|
|
|
{% if not concert.is_past %}
|
|
|
|
<section class="attendance-section" id="attendance">
|
|
|
|
<h2>
|
|
{{ _('🐧 Wer ist dabei?') }}
|
|
</h2>
|
|
|
|
<p>{{ _('Wähle, wie es bei dir aussieht. Deine Auswahl kann jederzeit geändert werden.') }}</p>
|
|
|
|
<div class="attendance-actions">
|
|
|
|
<form method="post" action="/concerts/{{ concert.id }}/attendance">
|
|
<input type="hidden" name="status" value="attending">
|
|
<button
|
|
type="submit"
|
|
class="attendance-option {% if current_attendance == 'attending' %}is-selected{% endif %}"
|
|
>
|
|
{{ _('✓ Zugesagt') }}
|
|
</button>
|
|
</form>
|
|
|
|
<form method="post" action="/concerts/{{ concert.id }}/attendance">
|
|
<input type="hidden" name="status" value="maybe">
|
|
<button
|
|
type="submit"
|
|
class="attendance-option {% if current_attendance == 'maybe' %}is-selected{% endif %}"
|
|
>
|
|
{{ _('? Vielleicht') }}
|
|
</button>
|
|
</form>
|
|
|
|
<form method="post" action="/concerts/{{ concert.id }}/attendance">
|
|
<input type="hidden" name="status" value="ticket_search">
|
|
<button
|
|
type="submit"
|
|
class="attendance-option {% if current_attendance == 'ticket_search' %}is-selected{% endif %}"
|
|
>
|
|
{{ _('🔎 Suche Ticket') }}
|
|
</button>
|
|
</form>
|
|
|
|
<form method="post" action="/concerts/{{ concert.id }}/attendance">
|
|
<input type="hidden" name="status" value="ticket_offer">
|
|
<button
|
|
type="submit"
|
|
class="attendance-option {% if current_attendance == 'ticket_offer' %}is-selected{% endif %}"
|
|
>
|
|
{{ _('🎟️ Biete Ticket') }}
|
|
</button>
|
|
</form>
|
|
|
|
</div>
|
|
|
|
<details class="attendance-list">
|
|
<summary>
|
|
{{ attending_count }} {{ _('Zusage') if attending_count == 1 else _('Zusagen') }}
|
|
· {{ maybe_count }} {{ _('Vielleicht') }} · {{ ticket_seeker_count }} {{ _('sucht Ticket') }} · {{ ticket_offer_count }} {{ _('bietet Ticket') }}
|
|
</summary>
|
|
|
|
<div class="attendance-groups">
|
|
|
|
<div>
|
|
<h3>{{ _('✓ Zugesagt') }}</h3>
|
|
|
|
{% if attending_users %}
|
|
<ul>
|
|
{% for attendee in attending_users %}
|
|
<li><a href="/users/{{ attendee.username }}">{{ attendee.name }}</a></li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% else %}
|
|
<p>{{ _('Noch niemand hat zugesagt.') }}</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<h3>{{ _('? Vielleicht') }}</h3>
|
|
|
|
{% if maybe_users %}
|
|
<ul>
|
|
{% for maybe_user in maybe_users %}
|
|
<li><a href="/users/{{ maybe_user.username }}">{{ maybe_user.name }}</a></li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% else %}
|
|
<p>{{ _('Noch keine Vielleicht-Angaben.') }}</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<h3>{{ _('🔎 Sucht ein Ticket') }}</h3>
|
|
|
|
{% if ticket_seekers %}
|
|
<ul>
|
|
{% for seeker in ticket_seekers %}
|
|
<li><a href="/users/{{ seeker.username }}">{{ seeker.name }}</a></li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% else %}
|
|
<p>{{ _('Aktuell sucht niemand ein Ticket.') }}</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<h3>{{ _('🎟️ Bietet ein Ticket') }}</h3>
|
|
|
|
{% if ticket_offers %}
|
|
<ul>
|
|
{% for offer in ticket_offers %}
|
|
<li><a href="/users/{{ offer.username }}">{{ offer.name }}</a></li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% else %}
|
|
<p>{{ _('Aktuell bietet niemand ein Ticket an.') }}</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
</div>
|
|
</details>
|
|
|
|
</section>
|
|
|
|
{% endif %}
|
|
|
|
{% if concert.is_past %}
|
|
<section class="diary-section" id="diary">
|
|
<h2>{{ _('📓 Mein Konzerttagebuch') }}</h2>
|
|
{% if can_write_diary %}
|
|
<p>{{ _('Der private Eintrag wurde automatisch angelegt.') }} <a class="button" href="/diary#concert-{{ concert.id }}">{{ _('Im Konzerttagebuch bearbeiten') }}</a></p>
|
|
{% else %}
|
|
<p>{{ _('Ein Tagebucheintrag wird automatisch angelegt, sobald du das vergangene Konzert als „Zugesagt“ markierst.') }}</p>
|
|
{% endif %}
|
|
</section>
|
|
{% endif %}
|
|
|
|
<section class="comments-section" id="comments">
|
|
|
|
<h2>{{ _('💬 Kommentare') }}</h2>
|
|
|
|
<form method="post" action="/concerts/{{ concert.id }}/comments" class="comment-form">
|
|
<label for="comment-body">{{ _('Mit anderen Konzertbesuchern austauschen') }}</label>
|
|
<textarea
|
|
id="comment-body"
|
|
name="body"
|
|
rows="4"
|
|
maxlength="2000"
|
|
required
|
|
placeholder="{{ _('Schreib einen Kommentar …') }}"
|
|
></textarea>
|
|
<button type="submit" class="attendance-option comment-submit">
|
|
{{ _('Kommentar senden') }}
|
|
</button>
|
|
</form>
|
|
|
|
{% if comments %}
|
|
|
|
<div class="comment-list">
|
|
{% for comment in comments %}
|
|
<article class="comment">
|
|
<div class="comment-meta">
|
|
<strong><a href="/users/{{ comment.username }}">{{ comment.author }}</a></strong>
|
|
<span>{{ comment.created_at }}</span>
|
|
</div>
|
|
<p>{{ comment.body }}</p>
|
|
</article>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
{% else %}
|
|
|
|
<p class="comments-empty">{{ _('Noch keine Kommentare. Mach den Anfang!') }}</p>
|
|
|
|
{% endif %}
|
|
|
|
</section>
|
|
|
|
</div>
|
|
|
|
</article>
|
|
|
|
</div>
|
|
|
|
</body>
|
|
|
|
</html>
|