fix: :necktie: Improve consent step on sign up with Google
Tim Izzo tim@5ika.ch
Thu, 12 Dec 2024 17:01:24 +0100
4 files changed,
67 insertions(+),
26 deletions(-)
M
frontend/layouts/ConfirmLayout.tsx
→
frontend/layouts/ConfirmLayout.tsx
@@ -1,22 +1,17 @@
import Card from '@mui/material/Card'; -import {useTheme} from '@mui/material/styles'; import CardMedia from '@mui/material/CardMedia'; import CardContent from '@mui/material/CardContent'; import Layout from './Centered'; import Logo from '../components/Logo'; const CommonConfirm = ({children}) => { - const theme = useTheme(); return ( <Layout displayMenu={false}> <Card> <CardMedia component={Logo} /> <CardContent sx={{ - padding: theme.spacing(0, 8), - '&:last-child': { - paddingBottom: theme.spacing(12), - }, + px: 4, }} > {children}
M
frontend/pages/api/nauth/[...nextauth].js
→
frontend/pages/api/nauth/[...nextauth].js
@@ -61,10 +61,9 @@
token.id = data.user.id; token.jwt = data.jwt; token.email = data.user.email; - token.username = data.user.firstname; + token.username = data.user.name; token.lang = data.user.lang?.toLowerCase(); token.provider = account.provider; - token.userCreatedAt = data.user.createdAt; } // Strapi Auth@@ -75,7 +74,6 @@ token.email = user.email;
token.username = user.firstname; token.lang = user.lang?.toLowerCase(); token.provider = account.provider; - token.userCreatedAt = user.createdAt; } return token;@@ -83,6 +81,19 @@ },
session: async params => { const {session, token} = params; if (session) { + try { + const response = await fetch(`${STRAPI_URL}/api/users/me`, { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token.jwt}`, + }, + }); + const profile = await response.json(); + session.profile = profile; + } catch (error) { + console.error(error); + } + session.token = token; session.user.name = token.username; session.user.lang = token.lang;
M
frontend/pages/auth/confirm/google.tsx
→
frontend/pages/auth/confirm/google.tsx
@@ -1,34 +1,50 @@
import Typography from '@mui/material/Typography'; -import {useTheme} from '@mui/material/styles'; -import Icon from '@mui/material/Icon'; import FormControlLabel from '@mui/material/FormControlLabel'; import Checkbox from '@mui/material/Checkbox'; import Button from '@mui/material/Button'; import Box from '@mui/material/Box'; import {useTranslation, Trans} from 'next-i18next'; -import {useState} from 'react'; +import {useMemo, useState} from 'react'; import pageUtils from '../../../lib/pageUtils'; import CommonConfirm from '../../../layouts/ConfirmLayout'; import {useUpdateMeMutation} from '../../../generated/graphql'; -import router from 'next/router'; import useSettings from '../../../hooks/useSettings'; import moment from 'moment'; +import {useSession} from 'next-auth/react'; +import {TextField, useMediaQuery} from '@mui/material'; +import {useTheme} from '@mui/styles'; const Confirm = () => { - const theme = useTheme(); const {t} = useTranslation(); const settings = useSettings(); const [updateMe] = useUpdateMeMutation(); + const session = useSession(); + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const sessionNames = session?.data?.token?.name?.split(' ') || ['', '']; + const [firstname, setFirstname] = useState(sessionNames[0]); + const [lastname, setLastname] = useState(sessionNames[1]); const [newsletterConsent, setNewsletterConsent] = useState(false); const [tosConsent, setTosConsent] = useState(false); + const canConfirm = useMemo( + () => firstname?.length > 1 && lastname?.length > 1 && tosConsent, + [firstname, lastname, tosConsent] + ); const onSubmit = async () => { const tosAcceptationDate = tosConsent ? moment().toISOString() : null; await updateMe({ - variables: {userUpdate: {newsletterConsent, tosAcceptationDate}}, + variables: { + userUpdate: { + newsletterConsent, + tosAcceptationDate, + firstName: firstname, + lastName: lastname, + }, + }, }); - router.push('/dashboard'); + window.location.href = '/dashboard'; }; return (@@ -39,9 +55,30 @@ </Typography>
<Typography variant="h5" align="center"> {t('confirm.google.title')} </Typography> - <Typography align="center" sx={{margin: theme.spacing(5, 0)}}> - <Icon fontSize="large">mail</Icon> - </Typography> + <Box + mt={3} + mb={2} + display="flex" + gap={2} + flexDirection={isMobile ? 'column' : 'row'} + > + <TextField + label={t`signup.firstName`} + variant="outlined" + size="small" + value={firstname} + onChange={e => setFirstname(e.target.value)} + fullWidth + /> + <TextField + label={t`signup.lastName`} + variant="outlined" + size="small" + value={lastname} + onChange={e => setLastname(e.target.value)} + fullWidth + /> + </Box> <FormControlLabel sx={{width: '100%', my: 2, mx: 0}} control={@@ -57,7 +94,7 @@ }
label={t('signup.newsletter.consent')} /> <FormControlLabel - sx={{width: '100%', my: 2, mx: 0}} + sx={{width: '100%', mx: 0}} label={ <Trans i18nKey="signup.tos.consent"@@ -82,7 +119,7 @@ <Button
variant="contained" color="secondary" onClick={onSubmit} - disabled={!tosConsent} + disabled={!canConfirm} > {t('generic.confirm')} </Button>
M
frontend/pages/dashboard.tsx
→
frontend/pages/dashboard.tsx
@@ -110,12 +110,10 @@ permanent: false,
}, }; - const {provider, userCreatedAt} = session?.token || {}; - const isFirstLogin = userCreatedAt - ? moment().subtract({seconds: 3}).isBefore(userCreatedAt) - : false; + const provider = session?.token?.provider; + const hasAcceptedTos = !!session?.profile?.tosAcceptationDate; - if (provider === 'google' && isFirstLogin) + if (provider === 'google' && !hasAcceptedTos) return { redirect: { destination: '/auth/confirm/google',