diff --git a/apps/web/messages/it.json b/apps/web/messages/it.json index 892e972..fabfc7f 100644 --- a/apps/web/messages/it.json +++ b/apps/web/messages/it.json @@ -62,7 +62,9 @@ "ctaSectionTitle": "Pronti a partire?", "ctaSectionBody": "Sette passaggi, dieci minuti, e il tuo primo piano è pronto. Senza carta di credito.", "principlesEyebrow": "Tre principi non negoziabili", - "footerCopyright": "KetoPath — anno I, Italia." + "footerCopyright": "KetoPath — anno I, Italia.", + "footerLinkPrivacy": "Privacy", + "footerLinkTerms": "Termini" }, "Welcome": { "title": "Prima di iniziare", @@ -81,6 +83,7 @@ "CookieBanner": { "aria": "Informativa cookie", "message": "Usiamo solo cookie essenziali per autenticazione e sessione. Niente analytics o tracker di terze parti.", + "learnMore": "Leggi l'Informativa Privacy", "dismiss": "Ho capito" }, "Metadata": { @@ -98,7 +101,8 @@ "google": "Continua con Google", "or": "oppure", "noAccount": "Non hai ancora un account? Iscriviti", - "error": "Credenziali non valide. Riprova." + "error": "Credenziali non valide. Riprova.", + "legalNote": "Accedendo accetti i Termini di servizio e la nostra Informativa Privacy." }, "SignUp": { "title": "Iscriviti", @@ -113,7 +117,7 @@ "or": "oppure", "haveAccount": "Hai già un account? Accedi", "error": "Non è stato possibile completare la registrazione. Riprova.", - "disclaimer": "Procedendo accetti che i tuoi dati siano trattati come descritto nell'informativa sulla privacy. KetoPath non sostituisce il parere medico." + "disclaimer": "Procedendo accetti i Termini di servizio e l'Informativa Privacy. KetoPath è uno strumento di stile di vita, non sostituisce il parere medico." } }, "Fasting": { @@ -769,5 +773,198 @@ "api_error_401": "Devi accedere per gestire l'abbonamento.", "api_error_500": "Errore del server. Riprova fra poco." } + }, + "Legal": { + "Shared": { + "lastUpdated": "Ultimo aggiornamento — {date}", + "toc": "Indice", + "related": "Pagine collegate", + "linkPrivacy": "Informativa Privacy", + "linkTerms": "Termini di servizio", + "linkHome": "Torna alla home" + }, + "Privacy": { + "metaTitle": "Informativa Privacy — KetoPath", + "metaDescription": "Informativa sul trattamento dei dati personali ai sensi degli artt. 13 e 14 del Regolamento (UE) 2016/679 (GDPR).", + "eyebrow": "Capitolo X — Informativa Privacy", + "title": "Come trattiamo i tuoi dati", + "subtitle": "Questa informativa spiega quali dati personali raccogliamo quando usi KetoPath, perché lo facciamo, per quanto tempo li conserviamo e quali diritti puoi esercitare in qualsiasi momento. È redatta ai sensi degli artt. 13 e 14 del Regolamento (UE) 2016/679 (GDPR) e del D.Lgs. 196/2003 come modificato dal D.Lgs. 101/2018.", + "sections": { + "controller": { + "heading": "Titolare del trattamento", + "p1": "Il titolare del trattamento dei dati personali raccolti tramite il sito lamiadieta.luzaonline.net e l'applicazione KetoPath è Carlo Santoleri, in qualità di persona fisica. Per qualunque richiesta relativa alla presente informativa o all'esercizio dei diritti di cui agli artt. 15-22 GDPR puoi scrivere all'indirizzo email carlo.santoleri@gmail.com.", + "p2": "Non è stato nominato un Responsabile della Protezione dei Dati (DPO) in quanto non ricorrono i presupposti obbligatori di cui all'art. 37 GDPR. Il titolare resta comunque l'unico referente per ogni richiesta e si impegna a rispondere entro 30 giorni dalla ricezione, salvo proroghe motivate ai sensi dell'art. 12 par. 3 GDPR." + }, + "dataCollected": { + "heading": "Categorie di dati raccolti", + "p1": "Dati di account e autenticazione: indirizzo email, nome visualizzato, password (memorizzata esclusivamente come hash scrypt, mai in chiaro), identificativo OAuth se accedi tramite Google, data di creazione dell'account, data dell'ultimo accesso, indirizzo IP di sessione e identificativo del dispositivo.", + "p2": "Dati di profilo nutrizionale: data di nascita, sesso biologico (necessario al calcolo del metabolismo basale secondo la formula Mifflin-St Jeor), altezza, peso iniziale, peso obiettivo, livello di attività fisica, protocollo di digiuno intermittente preferito, esclusioni alimentari (allergie, intolleranze, scelte etiche).", + "p3": "Dati di tracking (categoria particolare ai sensi dell'art. 9 GDPR — vedi sezione successiva): pesate ricorrenti, misure corporee, eventuali fotografie di progresso caricate volontariamente, registrazioni di check-in soggettivi quotidiani (energia, sonno, fame, umore), sintomi associati ai digiuni, sessioni di digiuno avviate e completate.", + "p4": "Dati di pagamento e fatturazione: identificativo cliente Stripe, ultime quattro cifre della carta utilizzata, stato dell'abbonamento, periodi di rinnovo e fatture. La carta di pagamento non viene mai trasmessa ai nostri server: è gestita interamente dalla piattaforma Stripe Inc. e dalla sua controllata europea (vedi sezione \"Destinatari\").", + "p5": "Dati tecnici di funzionamento: log di errore lato server (senza riferimenti diretti ai dati di salute), preferenze di sessione (lingua, locale, consenso cookie), tipo di browser e sistema operativo per finalità di compatibilità e sicurezza." + }, + "healthData": { + "heading": "Dati relativi alla salute", + "p1": "I dati di tracking (peso, misure, foto, sintomi, check-in soggettivi) rientrano nella nozione di \"dati relativi alla salute\" di cui all'art. 4 n. 15 e art. 9 GDPR. Il loro trattamento richiede una base giuridica rafforzata, individuata nel consenso esplicito da te prestato in sede di onboarding (art. 9 par. 2 lett. a GDPR), che puoi revocare in qualsiasi momento dalla pagina Profilo > Dati senza che ciò pregiudichi la liceità del trattamento effettuato prima della revoca.", + "p2": "Questi dati sono cifrati at-rest tramite algoritmo AES-GCM 256 a livello applicativo prima di essere persistiti nel database, in aggiunta alla cifratura del filesystem del server. Non vengono utilizzati per profilazione, scoring sanitario o decisioni automatizzate ai sensi dell'art. 22 GDPR, né condivisi con compagnie assicurative, datori di lavoro, autorità sanitarie o terzi a fini commerciali. I log applicativi sono configurati per non includere alcun campo classificato come dato di salute." + }, + "purposes": { + "heading": "Finalità del trattamento", + "p1": "Erogare il servizio: creare il tuo account, calcolare fabbisogno calorico e macros, generare il piano alimentare settimanale e la lista della spesa, mostrarti grafici di andamento, gestire le sessioni di digiuno, inviarti i promemoria che hai esplicitamente scelto di ricevere.", + "p2": "Gestire l'abbonamento: fatturare il periodo di prova (gratuito 30 giorni) e gli eventuali rinnovi del piano Pro, conservare le fatture per gli obblighi fiscali, comunicarti scadenze e cambi di stato dell'abbonamento.", + "p3": "Garantire la sicurezza: rilevare e prevenire accessi abusivi, frodi sui pagamenti, abusi dell'API, attacchi automatizzati. Per questa finalità conserviamo per un periodo limitato gli indirizzi IP di sessione e i tentativi di accesso falliti.", + "p4": "Adempiere a obblighi di legge: conservare la documentazione fiscale e contabile, rispondere a richieste motivate dell'autorità giudiziaria, dell'autorità garante per la protezione dei dati personali o di altre autorità competenti." + }, + "legalBasis": { + "heading": "Base giuridica", + "p1": "Per i dati di account e per l'esecuzione del piano alimentare la base giuridica è l'esecuzione del contratto di cui sei parte ai sensi dell'art. 6 par. 1 lett. b GDPR.", + "p2": "Per i dati relativi alla salute (peso, misure, foto, sintomi, check-in) la base giuridica è il tuo consenso esplicito ai sensi dell'art. 9 par. 2 lett. a GDPR, prestato durante l'onboarding insieme all'accettazione del disclaimer medico.", + "p3": "Per la fatturazione, la sicurezza, la prevenzione frodi e la conservazione dei log la base giuridica è il legittimo interesse del titolare e l'adempimento di obblighi legali ai sensi dell'art. 6 par. 1 lett. c ed f GDPR." + }, + "recipients": { + "heading": "Destinatari e responsabili del trattamento", + "p1": "I tuoi dati sono accessibili al solo titolare e ai fornitori di servizi tecnici (\"responsabili del trattamento\" ai sensi dell'art. 28 GDPR) strettamente necessari all'erogazione del servizio. Tutti i responsabili sono vincolati da un accordo (Data Processing Agreement) che ne disciplina obblighi e limiti.", + "p2": "Hosting e database: il server applicativo, il database PostgreSQL e Redis sono ospitati su infrastruttura Virtualmin/VPS gestita all'interno dell'Unione Europea. I backup giornalieri sono cifrati e conservati sullo stesso provider.", + "p3": "Autenticazione Google (opzionale): se scegli di accedere con Google, Google Ireland Limited tratta il tuo indirizzo email e il tuo nome al solo scopo di autenticarti. KetoPath riceve esclusivamente le informazioni minime di profilo necessarie a creare la sessione.", + "p4": "Pagamenti: Stripe Payments Europe Limited (sede in Irlanda) elabora le transazioni economiche e gestisce direttamente i dati della carta. KetoPath riceve da Stripe soltanto i metadati strettamente necessari alla fatturazione e all'identificazione del cliente.", + "p5": "Email transazionali: SendGrid (Twilio Inc.) viene utilizzato per l'invio di email di sistema (conferma account, reset password, promemoria di rinnovo). A SendGrid trasmettiamo unicamente il tuo indirizzo email e il contenuto della comunicazione.", + "p6": "Storage delle foto progresso: le immagini che decidi di caricare sono archiviate su Cloudflare R2 in region europea, accessibili tramite URL firmati a scadenza breve. Nessun altro soggetto può accedere alle tue foto." + }, + "transfers": { + "heading": "Trasferimenti extra-UE", + "p1": "Alcuni responsabili (Stripe, SendGrid, Cloudflare) appartengono a gruppi societari con sede negli Stati Uniti. I trasferimenti di dati al di fuori dello Spazio Economico Europeo sono effettuati sulla base delle Clausole Contrattuali Standard approvate dalla Commissione Europea (decisione 2021/914) e, ove applicabile, sulla base del Data Privacy Framework UE-USA.", + "p2": "Su richiesta puoi ottenere copia delle garanzie contrattuali in essere scrivendo all'indirizzo email del titolare." + }, + "retention": { + "heading": "Tempi di conservazione", + "p1": "Dati di account: per tutta la durata del tuo utilizzo del servizio e fino a 12 mesi dall'ultimo accesso, dopodiché l'account è soggetto a procedura di chiusura automatica con preavviso. Su tua richiesta possiamo procedere alla cancellazione immediata.", + "p2": "Dati relativi alla salute: per la durata dell'account, salvo revoca del consenso. Alla cancellazione dell'account vengono rimossi entro 30 giorni, esclusi i backup cifrati che decadono al massimo entro 90 giorni dalla cancellazione.", + "p3": "Dati fiscali e di fatturazione: 10 anni dalla data di emissione del documento, in adempimento agli obblighi del Codice Civile e della normativa fiscale italiana." + }, + "security": { + "heading": "Misure di sicurezza", + "p1": "Adottiamo misure tecniche e organizzative adeguate al rischio (art. 32 GDPR): connessione HTTPS con certificato Let's Encrypt, cifratura del database a livello di disco e a livello di campo per i dati sensibili, hashing scrypt delle password, rate limiting sulle API, accesso al server limitato a chiavi SSH dedicate, backup giornalieri cifrati, monitoraggio degli accessi anomali e degli errori applicativi.", + "p2": "Nonostante l'impegno costante, nessun sistema può garantire la sicurezza assoluta. Ti chiediamo di scegliere una password robusta, di non condividerla e di segnalarci immediatamente qualunque attività sospetta sul tuo account." + }, + "rights": { + "heading": "I tuoi diritti", + "p1": "Hai il diritto di accedere ai tuoi dati (art. 15), di chiederne la rettifica (art. 16), la cancellazione (art. 17 — diritto all'oblio), la limitazione del trattamento (art. 18), di ricevere i dati in formato strutturato e leggibile da dispositivo automatico per trasmetterli ad altro titolare (art. 20 — portabilità), di opporti al trattamento (art. 21) e di revocare in qualsiasi momento il consenso prestato senza pregiudizio per la liceità del trattamento precedente.", + "p2": "Puoi esercitare questi diritti direttamente dalla pagina Profilo > Dati (esportazione e cancellazione) oppure scrivendo a carlo.santoleri@gmail.com. La risposta è gratuita e ti perverrà entro 30 giorni, salvo proroga motivata.", + "p3": "Se ritieni che il trattamento dei tuoi dati violi il GDPR puoi proporre reclamo al Garante per la Protezione dei Dati Personali (Piazza Venezia 11, 00187 Roma — www.garanteprivacy.it) o all'autorità di controllo dello Stato membro UE in cui risiedi abitualmente." + }, + "minors": { + "heading": "Minori", + "p1": "Il servizio è destinato esclusivamente a persone maggiorenni. Non raccogliamo intenzionalmente dati di minori di 18 anni. Se vieni a conoscenza di un account riconducibile a un minore, ti invitiamo a segnalarcelo: provvederemo alla rimozione immediata." + }, + "cookies": { + "heading": "Cookie e tecnologie simili", + "p1": "KetoPath utilizza esclusivamente cookie tecnici di sessione e cookie di funzionalità (preferenze di lingua, conferma dell'avviso cookie). Non utilizziamo cookie di profilazione né tracker di terze parti: nessun Google Analytics, nessun pixel pubblicitario.", + "p2": "L'unica eccezione riguarda Stripe, che durante le pagine di checkout può impostare cookie di sicurezza necessari a prevenire frodi sui pagamenti: si tratta di cookie tecnici esenti dal consenso ai sensi del provvedimento del Garante del 10 giugno 2021." + }, + "changes": { + "heading": "Modifiche all'informativa", + "p1": "Possiamo aggiornare questa informativa quando cambiamo le finalità, le tecnologie o i fornitori che trattano i tuoi dati. In caso di modifiche sostanziali ti avviseremo via email o tramite un avviso visibile in app almeno 15 giorni prima dell'entrata in vigore. La data dell'ultimo aggiornamento è indicata in cima alla pagina." + }, + "contact": { + "heading": "Contatti", + "p1": "Per ogni richiesta legata a questa informativa o all'esercizio dei tuoi diritti puoi scrivere a carlo.santoleri@gmail.com. Cerchiamo di rispondere il prima possibile e comunque entro i termini di legge." + } + } + }, + "Terms": { + "metaTitle": "Termini di servizio — KetoPath", + "metaDescription": "Termini e condizioni d'uso dell'applicazione KetoPath: oggetto del servizio, account, abbonamento, recesso e responsabilità.", + "eyebrow": "Capitolo XI — Termini di servizio", + "title": "I termini, in chiaro", + "subtitle": "Queste sono le condizioni che regolano l'uso di KetoPath. Sono scritte in italiano semplice perché tu possa leggerle davvero. Iscrivendoti accetti questi termini insieme all'Informativa Privacy collegata.", + "sections": { + "object": { + "heading": "Oggetto del servizio", + "p1": "KetoPath è uno strumento di stile di vita pensato per accompagnarti in un percorso di alimentazione chetogenica e digiuno intermittente: piani alimentari personalizzati, lista della spesa automatica, tracking del peso e delle misure, timer per i protocolli di digiuno, suggerimenti progressivi sulle tre fasi (intensiva, transizione, mantenimento).", + "p2": "Il servizio è fornito da Carlo Santoleri (\"il titolare\") attraverso il sito lamiadieta.luzaonline.net. Iscrivendoti dichiari di aver letto e compreso questi termini e di accettarli integralmente." + }, + "noMedicalAdvice": { + "heading": "Non sostituisce il medico", + "p1": "KetoPath non è un dispositivo medico, non emette diagnosi e non prescrive trattamenti. Le indicazioni nutrizionali generate dall'app sono basate sui parametri che inserisci e su formule biometriche di letteratura: hanno valore informativo e di stile di vita, non valore sanitario.", + "p2": "Prima di iniziare un percorso chetogenico o di digiuno intermittente ti raccomandiamo di confrontarti con il tuo medico, in particolare se sei in gravidanza o allattamento, se hai diabete (di tipo 1 o di tipo 2 in terapia), patologie cardiache, renali o epatiche, disturbi del comportamento alimentare, oppure se assumi farmaci con dosaggio sensibile (es. ipoglicemizzanti, anticoagulanti, antipertensivi).", + "p3": "L'utente è l'unico responsabile dell'uso che fa delle informazioni fornite dall'app e delle decisioni alimentari conseguenti. In caso di sintomi inattesi sospendi l'uso del servizio e consulta un professionista." + }, + "account": { + "heading": "Account utente", + "p1": "Per usare il servizio devi avere almeno 18 anni e creare un account fornendo un indirizzo email valido oppure accedendo con Google. Sei responsabile della riservatezza delle credenziali e di ogni attività svolta tramite il tuo account.", + "p2": "Devi inserire dati veritieri: età, sesso, peso, altezza e livello di attività sono i parametri che alimentano i calcoli energetici dell'app. Dati errati produrranno piani non aderenti alle tue reali esigenze.", + "p3": "Puoi chiudere l'account in qualsiasi momento dalla pagina Profilo > Dati. La chiusura comporta la cessazione del servizio e l'avvio della procedura di cancellazione dei dati nei tempi descritti nell'Informativa Privacy." + }, + "trialAndSubscription": { + "heading": "Periodo di prova e abbonamento", + "p1": "KetoPath è disponibile gratuitamente per 30 giorni a partire dalla creazione dell'account. Durante questo periodo hai accesso a tutte le funzionalità della versione Pro senza alcun addebito e senza richiesta di carta di pagamento.", + "p2": "Al termine del periodo di prova, per continuare ad accedere alle funzionalità riservate (generazione e adattamento del piano settimanale, salvataggio illimitato dei tracking, esportazione PDF, lista della spesa avanzata), occorre sottoscrivere l'abbonamento Pro. Le funzionalità di base — visualizzazione del piano già generato, lettura dei tracking esistenti, contenuti informativi — restano disponibili anche senza sottoscrizione.", + "p3": "L'abbonamento Pro è offerto con cadenza mensile o annuale. Il prezzo vigente è indicato nella pagina di checkout al momento della sottoscrizione e può variare nel tempo per i nuovi sottoscrittori: per chi è già abbonato eventuali aumenti saranno comunicati con almeno 30 giorni di preavviso e potrai recedere prima della loro entrata in vigore.", + "p4": "L'abbonamento si rinnova automaticamente alla scadenza del periodo (mensile o annuale) salvo disdetta da effettuarsi entro la fine del periodo in corso direttamente dalla pagina Abbonamento." + }, + "paymentAndBilling": { + "heading": "Pagamento e fatturazione", + "p1": "I pagamenti sono gestiti da Stripe Payments Europe Limited. KetoPath non memorizza i dati della tua carta: vediamo soltanto l'identificativo cliente Stripe e gli ultimi quattro numeri della carta. Stripe accetta le principali carte di credito e debito.", + "p2": "Riceverai conferma del pagamento via email e, se richiedi fatturazione intestata, potrai inserire i tuoi dati fiscali direttamente nel portale clienti Stripe accessibile dalla pagina Abbonamento.", + "p3": "In caso di pagamento non riuscito (carta scaduta, fondi insufficienti, blocchi dell'emittente) Stripe ritenterà l'addebito per alcuni giorni. Trascorso questo periodo l'abbonamento entrerà in stato \"sospeso\" e l'accesso alle funzionalità Pro sarà temporaneamente disattivato finché il pagamento non sarà regolarizzato." + }, + "withdrawal": { + "heading": "Diritto di recesso", + "p1": "Ai sensi degli artt. 52 e seguenti del Codice del Consumo (D.Lgs. 206/2005) hai diritto di recedere senza fornire motivazioni entro 14 giorni dalla sottoscrizione dell'abbonamento Pro a pagamento.", + "p2": "Per esercitare il recesso è sufficiente comunicarcelo via email a carlo.santoleri@gmail.com indicando l'indirizzo email associato all'account. Provvederemo al rimborso del prezzo pagato entro 14 giorni dalla ricezione, utilizzando lo stesso strumento di pagamento.", + "p3": "Il periodo di prova gratuito di 30 giorni non comporta alcun addebito: per interromperlo è sufficiente non sottoscrivere l'abbonamento o chiudere l'account in qualunque momento, senza necessità di esercitare il recesso." + }, + "userObligations": { + "heading": "Obblighi e divieti", + "p1": "Devi usare il servizio in conformità alla legge e in buona fede. È vietato accedere all'account altrui, decompilare o reverse-engineering del software, aggirare i limiti tecnici, sovraccaricare i sistemi con automazioni non autorizzate.", + "p2": "È vietato caricare contenuti illeciti, lesivi della dignità altrui, pedopornografici, contrari all'ordine pubblico o protetti da diritti d'autore di terzi. Le foto progresso sono accessibili solo a te: non utilizzare il servizio come canale di pubblicazione.", + "p3": "È vietato utilizzare il servizio per fornire consulenze nutrizionali o sanitarie a terzi: KetoPath è uno strumento personale, non una piattaforma per professionisti.", + "p4": "Eventuali violazioni possono comportare la sospensione o la chiusura immediata dell'account, fermo restando il diritto al risarcimento dei danni e alla segnalazione alle autorità competenti." + }, + "ip": { + "heading": "Proprietà intellettuale", + "p1": "Il software KetoPath, il design dell'interfaccia, i testi editoriali, le ricette curate, gli algoritmi di calcolo e tutti i contenuti del servizio sono di proprietà del titolare o di chi gli ha concesso licenza, e sono protetti dalle leggi italiane ed europee sul diritto d'autore.", + "p2": "Con la sottoscrizione ti viene concessa una licenza personale, non esclusiva, non trasferibile e revocabile a usare il servizio per finalità non commerciali. Nessun contenuto può essere riprodotto, distribuito o utilizzato per addestrare modelli di intelligenza artificiale senza preventiva autorizzazione scritta." + }, + "userContent": { + "heading": "Contenuti generati dall'utente", + "p1": "I dati che inserisci nell'app (peso, misure, foto, sintomi, note) restano di tua proprietà. Concedi al titolare la licenza minima necessaria a erogarti il servizio: archiviarli, mostrarteli, generare statistiche personali, esportarli quando li richiedi.", + "p2": "Non utilizziamo i tuoi contenuti per scopi diversi dall'erogazione del servizio: nessuna pubblicità, nessuna cessione a terzi, nessun addestramento di modelli di intelligenza artificiale generativa." + }, + "serviceChanges": { + "heading": "Evoluzione del servizio", + "p1": "Il servizio è in continuo sviluppo: alcune funzionalità possono essere modificate, sostituite o rimosse. In caso di modifiche sostanziali che incidano sulle funzionalità incluse nell'abbonamento attivo ti avviseremo con almeno 30 giorni di preavviso.", + "p2": "Eventuali nuove funzionalità potranno essere offerte come parte dell'abbonamento esistente o come moduli aggiuntivi separati. Non sei mai obbligato ad accettarle." + }, + "termination": { + "heading": "Sospensione e cessazione", + "p1": "Il titolare può sospendere o chiudere l'account in caso di violazione di questi termini, di uso fraudolento del servizio o di mancato pagamento prolungato. Nei casi non urgenti riceverai un preavviso ragionevole con possibilità di rimediare.", + "p2": "Tu puoi chiudere l'account in qualsiasi momento dalla pagina Profilo > Dati. La chiusura non dà diritto al rimborso del periodo già pagato, salvo il caso del recesso entro 14 giorni descritto sopra." + }, + "liability": { + "heading": "Limitazione di responsabilità", + "p1": "Nei limiti consentiti dalla legge, il titolare non risponde dei danni indiretti, di lucro cessante, di perdita di dati o di occasione, derivanti dall'uso o dall'impossibilità di uso del servizio.", + "p2": "In ogni caso la responsabilità complessiva del titolare per danni diretti non potrà superare l'importo effettivamente pagato dall'utente nei 12 mesi precedenti l'evento dannoso, salvi i casi di dolo o colpa grave.", + "p3": "Nessuna clausola di questi termini esclude o limita la responsabilità per danni alla persona derivanti dalla violazione di diritti inderogabili previsti dalla legge italiana, in particolare in materia di consumatori (D.Lgs. 206/2005)." + }, + "forceMajeure": { + "heading": "Forza maggiore", + "p1": "Non rispondiamo dei mancati adempimenti dovuti a cause di forza maggiore o caso fortuito, ivi compresi guasti dei provider di hosting, interruzioni di rete, attacchi informatici massivi, provvedimenti delle autorità, calamità naturali, scioperi generali." + }, + "governingLaw": { + "heading": "Legge applicabile e foro", + "p1": "Questi termini sono regolati dalla legge italiana. Per ogni controversia relativa all'interpretazione e all'esecuzione del contratto è competente in via esclusiva il foro del consumatore individuato dal D.Lgs. 206/2005, ovvero il foro del luogo di residenza o domicilio dell'utente, se ubicato in Italia.", + "p2": "Prima di adire l'autorità giudiziaria ti incoraggiamo a contattarci via email per cercare una soluzione bonaria. È inoltre disponibile la piattaforma europea ODR (Online Dispute Resolution) all'indirizzo ec.europa.eu/consumers/odr." + }, + "changes": { + "heading": "Modifiche ai termini", + "p1": "Possiamo aggiornare questi termini per ragioni operative, normative o di sicurezza. In caso di modifiche sostanziali ti avviseremo via email o con un avviso visibile in app almeno 15 giorni prima dell'entrata in vigore. La prosecuzione dell'uso del servizio dopo l'entrata in vigore vale come accettazione; in caso contrario puoi recedere senza costi." + }, + "contact": { + "heading": "Contatti", + "p1": "Per qualsiasi domanda su questi termini o per esercitare i tuoi diritti puoi scrivere a carlo.santoleri@gmail.com." + } + } + } } } diff --git a/apps/web/src/app/[locale]/(auth)/sign-in/page.tsx b/apps/web/src/app/[locale]/(auth)/sign-in/page.tsx index 49b87d8..f1e4f4a 100644 --- a/apps/web/src/app/[locale]/(auth)/sign-in/page.tsx +++ b/apps/web/src/app/[locale]/(auth)/sign-in/page.tsx @@ -53,6 +53,26 @@ export default function SignInPage({ params: { locale } }: { params: { locale: s ), })}

