feat: :sparkles: Add TOS acceptation for anonymous users #567
Tim Izzo tim@octree.ch
Wed, 15 Jan 2025 15:36:33 +0100
8 files changed,
86 insertions(+),
2 deletions(-)
A
frontend/containers/TOSDialog/index.tsx
@@ -0,0 +1,71 @@
+import { + Box, + Button, + Checkbox, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Typography, +} from '@mui/material'; +import {useSession} from 'next-auth/react'; +import {useEffect, useReducer, useState} from 'react'; +import {useTranslation, Trans} from 'next-i18next'; +import useSettings from '../../hooks/useSettings'; + +const STORAGE_KEY = 'TOS_ACCEPTED'; + +const TOSDialog = () => { + const {t} = useTranslation(); + const settings = useSettings(); + const session = useSession(); + const [accepted, setAccepted] = useState(false); + const [showDialog, toggleDialog] = useReducer(i => !i, false); + + const onConfirm = () => { + toggleDialog(); + localStorage.setItem(STORAGE_KEY, new Date().toISOString()); + }; + + useEffect(() => { + if (!localStorage.getItem(STORAGE_KEY)) toggleDialog(); + }, []); + + if (session.status !== 'unauthenticated') return null; + + return ( + <Dialog open={showDialog} fullWidth maxWidth="xs"> + <DialogTitle>{t`signup.tos.title`}</DialogTitle> + <DialogContent> + <Box display="flex" justifyContent="space-between" gap={4}> + <Typography> + <Trans + i18nKey="signup.tos.consent" + components={{ + 'tos-link': <a href={settings.tos_link} target="_blank" />, + 'data-privacy-link': ( + <a href={settings.tos_link} target="_blank" /> + ), + }} + /> + </Typography> + <Checkbox + checked={accepted} + onChange={e => setAccepted(e.target.checked)} + /> + </Box> + </DialogContent> + <DialogActions> + <Button + variant="contained" + color="primary" + disabled={!accepted} + onClick={onConfirm} + fullWidth + >{t`signup.tos.button`}</Button> + </DialogActions> + </Dialog> + ); +}; + +export default TOSDialog;
M
frontend/layouts/Event.tsx
→
frontend/layouts/Event.tsx
@@ -14,6 +14,7 @@ Event as EventType,
useEventByUuidQuery, Module, } from '../generated/graphql'; +import TOSDialog from '../containers/TOSDialog'; const POLL_INTERVAL = 10000;@@ -105,6 +106,7 @@ event={event}
open={isAddToMyEvent} onClose={() => setIsAddToMyEvent(false)} /> + <TOSDialog /> </Layout> ); };
M
frontend/locales/de.json
→
frontend/locales/de.json
@@ -251,6 +251,8 @@ "travel.creation.travel.titleHelper": "Bitte geben Sie einen gültigen Namen an",
"travel.passengers.email_placeholder": "E-Mail", "travel.requestTrip.description": "Die folgenden Informationen werden dem Fahrer der Fahrt zugeschickt.", "signup.newsletter.consent": "Ich interessiere mich für Fahrgemeinschaften, ich möchte den Newsletter abonnieren.", + "signup.tos.title": "Nutzungsbedingungen", "signup.tos.consent": "Ich akzeptiere <tos-link>Nutzungsbedingungen</tos-link> und <data-privacy-link>Datenschutzbestimmungen</data-privacy-link>", + "signup.tos.button": "Beginnen Sie mit der Nutzung von Caroster", "meta.description": "Caroster Bilden Sie bei der Veranstaltung Fahrgemeinschaften, indem Sie ein Auto anbieten oder einen Platz einnehmen." }
M
frontend/locales/en.json
→
frontend/locales/en.json
@@ -210,7 +210,9 @@ "signup.create": "Create an account",
"signup.firstName": "Firstname", "signup.lastName": "lastname", "signup.newsletter.consent": "I am interested in carpooling, I want to subscribe to the newsletter.", + "signup.tos.title": "Terms of service", "signup.tos.consent": "I accept <tos-link>terms of service</tos-link> and <data-privacy-link>data privacy policy</data-privacy-link>", + "signup.tos.button": "Start using Caroster", "supportCaroster": "Support Caroster", "travel.actions.remove_alert": "Are you sure you want to remove this trip and add the subscribers to the waiting list?", "travel.actions.remove_alert.caroster_plus": "Are you sure you want to remove this trip? Passengers will be notified.",
M
frontend/locales/fr.json
→
frontend/locales/fr.json
@@ -206,7 +206,9 @@ "signup.create": "Créer un compte",
"signup.firstName": "Prénom", "signup.lastName": "Nom", "signup.newsletter.consent": "Le covoiturage m'intéresse, je souhaite recevoir des nouvelles de Caroster", + "signup.tos.title": "Conditions d'utilisation", "signup.tos.consent": "J'accepte les <tos-link>conditions d'utilisation</tos-link> et la <data-privacy-link>politique de gestion de données</data-privacy-link>", + "signup.tos.button": "Commencer à utiliser Caroster", "supportCaroster": "Soutenir Caroster", "travel.actions.remove_alert": "Voulez-vous vraiment supprimer ce trajet et ajouter les inscrits à la liste d'attente ?", "travel.actions.remove_alert.caroster_plus": "Voulez-vous vraiment supprimer ce trajet ? Les inscrits seront avertis.",
M
frontend/locales/it.json
→
frontend/locales/it.json
@@ -248,7 +248,9 @@ "passenger.assign.seats": "{{count}} posti disponibili",
"passenger.assign.title": "Assegna un passeggero", "passenger.errors.cant_add_passenger": "Impossibile aggiungere un passeggero", "profile.new_password": "Nuova password", + "signup.tos.title": "Condizioni del servizio", "signup.tos.consent": "Accetto le <tos-link>condizioni del servizio</tos-link> e la <data-privacy-link>politica sul trattamento dei dati</data-privacy-link>", + "signup.tos.button": "Inizia a usare Caroster", "travel.errors.cant_remove_passenger": "Impossibile rimuovere passeggero", "travel.removePassengerModal.plus.self.description": "Dove trovare un altro passaggio.", "event.errors.cant_create": "Impossibile creare l'evento",
M
frontend/locales/nl.json
→
frontend/locales/nl.json
@@ -187,7 +187,9 @@ "signup.email": "E-mailadres",
"signup.firstName": "Voornaam", "signup.lastName": "Achternaam", "signup.newsletter.consent": "Ik ben geïnteresseerd in carpooling en wil me abonneren op de nieuwsbrief.", + "signup.tos.title": "Algemene voorwaarden", "signup.tos.consent": "Ik ga akkoord met de <tos-link>algemene voorwaarden</tos-link> en het <data-privacy-link>privacybeleid</data-privacy-link>", + "signup.tos.button": "Begin met het gebruiken van Caroster", "supportCaroster": "Doneren", "travel.actions.remove_alert": "Weet u zeker dat u dit voertuig wilt verwijderen en daardoor de passagiers wilt toevoegen aan de wachtlijst?", "travel.actions.remove_alert.caroster_plus": "Weet u zeker dat u dit voertuig wilt verwijderen? Alle passagiers worden hiervan op de hoogte gesteld.",
M
frontend/pages/e/[uuid]/index.tsx
→
frontend/pages/e/[uuid]/index.tsx
@@ -22,8 +22,9 @@ const {host = ''} = context.req.headers;
const session = await getSession(context); let event = null; - const hasAcceptedTos = !!session?.profile?.tosAcceptationDate; - if (!hasAcceptedTos) + const userHasNotAcceptedTos = + !!session?.profile && !session.profile.tosAcceptationDate; + if (userHasNotAcceptedTos) return { redirect: { destination: '/auth/confirm',