Billing upgrade/downgrade, inviti in app e diretta YouTube da mobile.
Upgrade Stripe con addebito immediato; downgrade programmato a fine periodo. UX billing più sobria con box info; icone piani. API inviti e OAuth YouTube per staff trasmissione; deep link join; scelta partita programmata o nuova. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -6,6 +6,9 @@
|
||||
<%= render "shared/club_subscription_status", club: @club, entitlements: @entitlements, subscription: @subscription, on_billing_page: true %>
|
||||
|
||||
<%= render "shared/stripe_secure_payment" %>
|
||||
<% if MatchLiveTv.stripe_enabled? %>
|
||||
<%= render "shared/plan_change_info", subscription: @subscription %>
|
||||
<% end %>
|
||||
<%= render "shared/plan_cards", show_stripe_portal: false %>
|
||||
<%= render "shared/subscription_cancel", club: @club, subscription: @subscription %>
|
||||
|
||||
|
||||
@@ -5,10 +5,17 @@
|
||||
<div class="card" style="max-width:480px">
|
||||
<h1>Accesso staff — <%= @invitation.team.name %></h1>
|
||||
<p>Sei stato aggiunto come <strong>responsabile trasmissione</strong> (<%= @invitation.email %>).</p>
|
||||
<p class="muted" style="font-size:0.9rem;margin-bottom:16px">
|
||||
Nell’app Match Live TV accedi con <strong><%= @invitation.email %></strong>, accetta l’invito e collega il tuo canale YouTube.
|
||||
</p>
|
||||
<% if logged_in? %>
|
||||
<%= button_to "Accetta invito", public_invitation_path(token: @token), method: :post, class: "btn btn-primary" %>
|
||||
<% else %>
|
||||
<p><%= link_to "Accedi", public_login_path %> o <%= link_to "registrati", public_signup_path %> con <%= @invitation.email %>.</p>
|
||||
<%= button_to "Accetta (se già loggato)", public_invitation_path(token: @token), method: :post, class: "btn btn-secondary" %>
|
||||
<% end %>
|
||||
<p style="margin-top:16px;font-size:0.88rem;color:#888">
|
||||
App mobile:
|
||||
<a href="matchlivetv://join/<%= @token %>">Apri invito nell’app</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div class="plans">
|
||||
<% @plans.each do |plan| %>
|
||||
<div class="plan-card">
|
||||
<h3><%= plan.name %></h3>
|
||||
<%= render "shared/plan_title", plan: plan %>
|
||||
<% if plan.slug == "free" %>
|
||||
<div class="plan-price">€0</div>
|
||||
<% elsif plan.slug == "premium_light" %>
|
||||
@@ -27,7 +27,6 @@
|
||||
<% if plan.slug == @entitlements.plan.slug %>
|
||||
<span class="btn btn-secondary" style="opacity:0.7">Piano attuale</span>
|
||||
<% elsif plan.slug == "free" %>
|
||||
<p style="color:#888;font-size:0.85rem">Contatta il supporto per downgrade.</p>
|
||||
<% elsif MatchLiveTv.stripe_enabled? %>
|
||||
<%= link_to "Gestisci abbonamento società", public_club_billing_path(@team.club), class: "btn btn-primary" %>
|
||||
<% else %>
|
||||
|
||||
@@ -16,8 +16,20 @@
|
||||
<strong><%= subscription.current_period_end.present? ? l_local(subscription.current_period_end.to_date) : "fine periodo" %></strong>,
|
||||
poi piano Free.
|
||||
</span>
|
||||
<% elsif subscription.plan_change_pending? && subscription.pending_plan.present? %>
|
||||
<span style="color:#ffb74d">
|
||||
Dal <strong><%= subscription.current_period_end.present? ? l_local(subscription.current_period_end) : "prossimo rinnovo" %></strong>
|
||||
passerai a <strong><%= subscription.pending_plan.name %></strong>
|
||||
<% if subscription.pending_billing_interval.present? %>
|
||||
(<%= Billing::Stripe::PriceCatalog.label(plan_slug: subscription.pending_plan.slug, interval: subscription.pending_billing_interval) %>)
|
||||
<% end %>.
|
||||
Fino ad allora resta attivo <strong><%= current_plan.name %></strong>.
|
||||
</span>
|
||||
<% elsif subscription.current_period_end.present? %>
|
||||
Prossimo rinnovo: <strong><%= l_local(subscription.current_period_end) %></strong>
|
||||
<% if subscription.billing_interval.present? %>
|
||||
· <%= Billing::Stripe::PriceCatalog.label(plan_slug: current_plan.slug, interval: subscription.billing_interval) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
current_slug: current_slug,
|
||||
target_plan: plan,
|
||||
stripe_subscription_active: stripe_subscription_active?(subscription),
|
||||
current_interval: current_interval
|
||||
current_interval: current_interval,
|
||||
subscription: subscription
|
||||
) : nil %>
|
||||
<div class="plan-card">
|
||||
<h3><%= plan.name %></h3>
|
||||
<%= render "shared/plan_title", plan: plan %>
|
||||
<% if plan.slug == "free" %>
|
||||
<div class="plan-price">€0</div>
|
||||
<% elsif plan.slug == "premium_light" %>
|
||||
@@ -39,7 +40,8 @@
|
||||
<% action_kind = action[:kind] %>
|
||||
<% if action_kind == :current %>
|
||||
<span class="btn btn-secondary" style="opacity:0.7"><%= action[:label] %></span>
|
||||
<% elsif action_kind == :contact || action_kind == :disabled %>
|
||||
<% elsif action_kind == :none %>
|
||||
<% elsif action_kind.in?(%i[contact disabled]) %>
|
||||
<p class="plan-action-hint"><%= action[:label] %></p>
|
||||
<% elsif action_kind == :checkout_options || action_kind == :change_options || action_kind == :interval_switch %>
|
||||
<% if billing_profile_blocks_premium?(club) %>
|
||||
@@ -52,16 +54,13 @@
|
||||
<% else %>
|
||||
<div class="plan-interval-actions">
|
||||
<% plan_intervals_for_display(action[:intervals]).each do |interval| %>
|
||||
<% btn_kind = action_kind == :checkout_options ? :checkout : :change %>
|
||||
<% btn_kind = action_kind == :checkout_options ? :checkout_options : action_kind %>
|
||||
<%= link_to plan_interval_button_label(plan, interval, kind: btn_kind),
|
||||
plan_interval_checkout_path(club, plan, interval),
|
||||
class: plan_interval_button_class(interval) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if action_kind == :interval_switch && action[:current_interval].present? %>
|
||||
<p class="plan-action-hint">Fatturazione attuale: <%= Billing::Stripe::PriceCatalog.label(plan_slug: plan.slug, interval: action[:current_interval]) %></p>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% elsif plan.slug == "free" %>
|
||||
<%= link_to "Inizia gratis", public_signup_path, class: "btn btn-secondary" %>
|
||||
|
||||
17
backend/app/views/shared/_plan_change_info.html.erb
Normal file
17
backend/app/views/shared/_plan_change_info.html.erb
Normal file
@@ -0,0 +1,17 @@
|
||||
<%# locals: (subscription: nil) %>
|
||||
<% lines = billing_plan_change_info_lines(subscription: subscription) %>
|
||||
<div class="plan-change-info-wrap">
|
||||
<details class="plan-change-info">
|
||||
<summary class="plan-change-info__trigger" aria-label="Info cambio piano e fatturazione" title="Info cambio piano e fatturazione">
|
||||
<i class="fa-solid fa-circle-info" aria-hidden="true"></i>
|
||||
</summary>
|
||||
<div class="plan-change-info__box" role="note">
|
||||
<p class="plan-change-info__title">Cambio piano e fatturazione</p>
|
||||
<ul>
|
||||
<% lines.each do |line| %>
|
||||
<li><%= line %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
5
backend/app/views/shared/_plan_title.html.erb
Normal file
5
backend/app/views/shared/_plan_title.html.erb
Normal file
@@ -0,0 +1,5 @@
|
||||
<%# locals: (plan:) %>
|
||||
<h3 class="plan-card__title">
|
||||
<i class="<%= plan_icon_class(plan) %>" aria-hidden="true"></i>
|
||||
<span><%= plan.name %></span>
|
||||
</h3>
|
||||
@@ -1,7 +1,7 @@
|
||||
<%# locals: (club:, subscription:) %>
|
||||
<% return unless subscription&.premium? && subscription.stripe_subscription_id.present? && MatchLiveTv.stripe_enabled? %>
|
||||
|
||||
<section class="subscription-cancel" style="margin-top:24px;padding:16px;border:1px solid #333;border-radius:8px">
|
||||
<section id="subscription-cancel" class="subscription-cancel" style="margin-top:24px;padding:16px;border:1px solid #333;border-radius:8px">
|
||||
<% if subscription.cancel_at_period_end? %>
|
||||
<p style="color:#e53935;margin:0 0 8px">
|
||||
<strong>Disdetta programmata.</strong>
|
||||
|
||||
Reference in New Issue
Block a user