From 18db2e51168d75701ad055dff3553bdb391681e9 Mon Sep 17 00:00:00 2001 From: Xiao Yijun Date: Tue, 13 Aug 2024 11:27:44 +0800 Subject: [PATCH] feat(experience): add identifier register page --- packages/experience/src/App.tsx | 7 ++++ .../src/pages/IdentifierRegister/index.tsx | 41 +++++++++++++++++++ .../use-identifier-sign-up-methods.ts | 35 ++++++++++++++++ .../src/locales/de/description.ts | 3 ++ .../src/locales/en/description.ts | 3 ++ .../src/locales/es/description.ts | 3 ++ .../src/locales/fr/description.ts | 3 ++ .../src/locales/it/description.ts | 3 ++ .../src/locales/ja/description.ts | 3 ++ .../src/locales/ko/description.ts | 3 ++ .../src/locales/pl-pl/description.ts | 3 ++ .../src/locales/pt-br/description.ts | 3 ++ .../src/locales/pt-pt/description.ts | 3 ++ .../src/locales/ru/description.ts | 3 ++ .../src/locales/tr-tr/description.ts | 3 ++ .../src/locales/zh-cn/description.ts | 2 + .../src/locales/zh-hk/description.ts | 2 + .../src/locales/zh-tw/description.ts | 2 + packages/schemas/src/consts/experience.ts | 1 + 19 files changed, 126 insertions(+) create mode 100644 packages/experience/src/pages/IdentifierRegister/index.tsx create mode 100644 packages/experience/src/pages/IdentifierRegister/use-identifier-sign-up-methods.ts diff --git a/packages/experience/src/App.tsx b/packages/experience/src/App.tsx index 56e03faa518..3ab55e763d2 100644 --- a/packages/experience/src/App.tsx +++ b/packages/experience/src/App.tsx @@ -14,6 +14,7 @@ import Continue from './pages/Continue'; import DirectSignIn from './pages/DirectSignIn'; import ErrorPage from './pages/ErrorPage'; import ForgotPassword from './pages/ForgotPassword'; +import IdentifierRegister from './pages/IdentifierRegister'; import IdentifierSignIn from './pages/IdentifierSignIn'; import MfaBinding from './pages/MfaBinding'; import BackupCodeBinding from './pages/MfaBinding/BackupCodeBinding'; @@ -129,6 +130,12 @@ const App = () => { path={experience.routes.identifierSignIn} element={} /> + + {/* Identifier register */} + } + /> )} diff --git a/packages/experience/src/pages/IdentifierRegister/index.tsx b/packages/experience/src/pages/IdentifierRegister/index.tsx new file mode 100644 index 00000000000..a7ab58c66e4 --- /dev/null +++ b/packages/experience/src/pages/IdentifierRegister/index.tsx @@ -0,0 +1,41 @@ +import { AgreeToTermsPolicy, experience } from '@logto/schemas'; +import { useTranslation } from 'react-i18next'; +import { Navigate } from 'react-router-dom'; + +import IdentifierPageLayout from '@/Layout/IdentifierPageLayout'; +import { identifierInputDescriptionMap } from '@/utils/form'; + +import IdentifierRegisterForm from '../Register/IdentifierRegisterForm'; + +import useIdentifierSignUpMethods from './use-identifier-sign-up-methods'; + +const IdentifierRegister = () => { + const { t } = useTranslation(); + const signUpMethods = useIdentifierSignUpMethods(); + + /** + * Fallback to sign-in page if no sign up methods are available (not allowed to create an account). + */ + if (signUpMethods.length === 0) { + return ; + } + + return ( + t(identifierInputDescriptionMap[identifier])), + })} + footerTermsDisplayPolicies={[AgreeToTermsPolicy.Automatic]} + authOptionsLink={{ + to: `/${experience.routes.register}`, + text: 'description.all_account_creation_options', + }} + > + + + ); +}; + +export default IdentifierRegister; diff --git a/packages/experience/src/pages/IdentifierRegister/use-identifier-sign-up-methods.ts b/packages/experience/src/pages/IdentifierRegister/use-identifier-sign-up-methods.ts new file mode 100644 index 00000000000..1a08d0553d9 --- /dev/null +++ b/packages/experience/src/pages/IdentifierRegister/use-identifier-sign-up-methods.ts @@ -0,0 +1,35 @@ +import { useMemo } from 'react'; + +import useIdentifierParams from '@/hooks/use-identifier-params'; +import { useSieMethods } from '@/hooks/use-sie'; + +/** + * Read sign-up methods from sign-in experience config and URL identifier parameters. + * + * Sign-up methods fallback logic: + * 1. If no identifiers are provided in the URL, return all sign-up methods from sign-in experience config. + * 2. If identifiers are provided in the URL but all of them are not supported by the sign-in experience config, return all sign-up methods from sign-in experience config. + * 3. If identifiers are provided in the URL and supported by the sign-in experience config, return the intersection of the two. + */ +const useIdentifierSignUpMethods = () => { + const { signUpMethods: signUpMethodsFromSie } = useSieMethods(); + const { identifiers } = useIdentifierParams(); + + return useMemo(() => { + // Fallback to all sign up methods if no identifiers are provided + if (identifiers.length === 0) { + return signUpMethodsFromSie; + } + + const methods = signUpMethodsFromSie.filter((identifier) => identifiers.includes(identifier)); + + // Fallback to all sign up methods if no identifiers are supported + if (methods.length === 0) { + return signUpMethodsFromSie; + } + + return methods; + }, [identifiers, signUpMethodsFromSie]); +}; + +export default useIdentifierSignUpMethods; diff --git a/packages/phrases-experience/src/locales/de/description.ts b/packages/phrases-experience/src/locales/de/description.ts index bde66dd9c3c..3d72bc3aa92 100644 --- a/packages/phrases-experience/src/locales/de/description.ts +++ b/packages/phrases-experience/src/locales/de/description.ts @@ -105,6 +105,9 @@ const description = { identifier_sign_in_description: 'Geben Sie Ihre {{types, list(type: disjunction;)}} ein, um sich anzumelden.', all_sign_in_options: 'Alle Anmeldeoptionen', + identifier_register_description: + 'Geben Sie Ihre {{types, list(type: disjunction;)}} ein, um ein neues Konto zu erstellen.', + all_account_creation_options: 'Alle Kontoerstellungsoptionen', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/en/description.ts b/packages/phrases-experience/src/locales/en/description.ts index 8689e7e1e2a..62ad7540150 100644 --- a/packages/phrases-experience/src/locales/en/description.ts +++ b/packages/phrases-experience/src/locales/en/description.ts @@ -90,6 +90,9 @@ const description = { auto_agreement: 'By continuing, you agree to the .', identifier_sign_in_description: 'Enter you {{types, list(type: disjunction;)}} to sign in.', all_sign_in_options: 'All sign-in options', + identifier_register_description: + 'Enter you {{types, list(type: disjunction;)}} to create a new account.', + all_account_creation_options: 'All account creation options', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/es/description.ts b/packages/phrases-experience/src/locales/es/description.ts index fbec1edf258..ad6341bc283 100644 --- a/packages/phrases-experience/src/locales/es/description.ts +++ b/packages/phrases-experience/src/locales/es/description.ts @@ -105,6 +105,9 @@ const description = { identifier_sign_in_description: 'Ingrese su {{types, list(type: disjunction;)}} para iniciar sesión.', all_sign_in_options: 'Todas las opciones de inicio de sesión', + identifier_register_description: + 'Ingrese su {{types, list(type: disjunction;)}} para crear una nueva cuenta.', + all_account_creation_options: 'Todas las opciones de creación de cuenta', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/fr/description.ts b/packages/phrases-experience/src/locales/fr/description.ts index 867e96ec756..748074b7b45 100644 --- a/packages/phrases-experience/src/locales/fr/description.ts +++ b/packages/phrases-experience/src/locales/fr/description.ts @@ -105,6 +105,9 @@ const description = { identifier_sign_in_description: 'Entrez votre {{types, list(type: disjunction;)}} pour vous connecter.', all_sign_in_options: 'Toutes les options de connexion', + identifier_register_description: + 'Entrez votre {{types, list(type: disjunction;)}} pour créer un nouveau compte.', + all_account_creation_options: 'Toutes les options de création de compte', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/it/description.ts b/packages/phrases-experience/src/locales/it/description.ts index 8c5fa999e46..3a3eed40c36 100644 --- a/packages/phrases-experience/src/locales/it/description.ts +++ b/packages/phrases-experience/src/locales/it/description.ts @@ -102,6 +102,9 @@ const description = { identifier_sign_in_description: 'Inserisci il tuo {{types, list(type: disjunction;)}} per accedere.', all_sign_in_options: 'Tutte le opzioni di accesso', + identifier_register_description: + 'Inserisci il tuo {{types, list(type: disjunction;)}} per creare un nuovo account.', + all_account_creation_options: 'Tutte le opzioni di creazione account', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/ja/description.ts b/packages/phrases-experience/src/locales/ja/description.ts index 4bf41550720..6a68e572bf7 100644 --- a/packages/phrases-experience/src/locales/ja/description.ts +++ b/packages/phrases-experience/src/locales/ja/description.ts @@ -101,6 +101,9 @@ const description = { auto_agreement: '続行することで、に同意したことになります。', identifier_sign_in_description: '{{types, list(type: disjunction;)}}を入力してサインインします。', all_sign_in_options: 'すべてのサインインオプション', + identifier_register_description: + '{{types, list(type: disjunction;)}}を入力して新しいアカウントを作成します。', + all_account_creation_options: 'すべてのアカウント作成オプション', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/ko/description.ts b/packages/phrases-experience/src/locales/ko/description.ts index 460663a2c99..6a952a4fdb2 100644 --- a/packages/phrases-experience/src/locales/ko/description.ts +++ b/packages/phrases-experience/src/locales/ko/description.ts @@ -96,6 +96,9 @@ const description = { identifier_sign_in_description: '로그인하려면 {{types, list(type: disjunction;)}}을(를) 입력하세요.', all_sign_in_options: '모든 로그인 옵션', + identifier_register_description: + '새 계정을 만들려면 {{types, list(type: disjunction;)}}을(를) 입력하세요.', + all_account_creation_options: '모든 계정 생성 옵션', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/pl-pl/description.ts b/packages/phrases-experience/src/locales/pl-pl/description.ts index 8ec9d862dcd..8f117249891 100644 --- a/packages/phrases-experience/src/locales/pl-pl/description.ts +++ b/packages/phrases-experience/src/locales/pl-pl/description.ts @@ -103,6 +103,9 @@ const description = { identifier_sign_in_description: 'Wprowadź swoje {{types, list(type: disjunction;)}} aby się zalogować.', all_sign_in_options: 'Wszystkie opcje logowania', + identifier_register_description: + 'Wprowadź swoje {{types, list(type: disjunction;)}} aby utworzyć nowe konto.', + all_account_creation_options: 'Wszystkie opcje tworzenia konta', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/pt-br/description.ts b/packages/phrases-experience/src/locales/pt-br/description.ts index 2bfa3756165..d9e0cb9a773 100644 --- a/packages/phrases-experience/src/locales/pt-br/description.ts +++ b/packages/phrases-experience/src/locales/pt-br/description.ts @@ -99,6 +99,9 @@ const description = { auto_agreement: 'Ao continuar, você concorda com os .', identifier_sign_in_description: 'Digite seu {{types, list(type: disjunction;)}} para entrar.', all_sign_in_options: 'Todas as opções de login', + identifier_register_description: + 'Digite seu {{types, list(type: disjunction;)}} para criar uma nova conta.', + all_account_creation_options: 'Todas as opções de criação de conta', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/pt-pt/description.ts b/packages/phrases-experience/src/locales/pt-pt/description.ts index 70a3d64ad0a..1991d3825b4 100644 --- a/packages/phrases-experience/src/locales/pt-pt/description.ts +++ b/packages/phrases-experience/src/locales/pt-pt/description.ts @@ -100,6 +100,9 @@ const description = { identifier_sign_in_description: 'Introduza o seu {{types, list(type: disjunction;)}} para iniciar sessão.', all_sign_in_options: 'Todas as opções de início de sessão', + identifier_register_description: + 'Introduza o seu {{types, list(type: disjunction;)}} para criar uma nova conta.', + all_account_creation_options: 'Todas as opções de criação de conta', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/ru/description.ts b/packages/phrases-experience/src/locales/ru/description.ts index dab9966c37c..1f8f6ca8b76 100644 --- a/packages/phrases-experience/src/locales/ru/description.ts +++ b/packages/phrases-experience/src/locales/ru/description.ts @@ -103,6 +103,9 @@ const description = { auto_agreement: 'Продолжая, вы соглашаетесь с .', identifier_sign_in_description: 'Введите свои {{types, list(type: disjunction;)}} для входа.', all_sign_in_options: 'Все варианты входа', + identifier_register_description: + 'Введите свои {{types, list(type: disjunction;)}} чтобы создать новую учётную запись.', + all_account_creation_options: 'Все варианты создания учётной записи', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/tr-tr/description.ts b/packages/phrases-experience/src/locales/tr-tr/description.ts index cecb875900e..6189a4b26e7 100644 --- a/packages/phrases-experience/src/locales/tr-tr/description.ts +++ b/packages/phrases-experience/src/locales/tr-tr/description.ts @@ -99,6 +99,9 @@ const description = { auto_agreement: 'Devam ederek kabul etmiş oluyorsunuz.', identifier_sign_in_description: 'Oturum açmak için {{types, list(type: disjunction;)}} girin.', all_sign_in_options: 'Tüm oturum açma seçenekleri', + identifier_register_description: + 'Yeni bir hesap oluşturmak için {{types, list(type: disjunction;)}} girin.', + all_account_creation_options: 'Tüm hesap oluşturma seçenekleri', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/zh-cn/description.ts b/packages/phrases-experience/src/locales/zh-cn/description.ts index f0c9b23ed5b..a24ae4f85e6 100644 --- a/packages/phrases-experience/src/locales/zh-cn/description.ts +++ b/packages/phrases-experience/src/locales/zh-cn/description.ts @@ -79,6 +79,8 @@ const description = { auto_agreement: '继续即表示您同意。', identifier_sign_in_description: '输入您的{{types, list(type: disjunction;)}}以登录。', all_sign_in_options: '所有登录选项', + identifier_register_description: '输入您的{{types, list(type: disjunction;)}}以创建新账户。', + all_account_creation_options: '所有账户创建选项', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/zh-hk/description.ts b/packages/phrases-experience/src/locales/zh-hk/description.ts index 1ef2ce8bd30..fc9a1233013 100644 --- a/packages/phrases-experience/src/locales/zh-hk/description.ts +++ b/packages/phrases-experience/src/locales/zh-hk/description.ts @@ -91,6 +91,8 @@ const description = { auto_agreement: '繼續即表示您同意。', identifier_sign_in_description: '輸入您的{{types, list(type: disjunction;)}}以登入。', all_sign_in_options: '所有登入選項', + identifier_register_description: '輸入您的{{types, list(type: disjunction;)}}以建立新帳戶。', + all_account_creation_options: '所有帳戶創建選項', }; export default Object.freeze(description); diff --git a/packages/phrases-experience/src/locales/zh-tw/description.ts b/packages/phrases-experience/src/locales/zh-tw/description.ts index 23c706afda8..89a0e0805bb 100644 --- a/packages/phrases-experience/src/locales/zh-tw/description.ts +++ b/packages/phrases-experience/src/locales/zh-tw/description.ts @@ -91,6 +91,8 @@ const description = { auto_agreement: '繼續即表示您同意。', identifier_sign_in_description: '輸入您的{{types, list(type: disjunction;)}}以登入。', all_sign_in_options: '所有登入選項', + identifier_register_description: '輸入您的{{types, list(type: disjunction;)}}以建立新帳戶。', + all_account_creation_options: '所有帳戶創建選項', }; export default Object.freeze(description); diff --git a/packages/schemas/src/consts/experience.ts b/packages/schemas/src/consts/experience.ts index c992636b6ed..2fab4d0537e 100644 --- a/packages/schemas/src/consts/experience.ts +++ b/packages/schemas/src/consts/experience.ts @@ -4,6 +4,7 @@ const routes = Object.freeze({ sso: 'single-sign-on', consent: 'consent', identifierSignIn: 'identifier-sign-in', + identifierRegister: 'identifier-register', }); export const experience = Object.freeze({