Migliora UI archivio replay società con play e azioni separate.

Anteprima cliccabile con pulsante play, badge stato, select visibilità compatti e colonna azioni senza sovrapposizioni.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-09 09:14:38 +02:00
parent 9177e9e5a2
commit 214d276508
3 changed files with 382 additions and 77 deletions

View File

@@ -8,7 +8,7 @@
<%= render "shared/meta_tags" %> <%= render "shared/meta_tags" %>
<%= yield :head %> <%= yield :head %>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" integrity="sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A==" crossorigin="anonymous" referrerpolicy="no-referrer"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" integrity="sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A==" crossorigin="anonymous" referrerpolicy="no-referrer">
<link rel="stylesheet" href="/marketing.css?v=36"> <link rel="stylesheet" href="/marketing.css?v=37">
</head> </head>
<body<% if MatchLiveTv.google_analytics_configured? %> data-ga-id="<%= MatchLiveTv.google_analytics_measurement_id %>"<% end %>> <body<% if MatchLiveTv.google_analytics_configured? %> data-ga-id="<%= MatchLiveTv.google_analytics_measurement_id %>"<% end %>>
<%= render "shared/cookie_banner" %> <%= render "shared/cookie_banner" %>

View File

@@ -1,7 +1,7 @@
<% content_for :title, "Replay — #{@club.name}" %> <% content_for :title, "Replay — #{@club.name}" %>
<% content_for :robots, "noindex, nofollow" %> <% content_for :robots, "noindex, nofollow" %>
<div class="wrap club-dashboard" style="padding-top:20px"> <div class="wrap club-dashboard replay-archive" style="padding-top:20px">
<%= link_to "← #{@club.name}", public_club_path(@club), class: "back-link" %> <%= link_to "← #{@club.name}", public_club_path(@club), class: "back-link" %>
<h1>Archivio Replay</h1> <h1>Archivio Replay</h1>
@@ -48,84 +48,114 @@
<% end %> <% end %>
<% if @recordings.any? %> <% if @recordings.any? %>
<div class="card"> <div class="card replay-archive__card">
<table class="data"> <div class="replay-archive__table-wrap">
<table class="data replay-archive-table">
<thead> <thead>
<tr> <tr>
<th></th> <th class="replay-archive-table__col-thumb" scope="col"><span class="visually-hidden">Anteprima</span></th>
<th>Titolo</th> <th scope="col">Titolo</th>
<th>Piattaforma</th> <th scope="col">Piattaforma</th>
<th>Data</th> <th scope="col">Data</th>
<th>Durata</th> <th scope="col">Durata</th>
<th>Views</th> <th scope="col">Views</th>
<th>Scadenza</th> <th scope="col">Scadenza</th>
<th>Stato</th> <th scope="col">Stato</th>
<th>Visibilità</th> <th scope="col">Visibilità</th>
<th></th> <th class="replay-archive-table__col-actions" scope="col">Azioni</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<% @recordings.each do |rec| %> <% @recordings.each do |rec| %>
<% ent = rec.team.entitlements %>
<% can_play = rec.ready? && rec.replay_url.present? %>
<tr> <tr>
<td style="width:72px"> <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 %> <% if rec.thumbnail_url %>
<img src="<%= rec.thumbnail_url %>" alt="" width="64" height="36" style="object-fit:cover;border-radius:4px"> <img src="<%= rec.thumbnail_url %>" alt="" class="replay-archive__thumb-img" width="96" height="54" 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="96" height="54" loading="lazy">
<% else %>
<span class="replay-archive__thumb-placeholder" aria-hidden="true"><%= rec.status == "processing" ? "…" : "—" %></span>
<% end %>
</div>
<% end %> <% end %>
</td> </td>
<td> <td class="replay-archive-table__col-title">
<%= form_with url: public_club_recording_path(@club, rec), method: :patch, local: true do %> <%= form_with url: public_club_recording_path(@club, rec), method: :patch, local: true, class: "replay-archive__title-form" do %>
<%= hidden_field_tag :team_id, @filter_team_id if @filter_team_id.present? %> <%= hidden_field_tag :team_id, @filter_team_id if @filter_team_id.present? %>
<%= hidden_field_tag :status, @filter_status if @filter_status.present? %> <%= hidden_field_tag :status, @filter_status if @filter_status.present? %>
<%= text_field_tag "recording[title]", rec.title_or_default, class: "input", style: "min-width:12rem", onchange: "this.form.submit()" %> <%= text_field_tag "recording[title]", rec.title_or_default, class: "replay-archive__title-input", onchange: "this.form.submit()" %>
<% end %> <% end %>
</td> </td>
<td><%= rec.source_platform_label %></td> <td><%= rec.source_platform_label %></td>
<td><%= l_local(rec.recorded_at_or_fallback) %></td> <td class="replay-archive-table__nowrap"><%= l_local(rec.recorded_at_or_fallback) %></td>
<td><%= rec.duration_label %></td> <td><%= rec.duration_label %></td>
<td><%= rec.view_count %></td> <td><%= rec.view_count %></td>
<td> <td class="replay-archive-table__nowrap">
<% if rec.expires_at %> <% if rec.expires_at %>
<%= l_local(rec.expires_at) %> <%= l_local(rec.expires_at) %>
<% if rec.days_until_expiry && rec.days_until_expiry.positive? %> <% if rec.days_until_expiry && rec.days_until_expiry.positive? %>
<br><span class="muted" style="font-size:0.75rem">(<%= rec.days_until_expiry %> gg)</span> <span class="muted replay-archive-table__sub">(<%= rec.days_until_expiry %> gg)</span>
<% end %> <% end %>
<% else %> <% else %>
<% end %> <% end %>
</td> </td>
<td><%= rec.status_label %></td>
<td> <td>
<%= form_with url: public_club_recording_path(@club, rec), method: :patch, local: true do %> <span class="replay-archive__status replay-archive__status--<%= rec.status %>"><%= rec.status_label %></span>
</td>
<td class="replay-archive-table__col-privacy">
<%= form_with url: public_club_recording_path(@club, rec), method: :patch, local: true, class: "replay-archive__privacy-form" do %>
<%= hidden_field_tag :team_id, @filter_team_id if @filter_team_id.present? %> <%= hidden_field_tag :team_id, @filter_team_id if @filter_team_id.present? %>
<%= hidden_field_tag :status, @filter_status if @filter_status.present? %> <%= hidden_field_tag :status, @filter_status if @filter_status.present? %>
<%= select_tag "recording[privacy_status]", <%= select_tag "recording[privacy_status]",
options_for_select([["Pubblico", "public"], ["Privato (link)", "unlisted"]], rec.privacy_status), options_for_select([["Pubblico", "public"], ["Privato", "unlisted"]], rec.privacy_status),
class: "replay-archive__privacy-select",
onchange: "this.form.submit()" %> onchange: "this.form.submit()" %>
<% end %> <% end %>
</td> </td>
<td style="white-space:nowrap;font-size:0.8rem"> <td class="replay-archive-table__col-actions">
<% if rec.replay_url %> <div class="replay-archive__actions">
<%= link_to "Sito", rec.replay_url, target: "_blank", rel: "noopener" %> <% if can_play %>
<%= link_to rec.replay_url, class: "replay-archive__action replay-archive__action--play", target: "_blank", rel: "noopener", title: "Guarda replay" do %>
<span aria-hidden="true">▶</span>
<span class="replay-archive__action-label">Play</span>
<% end %> <% end %>
<% if rec.team.entitlements.phone_download_enabled? && rec.ready? %>
· <%= link_to "MP4", public_replay_download_path(rec.stream_session_id) %>
<% end %> <% end %>
<% ent = rec.team.entitlements %> <% 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? %> <% if ent.premium_full? && ent.youtube_enabled? && rec.ready? && rec.youtube_video_id.blank? %>
· <%= button_to "YouTube", public_club_recording_publish_youtube_path(@club, rec), method: :post, class: "btn-link", style: "display:inline;padding:0;border:0;background:none;color:inherit;cursor:pointer;text-decoration:underline" %> <%= button_to "YT", public_club_recording_publish_youtube_path(@club, rec), method: :post, class: "replay-archive__action replay-archive__action--secondary", title: "Pubblica su YouTube" %>
<% elsif rec.youtube_watch_url %> <% elsif rec.youtube_watch_url %>
· <%= link_to "YT", rec.youtube_watch_url, target: "_blank", rel: "noopener" %> <%= link_to "YT", rec.youtube_watch_url, class: "replay-archive__action replay-archive__action--secondary", target: "_blank", rel: "noopener", title: "Apri su YouTube" %>
<% end %> <% end %>
· <%= button_to "Elimina", public_club_recording_path(@club, rec), method: :delete, <%= button_to public_club_recording_path(@club, rec), method: :delete,
params: { team_id: @filter_team_id, status: @filter_status }.compact, params: { team_id: @filter_team_id, status: @filter_status }.compact,
class: "btn-link", style: "display:inline;padding:0;border:0;background:none;color:#e53935;cursor:pointer", class: "replay-archive__action replay-archive__action--danger",
form: { data: { turbo_confirm: "Eliminare definitivamente questo replay? Verranno rimossi i file sul server e il video YouTube collegato." } } %> 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 %>
<span aria-hidden="true">✕</span>
<span class="replay-archive__action-label">Elimina</span>
<% end %>
</div>
</td> </td>
</tr> </tr>
<% end %> <% end %>
</tbody> </tbody>
</table> </table>
</div> </div>
</div>
<% else %> <% else %>
<p class="muted">Nessuna registrazione ancora. I replay compaiono al termine delle dirette Premium.</p> <p class="muted">Nessuna registrazione ancora. I replay compaiono al termine delle dirette Premium.</p>
<% end %> <% end %>

