Localized signup and login

This commit is contained in:
Justin Edmund 2022-03-05 13:24:39 -08:00
parent 269152ee58
commit d79a13dc8a
4 changed files with 121 additions and 27 deletions

View file

@ -1,5 +1,6 @@
import React, { useState } from 'react'
import { useCookies } from 'react-cookie'
import { useTranslation } from 'react-i18next'
import { AxiosResponse } from 'axios'
import * as Dialog from '@radix-ui/react-dialog'
@ -24,6 +25,8 @@ interface ErrorMap {
const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
const LoginModal = (props: Props) => {
const { t } = useTranslation('common')
// Set up form states and error handling
const [formValid, setFormValid] = useState(false)
const [errors, setErrors] = useState<ErrorMap>({
@ -49,16 +52,16 @@ const LoginModal = (props: Props) => {
switch(name) {
case 'email':
if (value.length == 0)
newErrors.email = 'Please enter your email'
newErrors.email = t('modals.login.errors.empty_email')
else if (!emailRegex.test(value))
newErrors.email = 'That email address is not valid'
newErrors.email = t('modals.login.errors.invalid_email')
else
newErrors.email = ''
break
case 'password':
newErrors.password = value.length == 0
? 'Please enter your password'
? t('modals.login.errors.empty_password')
: ''
break
@ -117,21 +120,22 @@ const LoginModal = (props: Props) => {
access_token: response.data.access_token
}
setCookies('account', cookieObj, { path: '/'})
setCookies('account', cookieObj, { path: '/' })
}
function storeUserInfo(response: AxiosResponse) {
const user = response.data.user
setCookies('NEXT_LOCALE', user.language, { path: '/' })
const cookieObj = {
picture: user.picture.picture,
element: user.picture.element,
language: user.language,
}
setCookies('user', cookieObj, { path: '/'})
setCookies('user', cookieObj, { path: '/' })
accountState.account.language = user.language
accountState.account.user = {
id: user.id,
username: user.username,
@ -155,13 +159,13 @@ const LoginModal = (props: Props) => {
<Dialog.Root open={open} onOpenChange={openChange}>
<Dialog.Trigger asChild>
<li className="MenuItem">
<span>Log in</span>
<span>{t('menu.login')}</span>
</li>
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Content className="Login Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
<div className="DialogHeader">
<Dialog.Title className="DialogTitle">Log in</Dialog.Title>
<Dialog.Title className="DialogTitle">{t('modals.login.title')}</Dialog.Title>
<Dialog.Close className="DialogClose" asChild>
<span>
<CrossIcon />
@ -172,7 +176,7 @@ const LoginModal = (props: Props) => {
<form className="form" onSubmit={login}>
<Fieldset
fieldName="email"
placeholder="Email address"
placeholder={t('modals.login.placeholders.email')}
onChange={handleChange}
error={errors.email}
ref={emailInput}
@ -180,13 +184,13 @@ const LoginModal = (props: Props) => {
<Fieldset
fieldName="password"
placeholder="Password"
placeholder={t('modals.login.placeholders.password')}
onChange={handleChange}
error={errors.password}
ref={passwordInput}
/>
<Button>Log in</Button>
<Button>{t('modals.login.buttons.confirm')}</Button>
</form>
</Dialog.Content>
<Dialog.Overlay className="Overlay" />

View file

@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'
import { useCookies } from 'react-cookie'
import { Trans, useTranslation } from 'next-i18next'
import { AxiosResponse } from 'axios'
import * as Dialog from '@radix-ui/react-dialog'
@ -26,6 +27,8 @@ interface ErrorMap {
const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
const SignupModal = (props: Props) => {
const { t } = useTranslation('common')
// Set up form states and error handling
const [formValid, setFormValid] = useState(false)
const [errors, setErrors] = useState<ErrorMap>({
@ -95,9 +98,9 @@ const SignupModal = (props: Props) => {
language: user.language,
}
// TODO: Set language
setCookies('user', cookieObj, { path: '/'})
accountState.account.language = user.language
accountState.account.user = {
id: user.id,
username: user.username,
@ -138,7 +141,7 @@ const SignupModal = (props: Props) => {
validateName(fieldName, value)
} else {
newErrors[fieldName] = `This ${fieldName} is already in use`
newErrors[fieldName] = t('modals.signup.errors.field_in_use', { field: fieldName})
setErrors(newErrors)
setFormValid(false)
}
@ -150,9 +153,9 @@ const SignupModal = (props: Props) => {
switch(fieldName) {
case 'username':
if (value.length < 3)
newErrors.username = 'Username must be at least 3 characters'
newErrors.username = t('modals.signup.errors.username_too_short')
else if (value.length > 20)
newErrors.username = 'Username must be less than 20 characters'
newErrors.username = t('modals.signup.errors.username_too_long')
else
newErrors.username = ''
@ -161,7 +164,7 @@ const SignupModal = (props: Props) => {
case 'email':
newErrors.email = emailRegex.test(value)
? ''
: 'That email address is not valid'
: t('modals.signup.errors.invalid_email')
break
default:
@ -180,20 +183,20 @@ const SignupModal = (props: Props) => {
switch(name) {
case 'password':
newErrors.password = passwordInput.current?.value.includes(usernameInput.current?.value!)
? 'Your password should not contain your username'
? t('modals.signup.errors.password_contains_username')
: ''
break
case 'password':
newErrors.password = value.length < 8
? 'Password must be at least 8 characters'
? t('modals.signup.errors.password_too_short')
: ''
break
case 'confirm_password':
newErrors.passwordConfirmation = passwordInput.current?.value === passwordConfirmationInput.current?.value
? ''
: 'Your passwords don\'t match'
: t('modals.signup.errors.passwords_dont_match')
break
default:
@ -231,13 +234,13 @@ const SignupModal = (props: Props) => {
<Dialog.Root open={open} onOpenChange={openChange}>
<Dialog.Trigger asChild>
<li className="MenuItem">
<span>Sign up</span>
<span>{t('menu.signup')}</span>
</li>
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Content className="Signup Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
<div className="DialogHeader">
<Dialog.Title className="DialogTitle">Sign up</Dialog.Title>
<Dialog.Title className="DialogTitle">{t('modals.signup.title')}</Dialog.Title>
<Dialog.Close className="DialogClose" asChild>
<span>
<CrossIcon />
@ -248,7 +251,7 @@ const SignupModal = (props: Props) => {
<form className="form" onSubmit={register}>
<Fieldset
fieldName="username"
placeholder="Username"
placeholder={t('modals.signup.placeholders.username')}
onChange={handleNameChange}
error={errors.username}
ref={usernameInput}
@ -256,7 +259,7 @@ const SignupModal = (props: Props) => {
<Fieldset
fieldName="email"
placeholder="Email address"
placeholder={t('modals.signup.placeholders.email')}
onChange={handleNameChange}
error={errors.email}
ref={emailInput}
@ -264,7 +267,7 @@ const SignupModal = (props: Props) => {
<Fieldset
fieldName="password"
placeholder="Password"
placeholder={t('modals.signup.placeholders.password')}
onChange={handlePasswordChange}
error={errors.password}
ref={passwordInput}
@ -272,16 +275,18 @@ const SignupModal = (props: Props) => {
<Fieldset
fieldName="confirm_password"
placeholder="Password (again)"
placeholder={t('modals.signup.placeholders.password_confirm')}
onChange={handlePasswordChange}
error={errors.passwordConfirmation}
ref={passwordConfirmationInput}
/>
<Button>Sign up</Button>
<Button>{t('modals.signup.buttons.confirm')}</Button>
<Dialog.Description className="terms">
By signing up, I agree to the<br /><a href="#">Terms and Conditions</a> and <a href="#">Usage Guidelines</a>.
<Trans i18nKey="modals.signup.agreement">
By signing up, I agree to the <a href="/privacy">Privacy Policy</a><a href="/usage">Usage Guidelines</a>.
</Trans>
</Dialog.Description>
</form>
</Dialog.Content>

View file

@ -54,6 +54,22 @@
"cancel": "Nevermind"
}
},
"login": {
"title": "Log in",
"buttons": {
"confirm": "Log in"
},
"errors": {
"empty_email": "Please enter your email",
"empty_password": "Please enter your password",
"invalid_email": "That email address is not valid",
"invalid_credentials": "Your email address or password is incorrect"
},
"placeholders": {
"email": "Email address",
"password": "Password"
}
},
"settings": {
"title": "Account Settings",
"labels": {
@ -71,14 +87,40 @@
"buttons": {
"confirm": "Save settings"
}
},
"signup": {
"title": "Create an account",
"buttons": {
"confirm": "Sign up"
},
"agreement": "By signing up, I agree to the <br/><2>Privacy Policy</2> and <1>Usage Guidelines</1>.",
"errors": {
"field_in_use": "This {{field}} is already in use",
"empty_email": "Please enter your email",
"invalid_email": "That email address is not valid",
"username_too_short": "Username must be at least 3 characters",
"username_too_long": "Username must be less than 20 characters",
"empty_password": "Please enter your password",
"password_contains_username": "Your password should not contain your username",
"password_too_short": "Password must be at least 8 characters",
"mismatched_passwords": "Your passwords don't match"
},
"placeholders": {
"username": "Username",
"email": "Email address",
"password": "Password",
"password_confirm": "Password (again)"
}
}
},
"menu": {
"about": "About",
"guides": "Guides",
"language": "Language",
"login": "Log in",
"saved": "Saved",
"settings": "Settings",
"signup": "Sign up",
"teams": "Teams",
"logout": "Logout"
},

View file

@ -54,6 +54,22 @@
"cancel": "キャンセル"
}
},
"login": {
"title": "ログイン",
"buttons": {
"confirm": "ログイン"
},
"errors": {
"empty_email": "メールアドレスを入力して下さい",
"empty_password": "パスワードを入力して下さい",
"invalid_email": "メールアドレスは有効ではありません",
"invalid_credentials": "パスワードまたはメールアドレスが違います"
},
"placeholders": {
"email": "メールアドレス",
"password": "パスワード"
}
},
"settings": {
"title": "アカウント設定",
"labels": {
@ -71,14 +87,41 @@
"buttons": {
"confirm": "設定を保存する"
}
},
"signup": {
"title": "アカウント登録",
"buttons": {
"confirm": "登録する"
},
"agreement": "続行することで<1>利用規約</1>に同意し、<br/><1>プライバシーポリシー</1>を読んだものとみなされます。",
"errors": {
"field_in_use": "入力された{{field}}は既に登録済みです",
"empty_email": "メールアドレスを入力して下さい",
"invalid_email": "メールアドレスは有効ではありません",
"username_too_short": "ユーザーネームは3文字以上で入力してください",
"username_too_long": "ユーザーネームは20文字以内で入力してください",
"empty_password": "パスワードを入力して下さい",
"password_contains_username": "パスワードにはユーザー名を含めないでください",
"password_too_short": "パスワードは8文字以上で入力してください",
"mismatched_passwords": "パスワードとパスワード確認を確かめてください",
"invalid_credentials": "パスワードまたはメールアドレスが違います"
},
"placeholders": {
"username": "ユーザー名",
"email": "メールアドレス",
"password": "パスワード",
"password_confirm": "パスワード確認"
}
}
},
"menu": {
"about": "このサイトについて",
"guides": "攻略",
"language": "言語",
"login": "ログイン",
"saved": "保存した編成",
"settings": "アカウント設定",
"signup": "登録",
"teams": "編成一覧",
"logout": "ログアウト"
},