diff --git a/backend/app/controllers/public/pages_controller.rb b/backend/app/controllers/public/pages_controller.rb index e1efb79..bc2b078 100644 --- a/backend/app/controllers/public/pages_controller.rb +++ b/backend/app/controllers/public/pages_controller.rb @@ -11,17 +11,8 @@ module Public load_club_billing_context_for_pricing end - private - - def load_club_billing_context_for_pricing - return unless logged_in? - - @club = current_user.primary_club - return unless @club - - @subscription = @club.subscription - @team = @club.teams.order(:name).first - @entitlements = @team&.entitlements + def support + @app_store_review_chrome = true end def privacy @@ -38,5 +29,18 @@ module Public def pallavolo end + + private + + def load_club_billing_context_for_pricing + return unless logged_in? + + @club = current_user.primary_club + return unless @club + + @subscription = @club.subscription + @team = @club.teams.order(:name).first + @entitlements = @team&.entitlements + end end end diff --git a/backend/app/controllers/public/sitemap_controller.rb b/backend/app/controllers/public/sitemap_controller.rb index 814a237..35e1bde 100644 --- a/backend/app/controllers/public/sitemap_controller.rb +++ b/backend/app/controllers/public/sitemap_controller.rb @@ -11,6 +11,7 @@ module Public { loc: "#{base}/live", changefreq: "hourly", priority: "0.85" }, { loc: "#{base}/squadre", changefreq: "daily", priority: "0.85" }, { loc: "#{base}/privacy", changefreq: "yearly", priority: "0.3" }, + { loc: "#{base}/support", changefreq: "yearly", priority: "0.3" }, { loc: "#{base}/cookie", changefreq: "yearly", priority: "0.3" }, { loc: "#{base}/termini", changefreq: "yearly", priority: "0.3" } ] diff --git a/backend/app/views/layouts/marketing.html.erb b/backend/app/views/layouts/marketing.html.erb index 0561bfa..11303a1 100644 --- a/backend/app/views/layouts/marketing.html.erb +++ b/backend/app/views/layouts/marketing.html.erb @@ -12,13 +12,13 @@ data-ga-id="<%= MatchLiveTv.google_analytics_measurement_id %>"<% end %>> <%= render "shared/cookie_banner" %> - <%= render "shared/marketing_nav" %> + <%= render(@app_store_review_chrome ? "shared/marketing_nav_app_store" : "shared/marketing_nav") %>
<% if flash[:notice] %>
<%= flash[:notice] %>
<% end %> <% if flash[:alert] %>
<%= flash[:alert] %>
<% end %> <%= yield %>
- <%= render "shared/marketing_footer" %> + <%= render(@app_store_review_chrome ? "shared/marketing_footer_app_store" : "shared/marketing_footer") %> diff --git a/backend/app/views/public/pages/support.html.erb b/backend/app/views/public/pages/support.html.erb new file mode 100644 index 0000000..245c712 --- /dev/null +++ b/backend/app/views/public/pages/support.html.erb @@ -0,0 +1,38 @@ +<% content_for :title, t("legal.support.title") %> +<% content_for :meta_description, t("legal.support.meta_description") %> +<% content_for :canonical_url, seo_absolute_url(public_support_path) %> + + diff --git a/backend/app/views/shared/_marketing_footer.html.erb b/backend/app/views/shared/_marketing_footer.html.erb index 378f0c3..4a61d7d 100644 --- a/backend/app/views/shared/_marketing_footer.html.erb +++ b/backend/app/views/shared/_marketing_footer.html.erb @@ -4,6 +4,7 @@ Match Live TV — <%= t("footer.tagline") %>
+ <%= link_to t("common.support"), public_support_path %> · <%= link_to t("common.pricing"), public_prezzi_path %> · <%= link_to t("footer.live"), public_live_index_path %> · <%= link_to t("common.faq"), public_faq_path %> · diff --git a/backend/app/views/shared/_marketing_footer_app_store.html.erb b/backend/app/views/shared/_marketing_footer_app_store.html.erb new file mode 100644 index 0000000..8487c3b --- /dev/null +++ b/backend/app/views/shared/_marketing_footer_app_store.html.erb @@ -0,0 +1,19 @@ +<%# Footer minimale per App Store Review: solo link legali/supporto, nessun CTA commerciale. %> + diff --git a/backend/app/views/shared/_marketing_nav_app_store.html.erb b/backend/app/views/shared/_marketing_nav_app_store.html.erb new file mode 100644 index 0000000..06a0a18 --- /dev/null +++ b/backend/app/views/shared/_marketing_nav_app_store.html.erb @@ -0,0 +1,86 @@ +<%# Chrome minimale per App Store Review: branding, lingua, Privacy e Supporto — senza CTA commerciali. %> +
+
+
+ <%= link_to public_support_path, class: "mast-brand", aria: { label: "Match Live TV" }, title: "Match Live TV" do %> + + + <% end %> + +
+ +
+
+
+ + +
+ + + + diff --git a/backend/config/initializers/match_live_tv.rb b/backend/config/initializers/match_live_tv.rb index f97faac..f6b3a0c 100644 --- a/backend/config/initializers/match_live_tv.rb +++ b/backend/config/initializers/match_live_tv.rb @@ -81,6 +81,12 @@ module MatchLiveTv ENV.fetch("PRIVACY_CONTACT_EMAIL", "privacy@matchlivetv.it") end + # Email di supporto (App Store Support URL e contatti assistenza). + # Preferisce SUPPORT_CONTACT_EMAIL; default = contatto commerciale già usato nel sito. + def support_email + ENV["SUPPORT_CONTACT_EMAIL"].presence || "info@matchlivetv.it" + end + def privacy_controller_address ENV.fetch("PRIVACY_CONTROLLER_ADDRESS", "Via Guido De Ruggiero, 89 - 20142 - Milano (MI)") end diff --git a/backend/config/locales/legal.de.yml b/backend/config/locales/legal.de.yml index a1699cb..c521da1 100644 --- a/backend/config/locales/legal.de.yml +++ b/backend/config/locales/legal.de.yml @@ -195,3 +195,18 @@ de: s6_body_html: "Um die von der DSGVO vorgesehenen Rechte auszuüben (Zugang, Löschung, Widerspruch, Widerruf der Einwilligung), schreiben Sie an %{email_link}. Details finden Sie im %{privacy_doc_link}." s6_privacy_doc_link_text: Datenschutzdokument manage_button: Cookie-Einstellungen verwalten + support: + title: Match Live TV Support + meta_description: "Match Live TV Hilfe: Zugangsprobleme, Livestreams, Teamverwaltung und Support-Kontaktdaten." + h1: Match Live TV Support + intro: "Brauchen Sie Hilfe mit Match Live TV? Bei Problemen mit dem Zugang, der Einrichtung von Livestreams, der Spielverwaltung oder der Nutzung der App können Sie unseren Support kontaktieren." + email_label: "Support-E-Mail:" + access_title: Zugangsprobleme + access_body: "Wenn Sie sich nicht anmelden können, prüfen Sie die Zugangsdaten, die Sie von Ihrem Sportverein erhalten haben. Wenn das Problem weiterhin besteht, kontaktieren Sie den Support." + live_title: Probleme während eines Livestreams + live_body: "Prüfen Sie Ihre Internetverbindung und versuchen Sie erneut, die Übertragung in der App zu starten. Wenn das Problem weiterhin besteht, kontaktieren Sie den Support und geben Sie Gerät, App-Version und eine kurze Beschreibung des Problems an." + team_title: Teamverwaltung + team_body: "Konten und Übertragungsberechtigungen werden vom Sportverein verwaltet." + privacy_title: Datenschutz + privacy_body_html: "Informationen zur Verarbeitung personenbezogener Daten finden Sie auf der Seite %{privacy_link}." + privacy_link_text: Datenschutz diff --git a/backend/config/locales/legal.en.yml b/backend/config/locales/legal.en.yml index 6c41b51..dbef280 100644 --- a/backend/config/locales/legal.en.yml +++ b/backend/config/locales/legal.en.yml @@ -195,3 +195,18 @@ en: s6_body_html: "To exercise the rights provided by the GDPR (access, erasure, objection, withdrawal of consent) write to %{email_link}. Details are in the %{privacy_doc_link}." s6_privacy_doc_link_text: privacy document manage_button: Manage cookie preferences + support: + title: Match Live TV Support + meta_description: "Match Live TV help: access issues, live streaming, team management and support contact details." + h1: Match Live TV Support + intro: "Need help with Match Live TV? For access issues, live stream setup, match management or app usage, you can contact our support team." + email_label: "Support email:" + access_title: Access issues + access_body: "If you cannot sign in, check the credentials provided by your sports club. If the problem persists, contact support." + live_title: Issues during a live stream + live_body: "Check your Internet connection and try starting the broadcast from the app again. If the problem persists, contact support and include your device, app version and a short description of the issue." + team_title: Team management + team_body: "Accounts and broadcasting permissions are managed by the sports club." + privacy_title: Privacy + privacy_body_html: "For information on personal data processing, see the %{privacy_link} page." + privacy_link_text: Privacy diff --git a/backend/config/locales/legal.es.yml b/backend/config/locales/legal.es.yml index 3976662..851ba1a 100644 --- a/backend/config/locales/legal.es.yml +++ b/backend/config/locales/legal.es.yml @@ -195,3 +195,18 @@ es: s6_body_html: "Para ejercer los derechos previstos por el RGPD (acceso, supresión, oposición, revocación del consentimiento) escribe a %{email_link}. Más detalles en el %{privacy_doc_link}." s6_privacy_doc_link_text: documento de privacidad manage_button: Gestionar preferencias de cookies + support: + title: Soporte Match Live TV + meta_description: "Ayuda de Match Live TV: problemas de acceso, directos, gestión del equipo y datos de contacto del soporte." + h1: Soporte Match Live TV + intro: "¿Necesitas ayuda con Match Live TV? Para problemas de acceso, configuración de directos, gestión de partidos o uso de la app puedes contactar con nuestro soporte." + email_label: "Correo de soporte:" + access_title: Problemas de acceso + access_body: "Si no puedes acceder, verifica las credenciales recibidas de tu club deportivo. Si el problema continúa, contacta con el soporte." + live_title: Problemas durante un directo + live_body: "Verifica la conexión a Internet e intenta de nuevo iniciar la transmisión desde la app. Si el problema continúa, contacta con el soporte indicando el dispositivo, la versión de la app y una breve descripción del problema." + team_title: Gestión del equipo + team_body: "Las cuentas y los permisos de transmisión los gestiona el club deportivo." + privacy_title: Privacidad + privacy_body_html: "Para información sobre el tratamiento de datos personales, consulta la página %{privacy_link}." + privacy_link_text: Privacidad diff --git a/backend/config/locales/legal.fr.yml b/backend/config/locales/legal.fr.yml index 467be5c..fc9e061 100644 --- a/backend/config/locales/legal.fr.yml +++ b/backend/config/locales/legal.fr.yml @@ -195,3 +195,18 @@ fr: s6_body_html: "Pour exercer les droits prévus par le RGPD (accès, effacement, opposition, retrait du consentement), écrivez à %{email_link}. Détails dans le %{privacy_doc_link}." s6_privacy_doc_link_text: document de confidentialité manage_button: Gérer les préférences de cookies + support: + title: Support Match Live TV + meta_description: "Assistance Match Live TV : problèmes d'accès, directs, gestion d'équipe et coordonnées du support." + h1: Support Match Live TV + intro: "Besoin d'aide avec Match Live TV ? Pour les problèmes d'accès, la configuration des directs, la gestion des matchs ou l'utilisation de l'application, vous pouvez contacter notre support." + email_label: "E-mail du support :" + access_title: Problèmes d'accès + access_body: "Si vous ne parvenez pas à vous connecter, vérifiez les identifiants fournis par votre club sportif. Si le problème persiste, contactez le support." + live_title: Problèmes pendant un direct + live_body: "Vérifiez votre connexion Internet et réessayez de démarrer la diffusion depuis l'application. Si le problème persiste, contactez le support en indiquant l'appareil, la version de l'application et une brève description du problème." + team_title: Gestion de l'équipe + team_body: "Les comptes et les autorisations de diffusion sont gérés par le club sportif." + privacy_title: Confidentialité + privacy_body_html: "Pour les informations sur le traitement des données personnelles, consultez la page %{privacy_link}." + privacy_link_text: Confidentialité diff --git a/backend/config/locales/legal.it.yml b/backend/config/locales/legal.it.yml index 68a9f78..783bba5 100644 --- a/backend/config/locales/legal.it.yml +++ b/backend/config/locales/legal.it.yml @@ -195,3 +195,18 @@ it: s6_body_html: "Per esercitare i diritti previsti dal GDPR (accesso, cancellazione, opposizione, revoca consenso) scrivi a %{email_link}. Dettagli nel %{privacy_doc_link}." s6_privacy_doc_link_text: documento privacy manage_button: Gestisci preferenze cookie + support: + title: Supporto Match Live TV + meta_description: "Assistenza Match Live TV: problemi di accesso, dirette live, gestione squadra e contatti del supporto." + h1: Supporto Match Live TV + intro: "Hai bisogno di assistenza con Match Live TV? Per problemi di accesso, configurazione delle dirette, gestione delle partite o utilizzo dell’app puoi contattare il nostro supporto." + email_label: "Email di supporto:" + access_title: Problemi di accesso + access_body: "Se non riesci ad accedere, verifica le credenziali ricevute dalla tua società sportiva. Se il problema persiste, contatta il supporto." + live_title: Problemi durante una diretta + live_body: "Verifica la connessione Internet e riprova ad avviare la trasmissione dall’app. Se il problema persiste, contatta il supporto indicando dispositivo, versione dell’app e una breve descrizione del problema." + team_title: Gestione della squadra + team_body: "Gli account e le autorizzazioni per la trasmissione sono gestiti dalla società sportiva." + privacy_title: Privacy + privacy_body_html: "Per informazioni sul trattamento dei dati personali consulta la pagina %{privacy_link}." + privacy_link_text: Privacy diff --git a/backend/config/locales/ui.de.yml b/backend/config/locales/ui.de.yml index 88cf26c..3f0ff76 100644 --- a/backend/config/locales/ui.de.yml +++ b/backend/config/locales/ui.de.yml @@ -133,6 +133,7 @@ de: save_password: Passwort aktualisieren common: privacy: Datenschutz + support: Support cookies: Cookies terms: AGB pricing: Preise diff --git a/backend/config/locales/ui.en.yml b/backend/config/locales/ui.en.yml index 114682c..6fabb6c 100644 --- a/backend/config/locales/ui.en.yml +++ b/backend/config/locales/ui.en.yml @@ -133,6 +133,7 @@ en: save_password: Update password common: privacy: Privacy + support: Support cookies: Cookies terms: Terms pricing: Pricing diff --git a/backend/config/locales/ui.es.yml b/backend/config/locales/ui.es.yml index a4b3e74..7ff839d 100644 --- a/backend/config/locales/ui.es.yml +++ b/backend/config/locales/ui.es.yml @@ -133,6 +133,7 @@ es: save_password: Actualizar contraseña common: privacy: Privacidad + support: Soporte cookies: Cookies terms: Términos pricing: Precios diff --git a/backend/config/locales/ui.fr.yml b/backend/config/locales/ui.fr.yml index 7072601..3b17f06 100644 --- a/backend/config/locales/ui.fr.yml +++ b/backend/config/locales/ui.fr.yml @@ -133,6 +133,7 @@ fr: save_password: Mettre à jour le mot de passe common: privacy: Confidentialité + support: Support cookies: Cookies terms: Conditions pricing: Tarifs diff --git a/backend/config/locales/ui.it.yml b/backend/config/locales/ui.it.yml index daf409c..b1fd086 100644 --- a/backend/config/locales/ui.it.yml +++ b/backend/config/locales/ui.it.yml @@ -133,6 +133,7 @@ it: save_password: Aggiorna password common: privacy: Privacy + support: Supporto cookies: Cookie terms: Termini pricing: Prezzi diff --git a/backend/config/routes.rb b/backend/config/routes.rb index 5b37e3a..3107a01 100644 --- a/backend/config/routes.rb +++ b/backend/config/routes.rb @@ -154,6 +154,7 @@ Rails.application.routes.draw do get "prezzi", to: "pages#pricing", as: :prezzi get "pricing", to: redirect("/prezzi") get "privacy", to: "pages#privacy", as: :privacy + get "support", to: "pages#support", as: :support get "cookie", to: "pages#cookies", as: :cookies get "cookies", to: redirect("/cookie") get "termini", to: "pages#terms", as: :termini diff --git a/backend/spec/requests/public/support_page_spec.rb b/backend/spec/requests/public/support_page_spec.rb new file mode 100644 index 0000000..f50cdf1 --- /dev/null +++ b/backend/spec/requests/public/support_page_spec.rb @@ -0,0 +1,57 @@ +require "rails_helper" + +RSpec.describe "Public support page", type: :request do + it "è pubblica, indicizzabile e mostra l'email di supporto configurata" do + get public_support_path + + expect(response).to have_http_status(:ok) + expect(response.body).to include(MatchLiveTv.support_email) + expect(response.body).to include("mailto:#{MatchLiveTv.support_email}") + expect(response.body).to include(I18n.t("legal.support.h1", locale: :it)) + expect(response.body).to include('rel="canonical"') + expect(response.body).to include(public_support_path) + expect(response.body).to include(public_privacy_path) + end + + it "non espone CTA o link commerciali (App Store Review)" do + get public_support_path + body = response.body + + expect(body).not_to include(public_prezzi_path) + expect(body).not_to include(public_signup_path) + expect(body).not_to include('href="/prezzi"') + expect(body).not_to include('href="/signup"') + expect(body).not_to include(I18n.t("nav.signup", locale: :it)) + expect(body).not_to include(I18n.t("nav.pricing", locale: :it)) + expect(body).not_to include(I18n.t("common.pricing", locale: :it)) + expect(body).not_to match(/\bPremium Light\b/i) + expect(body).not_to match(/\bPremium Full\b/i) + expect(body).not_to match(/\bpiano Free\b/i) + expect(body).not_to match(/\bAbbonati\b/i) + expect(body).not_to match(/\bAcquista\b/i) + end + + { + "it" => "Supporto Match Live TV", + "en" => "Match Live TV Support", + "fr" => "Support Match Live TV", + "de" => "Match Live TV Support", + "es" => "Soporte Match Live TV" + }.each do |locale, heading| + it "renderizza correttamente in #{locale} senza translation missing" do + cookies[:mltv_locale] = locale + get public_support_path + + expect(response).to have_http_status(:ok) + expect(response.body).to include(heading) + expect(response.body).not_to include("translation missing") + end + end + + it "include /support nella sitemap" do + get "/sitemap.xml" + + expect(response).to have_http_status(:ok) + expect(response.body).to include("#{MatchLiveTv.app_public_url.chomp('/')}/support") + end +end diff --git a/infra/.env.example b/infra/.env.example index ec6149b..bae5327 100644 --- a/infra/.env.example +++ b/infra/.env.example @@ -15,6 +15,8 @@ YOUTUBE_MOCK_STREAM_KEY=mock-stream-key PRIVACY_CONTROLLER_NAME=Emiliano Frascaro PRIVACY_CONTROLLER_ADDRESS=Via Guido De Ruggiero, 89 - 20142 - Milano (MI) PRIVACY_CONTACT_EMAIL=privacy@matchlivetv.it +# Opzionale: email dedicata di supporto (default = info@matchlivetv.it) +# SUPPORT_CONTACT_EMAIL=info@matchlivetv.it MAILER_FROM=Match Live TV PASSWORD_RESET_EXPIRY_HOURS=2 diff --git a/infra/.env.production.example b/infra/.env.production.example index bc56c6b..7beb295 100644 --- a/infra/.env.production.example +++ b/infra/.env.production.example @@ -39,6 +39,8 @@ RAILS_LOG_LEVEL=info PRIVACY_CONTROLLER_NAME=Emiliano Frascaro PRIVACY_CONTROLLER_ADDRESS=Via Guido De Ruggiero, 89 - 20142 - Milano (MI) PRIVACY_CONTACT_EMAIL=privacy@matchlivetv.it +# Opzionale: email di supporto App Store (default = info@matchlivetv.it) +# SUPPORT_CONTACT_EMAIL=info@matchlivetv.it PRIVACY_CONTROLLER_VAT= # Email transazionali (reset password, inviti) diff --git a/infra/docker-compose.prod.yml b/infra/docker-compose.prod.yml index 99f3360..3835ea0 100644 --- a/infra/docker-compose.prod.yml +++ b/infra/docker-compose.prod.yml @@ -73,6 +73,7 @@ services: HLS_PUBLIC_URL: ${HLS_PUBLIC_URL:-http://localhost:8888} APP_PUBLIC_URL: ${APP_PUBLIC_URL:-http://localhost:3000} PRIVACY_CONTACT_EMAIL: ${PRIVACY_CONTACT_EMAIL:-privacy@matchlivetv.it} + SUPPORT_CONTACT_EMAIL: ${SUPPORT_CONTACT_EMAIL:-} PRIVACY_CONTROLLER_NAME: ${PRIVACY_CONTROLLER_NAME:-Emiliano Frascaro} PRIVACY_CONTROLLER_ADDRESS: ${PRIVACY_CONTROLLER_ADDRESS:-Via Guido De Ruggiero, 89 - 20142 - Milano (MI)} PRIVACY_CONTROLLER_VAT: ${PRIVACY_CONTROLLER_VAT:-} diff --git a/infra/docker-compose.yml b/infra/docker-compose.yml index 71845a5..96b5da6 100644 --- a/infra/docker-compose.yml +++ b/infra/docker-compose.yml @@ -71,6 +71,7 @@ services: PRIVACY_CONTROLLER_NAME: ${PRIVACY_CONTROLLER_NAME:-Emiliano Frascaro} PRIVACY_CONTROLLER_ADDRESS: ${PRIVACY_CONTROLLER_ADDRESS:-Via Guido De Ruggiero, 89 - 20142 - Milano (MI)} PRIVACY_CONTACT_EMAIL: ${PRIVACY_CONTACT_EMAIL:-privacy@matchlivetv.it} + SUPPORT_CONTACT_EMAIL: ${SUPPORT_CONTACT_EMAIL:-} MAILER_FROM: ${MAILER_FROM:-Match Live TV } APP_PUBLIC_URL: ${APP_PUBLIC_URL:-http://localhost:3000} STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY:-}