View File

@@ -1354,3 +1354,278 @@ label { display: block; margin-bottom: 6px; font-size: 0.9rem; color: #c8c8d4; f
body.cookie-banner-visible { body.cookie-banner-visible {
padding-bottom: 120px; padding-bottom: 120px;
} }
/* —— Archivio replay società —— */
.replay-archive__card {
padding: 0;
overflow: hidden;
}
.replay-archive__table-wrap {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.replay-archive-table {
width: 100%;
min-width: 920px;
border-collapse: collapse;
}
.replay-archive-table th,
.replay-archive-table td {
padding: 12px 10px;
border-bottom: 1px solid #2a2a36;
vertical-align: middle;
}
.replay-archive-table th {
font-size: 0.78rem;
font-weight: 600;
color: #9a9aaa;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.replay-archive-table__col-thumb {
width: 108px;
}
.replay-archive-table__col-title {
min-width: 11rem;
}
.replay-archive-table__col-privacy {
width: 8.5rem;
}
.replay-archive-table__col-actions {
width: 1%;
white-space: nowrap;
}
.replay-archive-table__nowrap {
white-space: nowrap;
font-size: 0.9rem;
}
.replay-archive-table__sub {
display: block;
font-size: 0.75rem;
margin-top: 2px;
}
.replay-archive__thumb {
position: relative;
display: block;
width: 96px;
height: 54px;
border-radius: 8px;
overflow: hidden;
background: #0f0f14;
border: 1px solid #3a3a48;
text-decoration: none;
transition: border-color 0.15s, transform 0.15s;
}
a.replay-archive__thumb:hover {
border-color: #e53935;
transform: scale(1.03);
}
.replay-archive__thumb--static {
cursor: default;
opacity: 0.72;
}
.replay-archive__thumb-img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
.replay-archive__thumb-placeholder {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
font-size: 1.25rem;
color: #555;
}
.replay-archive__play-btn {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 36px;
height: 36px;
border-radius: 50%;
background: rgba(229, 57, 53, 0.95);
color: #fff;
font-size: 0.85rem;
line-height: 36px;
text-align: center;
padding-left: 3px;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
pointer-events: none;
}
.replay-archive__title-form,
.replay-archive__privacy-form,
.replay-archive__action-form {
margin: 0;
display: block;
}
.replay-archive__title-input {
width: 100%;
min-width: 10rem;
max-width: 18rem;
margin: 0;
padding: 8px 10px;
font-size: 0.92rem;
}
.replay-archive__privacy-select {
width: 100%;
min-width: 7.5rem;
margin: 0;
padding: 8px 10px;
font-size: 0.85rem;
}
.replay-archive__status {
display: inline-block;
padding: 4px 10px;
border-radius: 999px;
font-size: 0.78rem;
font-weight: 600;
white-space: nowrap;
}
.replay-archive__status--ready {
background: rgba(76, 175, 80, 0.18);
color: #81c784;
}
.replay-archive__status--processing {
background: rgba(255, 193, 7, 0.15);
color: #ffca28;
}
.replay-archive__status--failed,
.replay-archive__status--expired {
background: rgba(229, 57, 53, 0.15);
color: #ef9a9a;
}
.replay-archive__actions {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: flex-end;
gap: 6px;
}
.replay-archive__action {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 4px;
min-height: 34px;
padding: 0 10px;
border-radius: 8px;
border: 1px solid #3d3d4a;
background: #1c1c26;
color: #e8e8f0;
font-size: 0.8rem;
font-weight: 600;
text-decoration: none;
cursor: pointer;
white-space: nowrap;
transition: background 0.15s, border-color 0.15s;
}
.replay-archive__action:hover {
background: #262632;
border-color: #5a5a68;
color: #fff;
}
.replay-archive__action--play {
background: #e53935;
border-color: #e53935;
color: #fff;
min-width: 34px;
padding: 0 12px;
}
.replay-archive__action--play:hover {
background: #c62828;
border-color: #c62828;
color: #fff;
}
.replay-archive__action--secondary {
font-size: 0.75rem;
padding: 0 8px;
}
.replay-archive__action--danger {
border-color: rgba(229, 57, 53, 0.45);
color: #ef9a9a;
}
.replay-archive__action--danger:hover {
background: rgba(229, 57, 53, 0.15);
border-color: #e53935;
color: #ffcdd2;
}
.replay-archive .replay-filter-form {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
gap: 12px 16px;
margin-bottom: 20px;
}
.replay-archive .replay-filter-form label {
margin: 0 0 4px;
}
.replay-archive .replay-filter-form .input {
width: auto;
min-width: 10rem;
margin: 0;
}
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
@media (max-width: 720px) {
.replay-archive__action-label {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
}
.replay-archive__action--play {
min-width: 40px;
padding: 0;
}
}