Add terms and conditions checkbox to sign-up methods (#45)

A checkbox has been added for user acceptance of terms and conditions during sign-up. This change includes adding a new adjustable flag in the configuration to control the display of the checkbox. A new file "terms-and-conditions-form-field.tsx" is added to handle the checkbox UI part. Also, localization support has been added for the feature.
This commit is contained in:
Giancarlo Buomprisco
2024-07-12 14:32:02 +08:00
committed by GitHub
parent 3393863dd2
commit a75f7c576d
8 changed files with 96 additions and 1 deletions

View File

@@ -44,6 +44,7 @@ function SignUpPage({ searchParams }: Props) {
<SignUpMethodsContainer
providers={authConfig.providers}
displayTermsCheckbox={authConfig.displayTermsCheckbox}
inviteToken={inviteToken}
paths={paths}
/>

View File

@@ -5,7 +5,16 @@ import { z } from 'zod';
const providers: z.ZodType<Provider> = getProviders();
const AuthConfigSchema = z.object({
captchaTokenSiteKey: z.string().optional(),
captchaTokenSiteKey: z
.string({
description: 'The reCAPTCHA site key.',
})
.optional(),
displayTermsCheckbox: z
.boolean({
description: 'Whether to display the terms checkbox during sign-up.',
})
.optional(),
providers: z.object({
password: z.boolean({
description: 'Enable password authentication.',
@@ -22,6 +31,10 @@ const authConfig = AuthConfigSchema.parse({
// Copy the value from the Supabase Dashboard.
captchaTokenSiteKey: process.env.NEXT_PUBLIC_CAPTCHA_SITE_KEY,
// whether to display the terms checkbox during sign-up
displayTermsCheckbox:
process.env.NEXT_PUBLIC_DISPLAY_TERMS_AND_CONDITIONS_CHECKBOX === 'true',
// NB: Enable the providers below in the Supabase Console
// in your production project
providers: {

View File

@@ -61,6 +61,9 @@
"emailPlaceholder": "your@email.com",
"inviteAlertHeading": "You have been invited to join a team",
"inviteAlertBody": "Please sign in or sign up to accept the invite and join the team.",
"acceptTermsAndConditions": "I accept the <TermsOfServiceLink /> and <PrivacyPolicyLink />",
"termsOfService": "Terms of Service",
"privacyPolicy": "Privacy Policy",
"errors": {
"Invalid login credentials": "The credentials entered are invalid",
"User already registered": "This credential is already in use. Please try with another one.",

View File

@@ -23,16 +23,20 @@ import { Input } from '@kit/ui/input';
import { Trans } from '@kit/ui/trans';
import { useCaptchaToken } from '../captcha/client';
import { TermsAndConditionsFormField } from './terms-and-conditions-form-field';
export function MagicLinkAuthContainer({
inviteToken,
redirectUrl,
shouldCreateUser,
defaultValues,
displayTermsCheckbox,
}: {
inviteToken?: string;
redirectUrl: string;
shouldCreateUser: boolean;
displayTermsCheckbox?: boolean;
defaultValues?: {
email: string;
};
@@ -115,6 +119,10 @@ export function MagicLinkAuthContainer({
name={'email'}
/>
<If condition={displayTermsCheckbox}>
<TermsAndConditionsFormField />
</If>
<Button disabled={signInWithOtpMutation.isPending}>
<If
condition={signInWithOtpMutation.isPending}

View File

@@ -14,6 +14,7 @@ import { AuthErrorAlert } from './auth-error-alert';
import { PasswordSignUpForm } from './password-sign-up-form';
interface EmailPasswordSignUpContainerProps {
displayTermsCheckbox?: boolean;
defaultValues?: {
email: string;
};
@@ -26,6 +27,7 @@ export function EmailPasswordSignUpContainer({
defaultValues,
onSignUp,
emailRedirectTo,
displayTermsCheckbox
}: EmailPasswordSignUpContainerProps) {
const { captchaToken, resetCaptchaToken } = useCaptchaToken();
@@ -81,6 +83,7 @@ export function EmailPasswordSignUpContainer({
onSubmit={onSignupRequested}
loading={loading}
defaultValues={defaultValues}
displayTermsCheckbox={displayTermsCheckbox}
/>
</If>
</>

View File

@@ -20,9 +20,11 @@ import { Input } from '@kit/ui/input';
import { Trans } from '@kit/ui/trans';
import { PasswordSignUpSchema } from '../schemas/password-sign-up.schema';
import { TermsAndConditionsFormField } from './terms-and-conditions-form-field';
export function PasswordSignUpForm({
defaultValues,
displayTermsCheckbox,
onSubmit,
loading,
}: {
@@ -30,6 +32,8 @@ export function PasswordSignUpForm({
email: string;
};
displayTermsCheckbox?: boolean;
onSubmit: (params: {
email: string;
password: string;
@@ -130,6 +134,10 @@ export function PasswordSignUpForm({
)}
/>
<If condition={displayTermsCheckbox}>
<TermsAndConditionsFormField />
</If>
<Button
data-test={'auth-submit-button'}
className={'w-full'}

View File

@@ -24,6 +24,7 @@ export function SignUpMethodsContainer(props: {
oAuth: Provider[];
};
displayTermsCheckbox?: boolean;
inviteToken?: string;
}) {
const redirectUrl = getCallbackUrl(props);
@@ -39,6 +40,7 @@ export function SignUpMethodsContainer(props: {
<EmailPasswordSignUpContainer
emailRedirectTo={redirectUrl}
defaultValues={defaultValues}
displayTermsCheckbox={props.displayTermsCheckbox}
/>
</If>
@@ -48,6 +50,7 @@ export function SignUpMethodsContainer(props: {
redirectUrl={redirectUrl}
shouldCreateUser={true}
defaultValues={defaultValues}
displayTermsCheckbox={props.displayTermsCheckbox}
/>
</If>

View File

@@ -0,0 +1,56 @@
import Link from 'next/link';
import { Checkbox } from '@kit/ui/checkbox';
import { FormControl, FormField, FormItem, FormMessage } from '@kit/ui/form';
import { Trans } from '@kit/ui/trans';
export function TermsAndConditionsFormField(
props: {
name?: string;
} = {},
) {
return (
<FormField
name={props.name ?? 'termsAccepted'}
render={({ field }) => {
return (
<FormItem>
<FormControl>
<label className={'flex items-start space-x-2 py-2'}>
<Checkbox required name={field.name} />
<div className={'text-xs'}>
<Trans
i18nKey={'auth:acceptTermsAndConditions'}
components={{
TermsOfServiceLink: (
<Link
target={'_blank'}
className={'underline'}
href={'/terms-of-service'}
>
<Trans i18nKey={'auth:termsOfService'} />
</Link>
),
PrivacyPolicyLink: (
<Link
target={'_blank'}
className={'underline'}
href={'/privacy-policy'}
>
<Trans i18nKey={'auth:privacyPolicy'} />
</Link>
),
}}
/>
</div>
</label>
</FormControl>
<FormMessage />
</FormItem>
);
}}
/>
);
}