+

+ {t.rich('legalNote', { + terms: (chunks) => ( + + {chunks} + + ), + privacy: (chunks) => ( + + {chunks} + + ), + })} +

diff --git a/apps/web/src/app/[locale]/(auth)/sign-up/page.tsx b/apps/web/src/app/[locale]/(auth)/sign-up/page.tsx index 0e4d349..7c87f8b 100644 --- a/apps/web/src/app/[locale]/(auth)/sign-up/page.tsx +++ b/apps/web/src/app/[locale]/(auth)/sign-up/page.tsx @@ -41,7 +41,24 @@ export default function SignUpPage({ params: { locale } }: { params: { locale: s

{t('title')}

- {t('disclaimer')} + {t.rich('disclaimer', { + terms: (chunks) => ( + + {chunks} + + ), + privacy: (chunks) => ( + + {chunks} + + ), + })}

{t.rich('haveAccount', { diff --git a/apps/web/src/app/[locale]/legal/privacy/page.tsx b/apps/web/src/app/[locale]/legal/privacy/page.tsx new file mode 100644 index 0000000..ba9b0cb --- /dev/null +++ b/apps/web/src/app/[locale]/legal/privacy/page.tsx @@ -0,0 +1,181 @@ +import type { Metadata } from 'next'; +import Link from 'next/link'; +import { useTranslations } from 'next-intl'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; + +import { Masthead } from '@/components/masthead'; + +const LAST_UPDATED_ISO = '2026-05-20'; + +export async function generateMetadata({ + params: { locale }, +}: { + params: { locale: string }; +}): Promise { + const t = await getTranslations({ locale, namespace: 'Legal.Privacy' }); + return { + title: t('metaTitle'), + description: t('metaDescription'), + robots: { index: true, follow: true }, + }; +} + +export default function PrivacyPage({ params: { locale } }: { params: { locale: string } }) { + setRequestLocale(locale); + return ; +} + +function PrivacyContent() { + const t = useTranslations('Legal.Privacy'); + const tShared = useTranslations('Legal.Shared'); + const lastUpdated = new Intl.DateTimeFormat('it-IT', { + day: 'numeric', + month: 'long', + year: 'numeric', + }).format(new Date(`${LAST_UPDATED_ISO}T00:00:00`)); + + return ( +

+
+ +
+ + X + + +

{t('eyebrow')}

+

+ + {t('title')} + . + +

+

+ {t('subtitle')} +

+

+ {tShared('lastUpdated', { date: lastUpdated })} +

+ +
+ + {/* TOC + corpo */} +
+ + +
+ {SECTIONS.map((s, i) => ( +
+ ))} +
+
+ +
+ + {/* Quick links bottom */} + +
+
+
+
+ ); +} + +interface SectionDef { + id: + | 'controller' + | 'dataCollected' + | 'healthData' + | 'purposes' + | 'legalBasis' + | 'recipients' + | 'transfers' + | 'retention' + | 'security' + | 'rights' + | 'minors' + | 'cookies' + | 'changes' + | 'contact'; + /** Numero di paragrafi tradotti come `sections..p1`, `p2`, ... */ + body: number; +} + +const SECTIONS: ReadonlyArray = [ + { id: 'controller', body: 2 }, + { id: 'dataCollected', body: 5 }, + { id: 'healthData', body: 2 }, + { id: 'purposes', body: 4 }, + { id: 'legalBasis', body: 3 }, + { id: 'recipients', body: 6 }, + { id: 'transfers', body: 2 }, + { id: 'retention', body: 3 }, + { id: 'security', body: 2 }, + { id: 'rights', body: 3 }, + { id: 'minors', body: 1 }, + { id: 'cookies', body: 2 }, + { id: 'changes', body: 1 }, + { id: 'contact', body: 1 }, +]; + +function Section({ id, index, body }: { id: SectionDef['id']; index: number; body: number }) { + const t = useTranslations('Legal.Privacy'); + return ( +
+
+ + {String(index).padStart(2, '0')} + +

+ {t(`sections.${id}.heading` as never)} +

+
+
+ {Array.from({ length: body }).map((_, i) => ( +

+ {t(`sections.${id}.p${i + 1}` as never)} +

+ ))} +
+
+ ); +} diff --git a/apps/web/src/app/[locale]/legal/terms/page.tsx b/apps/web/src/app/[locale]/legal/terms/page.tsx new file mode 100644 index 0000000..fdd51c1 --- /dev/null +++ b/apps/web/src/app/[locale]/legal/terms/page.tsx @@ -0,0 +1,182 @@ +import type { Metadata } from 'next'; +import Link from 'next/link'; +import { useTranslations } from 'next-intl'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; + +import { Masthead } from '@/components/masthead'; + +const LAST_UPDATED_ISO = '2026-05-20'; + +export async function generateMetadata({ + params: { locale }, +}: { + params: { locale: string }; +}): Promise { + const t = await getTranslations({ locale, namespace: 'Legal.Terms' }); + return { + title: t('metaTitle'), + description: t('metaDescription'), + robots: { index: true, follow: true }, + }; +} + +export default function TermsPage({ params: { locale } }: { params: { locale: string } }) { + setRequestLocale(locale); + return ; +} + +function TermsContent() { + const t = useTranslations('Legal.Terms'); + const tShared = useTranslations('Legal.Shared'); + const lastUpdated = new Intl.DateTimeFormat('it-IT', { + day: 'numeric', + month: 'long', + year: 'numeric', + }).format(new Date(`${LAST_UPDATED_ISO}T00:00:00`)); + + return ( +
+
+ +
+ + XI + + +

{t('eyebrow')}

+

+ + {t('title')} + . + +

+

+ {t('subtitle')} +

+

+ {tShared('lastUpdated', { date: lastUpdated })} +

+ +
+ +
+ + +
+ {SECTIONS.map((s, i) => ( +
+ ))} +
+
+ +
+ + +
+
+
+
+ ); +} + +interface SectionDef { + id: + | 'object' + | 'noMedicalAdvice' + | 'account' + | 'trialAndSubscription' + | 'paymentAndBilling' + | 'withdrawal' + | 'userObligations' + | 'ip' + | 'userContent' + | 'serviceChanges' + | 'termination' + | 'liability' + | 'forceMajeure' + | 'governingLaw' + | 'changes' + | 'contact'; + body: number; +} + +const SECTIONS: ReadonlyArray = [ + { id: 'object', body: 2 }, + { id: 'noMedicalAdvice', body: 3 }, + { id: 'account', body: 3 }, + { id: 'trialAndSubscription', body: 4 }, + { id: 'paymentAndBilling', body: 3 }, + { id: 'withdrawal', body: 3 }, + { id: 'userObligations', body: 4 }, + { id: 'ip', body: 2 }, + { id: 'userContent', body: 2 }, + { id: 'serviceChanges', body: 2 }, + { id: 'termination', body: 2 }, + { id: 'liability', body: 3 }, + { id: 'forceMajeure', body: 1 }, + { id: 'governingLaw', body: 2 }, + { id: 'changes', body: 1 }, + { id: 'contact', body: 1 }, +]; + +function Section({ id, index, body }: { id: SectionDef['id']; index: number; body: number }) { + const t = useTranslations('Legal.Terms'); + return ( +
+
+ + {String(index).padStart(2, '0')} + +

+ {t(`sections.${id}.heading` as never)} +

+
+
+ {Array.from({ length: body }).map((_, i) => ( +

+ {t(`sections.${id}.p${i + 1}` as never)} +

+ ))} +
+
+ ); +} diff --git a/apps/web/src/app/[locale]/page.tsx b/apps/web/src/app/[locale]/page.tsx index 4071eae..b224e5b 100644 --- a/apps/web/src/app/[locale]/page.tsx +++ b/apps/web/src/app/[locale]/page.tsx @@ -806,9 +806,23 @@ function Disclaimer() {

{t('disclaimer')}

-

- {t('footerCopyright')} -

+
+
    +
  • + + {t('footerLinkPrivacy')} + +
  • +
  • + + {t('footerLinkTerms')} + +
  • +
+

+ {t('footerCopyright')} +

+
); } diff --git a/apps/web/src/app/[locale]/welcome/page.tsx b/apps/web/src/app/[locale]/welcome/page.tsx index 8c10649..5960d8d 100644 --- a/apps/web/src/app/[locale]/welcome/page.tsx +++ b/apps/web/src/app/[locale]/welcome/page.tsx @@ -1,4 +1,5 @@ import { prisma } from '@ketopath/db'; +import Link from 'next/link'; import { redirect } from 'next/navigation'; import { useTranslations } from 'next-intl'; import { setRequestLocale } from 'next-intl/server'; @@ -64,6 +65,24 @@ function WelcomePageContent() {

{t('legalNote')}

+
    +
  • + + → Informativa Privacy + +
  • +
  • + + → Termini di servizio + +
  • +
); diff --git a/apps/web/src/components/cookie-banner.tsx b/apps/web/src/components/cookie-banner.tsx index 6a66995..1b4485a 100644 --- a/apps/web/src/components/cookie-banner.tsx +++ b/apps/web/src/components/cookie-banner.tsx @@ -1,5 +1,6 @@ 'use client'; +import Link from 'next/link'; import { useTranslations } from 'next-intl'; import { useEffect, useState } from 'react'; @@ -34,7 +35,13 @@ export function CookieBanner() {

Privacy - {t('message')} + {t('message')}{' '} + + {t('learnMore')} +