Aggiunge gestione archivio replay nel pannello admin.

Gli admin possono vedere, modificare ed eliminare i replay di una società come la squadra proprietaria, riusando la stessa UI e logica dell'archivio pubblico.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-13 09:01:38 +02:00
parent da75582dae
commit 89854869c7
15 changed files with 455 additions and 219 deletions

View File

@@ -0,0 +1,153 @@
<%# locals: admin_mode: false %>
<% paths = @archive_paths %>
<% filter_params = @archive_filter_params %>
<div class="replay-archive<%= " replay-archive--admin" if local_assigns[:admin_mode] %>">
<p style="margin-bottom:16px"><%= link_to "← #{@club.name}", paths.back %></p>
<h1>Archivio Replay<% if local_assigns[:admin_mode] %> <span class="muted" style="font-size:0.85rem;font-weight:400">(admin)</span><% end %></h1>
<p class="muted">
Gestisci registrazioni, visibilità e download.
<strong>Privato</strong> = link non indicizzato, non compare in <code>/replay</code> pubblico.
Eliminando un replay vengono rimossi anche i file sul server e il video YouTube collegato.
</p>
<div class="kpi-grid replay-archive__kpis">
<div class="card replay-archive__kpi">
<div class="kpi-value"><%= @stats[:available_count] %></div>
<div class="kpi-sub">Replay disponibili</div>
</div>
<div class="card replay-archive__kpi">
<div class="kpi-value"><%= @stats[:expiring_soon_count] %></div>
<div class="kpi-sub">In scadenza (7 gg)</div>
</div>
<div class="card replay-archive__kpi">
<div class="kpi-value"><%= number_to_human_size(@stats[:total_bytes]) %></div>
<div class="kpi-sub">Spazio archivio</div>
</div>
<div class="card replay-archive__kpi">
<div class="kpi-value"><%= @stats[:total_views] %></div>
<div class="kpi-sub">Visualizzazioni totali</div>
</div>
</div>
<%= form_with url: paths.index, method: :get, local: true, class: "replay-filter-form" do %>
<label for="team_id" class="muted">Squadra</label>
<select name="team_id" id="team_id" class="input" onchange="this.form.submit()">
<option value="">Tutte</option>
<% @teams.each do |team| %>
<option value="<%= team.id %>"<%= " selected" if @filter_team_id.to_s == team.id.to_s %>><%= team.name %></option>
<% end %>
</select>
<label for="status" class="muted">Stato</label>
<select name="status" id="status" class="input" onchange="this.form.submit()">
<option value="">Tutti</option>
<option value="ready"<%= " selected" if @filter_status == "ready" %>>Disponibili</option>
<option value="processing"<%= " selected" if @filter_status == "processing" %>>In elaborazione</option>
<option value="expired"<%= " selected" if @filter_status == "expired" %>>Scaduti / errore</option>
</select>
<% end %>
<% if @recordings.any? %>
<div class="card replay-archive__card">
<table class="data replay-archive-table">
<thead>
<tr>
<th class="replay-archive-table__col-thumb" scope="col"><span class="visually-hidden">Anteprima</span></th>
<th scope="col">Partita</th>
<th scope="col">Squadra</th>
<th scope="col">Dettagli</th>
<th scope="col">Stato e visibilità</th>
<th class="replay-archive-table__col-actions" scope="col">Azioni</th>
</tr>
</thead>
<tbody>
<% @recordings.each do |rec| %>
<% ent = rec.team.entitlements %>
<% can_play = rec.ready? && rec.replay_url.present? %>
<tr>
<td class="replay-archive-table__col-thumb">
<% if can_play %>
<%= link_to rec.replay_url, class: "replay-archive__thumb", target: "_blank", rel: "noopener", title: "Guarda replay" do %>
<% if rec.thumbnail_url %>
<img src="<%= rec.thumbnail_url %>" alt="" class="replay-archive__thumb-img" width="80" height="45" loading="lazy">
<% else %>
<span class="replay-archive__thumb-placeholder" aria-hidden="true">▶</span>
<% end %>
<span class="replay-archive__play-btn" aria-hidden="true">▶</span>
<% end %>
<% else %>
<div class="replay-archive__thumb replay-archive__thumb--static" title="<%= rec.status == "processing" ? "Elaborazione in corso" : "Replay non disponibile" %>">
<% if rec.thumbnail_url %>
<img src="<%= rec.thumbnail_url %>" alt="" class="replay-archive__thumb-img" width="80" height="45" loading="lazy">
<% else %>
<span class="replay-archive__thumb-placeholder" aria-hidden="true"><%= rec.status == "processing" ? "…" : "—" %></span>
<% end %>
</div>
<% end %>
</td>
<td class="replay-archive-table__col-match">
<%= form_with url: paths.update.call(rec), method: :patch, local: true, class: "replay-archive__title-form" do %>
<% filter_params.each { |key, value| concat hidden_field_tag(key, value) } %>
<%= text_field_tag "recording[title]", rec.title_or_default, class: "replay-archive__title-input", onchange: "this.form.submit()" %>
<% end %>
<span class="replay-archive__meta-line"><%= rec.source_platform_label %></span>
</td>
<td class="replay-archive-table__col-team">
<span class="replay-archive__meta-line"><%= rec.team.name %></span>
</td>
<td class="replay-archive-table__col-details">
<span class="replay-archive__detail-line">
<%= l_local(rec.recorded_at_or_fallback, format: :short) %>
· <%= rec.duration_label %>
· <%= rec.view_count %> vis.
</span>
<span class="replay-archive__meta-line">
<% if rec.expires_at %>
Scade <%= l_local(rec.expires_at, format: :short) %>
<% if rec.days_until_expiry && rec.days_until_expiry.positive? %>
(<%= rec.days_until_expiry %> gg)
<% end %>
<% else %>
Nessuna scadenza
<% end %>
</span>
</td>
<td class="replay-archive-table__col-status">
<span class="replay-archive__status replay-archive__status--<%= rec.status %>"><%= rec.status_label %></span>
<%= form_with url: paths.update.call(rec), method: :patch, local: true, class: "replay-archive__privacy-form" do %>
<% filter_params.each { |key, value| concat hidden_field_tag(key, value) } %>
<%= select_tag "recording[privacy_status]",
options_for_select([["Pubblico", "public"], ["Privato", "unlisted"]], rec.privacy_status),
class: "replay-archive__privacy-select",
onchange: "this.form.submit()" %>
<% end %>
</td>
<td class="replay-archive-table__col-actions">
<div class="replay-archive__actions">
<% if ent.phone_download_enabled? && rec.ready? %>
<%= link_to "MP4", public_replay_download_path(rec.stream_session_id), class: "replay-archive__action replay-archive__action--secondary", title: "Scarica MP4" %>
<% end %>
<% if ent.premium_full? && ent.youtube_enabled? && rec.ready? && rec.youtube_video_id.blank? %>
<%= button_to "YT", paths.publish_youtube.call(rec), method: :post, class: "replay-archive__action replay-archive__action--secondary", title: "Pubblica su YouTube" %>
<% elsif rec.youtube_watch_url %>
<%= link_to "YT", rec.youtube_watch_url, class: "replay-archive__action replay-archive__action--secondary", target: "_blank", rel: "noopener", title: "Apri su YouTube" %>
<% end %>
<%= button_to paths.destroy.call(rec), method: :delete,
params: filter_params,
class: "replay-archive__action replay-archive__action--danger",
title: "Elimina replay",
form: { data: { turbo_confirm: "Eliminare definitivamente questo replay? Verranno rimossi i file sul server e il video YouTube collegato." }, class: "replay-archive__action-form" } do %>
<% end %>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<% else %>
<p class="muted">Nessuna registrazione per i filtri selezionati.</p>
<% end %>
</div>