From a0deeabfed3332c687652b7023eb91d14a09adbf Mon Sep 17 00:00:00 2001 From: Max Alekseenko Date: Thu, 7 Nov 2024 14:48:52 +0100 Subject: [PATCH] Adding an email when logging into merits (#2369) * add email step * fix preset * update text * fix login with wallet * update button text and var names * update mixpanel events --- configs/envs/.env.eth_sepolia | 2 +- lib/mixpanel/utils.ts | 2 +- ui/rewards/login/RewardsLoginModal.tsx | 74 +++++++++++++------ ui/rewards/login/steps/LoginStepContent.tsx | 39 ++++++---- ui/snippets/auth/AuthModal.tsx | 7 +- .../screens/AuthModalScreenSuccessWallet.tsx | 14 +++- 6 files changed, 93 insertions(+), 45 deletions(-) diff --git a/configs/envs/.env.eth_sepolia b/configs/envs/.env.eth_sepolia index 763512fdb5..7c75dd73d9 100644 --- a/configs/envs/.env.eth_sepolia +++ b/configs/envs/.env.eth_sepolia @@ -62,4 +62,4 @@ NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=noves NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com NEXT_PUBLIC_REWARDS_SERVICE_API_HOST=https://points.k8s-dev.blockscout.com -NEXT_PUBLIC_XSTAR_SCORE_URL='https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address' +NEXT_PUBLIC_XSTAR_SCORE_URL=https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address diff --git a/lib/mixpanel/utils.ts b/lib/mixpanel/utils.ts index acea62a1f8..78dbe4d046 100644 --- a/lib/mixpanel/utils.ts +++ b/lib/mixpanel/utils.ts @@ -74,7 +74,7 @@ Type extends EventTypes.LOGIN ? ( } ) : Type extends EventTypes.ACCOUNT_LINK_INFO ? { - 'Source': 'Profile' | 'Login modal' | 'Profile dropdown'; + 'Source': 'Profile' | 'Login modal' | 'Profile dropdown' | 'Merits'; 'Status': 'Started' | 'OTP sent' | 'Finished'; 'Type': 'Email' | 'Wallet'; } : diff --git a/ui/rewards/login/RewardsLoginModal.tsx b/ui/rewards/login/RewardsLoginModal.tsx index da48b163ca..a98089abdc 100644 --- a/ui/rewards/login/RewardsLoginModal.tsx +++ b/ui/rewards/login/RewardsLoginModal.tsx @@ -1,13 +1,23 @@ -import { Modal, ModalOverlay, ModalContent, ModalHeader, ModalCloseButton, ModalBody, useBoolean } from '@chakra-ui/react'; +import { Modal, ModalOverlay, ModalContent, ModalHeader, ModalCloseButton, ModalBody, useBoolean, useDisclosure } from '@chakra-ui/react'; import React, { useCallback, useEffect } from 'react'; import { useRewardsContext } from 'lib/contexts/rewards'; import useIsMobile from 'lib/hooks/useIsMobile'; import useWallet from 'lib/web3/useWallet'; +import AuthModal from 'ui/snippets/auth/AuthModal'; import CongratsStepContent from './steps/CongratsStepContent'; import LoginStepContent from './steps/LoginStepContent'; +const MIXPANEL_CONFIG = { + account_link_info: { + source: 'Merits' as const, + }, + wallet_connect: { + source: 'Merits' as const, + }, +}; + const RewardsLoginModal = () => { const { isOpen: isWalletModalOpen } = useWallet({ source: 'Merits' }); const isMobile = useIsMobile(); @@ -15,6 +25,8 @@ const RewardsLoginModal = () => { const [ isLoginStep, setIsLoginStep ] = useBoolean(true); const [ isReferral, setIsReferral ] = useBoolean(false); + const [ isAuth, setIsAuth ] = useBoolean(false); + const authModal = useDisclosure(); useEffect(() => { if (!isLoginModalOpen) { @@ -30,27 +42,47 @@ const RewardsLoginModal = () => { setIsLoginStep.off(); }, [ setIsLoginStep, setIsReferral ]); + const handleAuthModalOpen = useCallback((isAuth: boolean) => { + setIsAuth[isAuth ? 'on' : 'off'](); + authModal.onOpen(); + }, [ authModal, setIsAuth ]); + + const handleAuthModalClose = useCallback(() => { + setIsAuth.off(); + authModal.onClose(); + }, [ authModal, setIsAuth ]); + return ( - - - - - { isLoginStep ? 'Login' : 'Congratulations' } - - - - { isLoginStep ? - : - - } - - - + <> + + + + + { isLoginStep ? 'Login' : 'Congratulations' } + + + + { isLoginStep ? + : + + } + + + + { authModal.isOpen && ( + + ) } + ); }; diff --git a/ui/rewards/login/steps/LoginStepContent.tsx b/ui/rewards/login/steps/LoginStepContent.tsx index 827a9483a9..f701c1ca55 100644 --- a/ui/rewards/login/steps/LoginStepContent.tsx +++ b/ui/rewards/login/steps/LoginStepContent.tsx @@ -10,14 +10,14 @@ import useWallet from 'lib/web3/useWallet'; import FormInputPlaceholder from 'ui/shared/forms/inputs/FormInputPlaceholder'; import LinkExternal from 'ui/shared/links/LinkExternal'; import useProfileQuery from 'ui/snippets/auth/useProfileQuery'; -import useSignInWithWallet from 'ui/snippets/auth/useSignInWithWallet'; type Props = { goNext: (isReferral: boolean) => void; closeModal: () => void; + openAuthModal: (isAuth: boolean) => void; }; -const LoginStepContent = ({ goNext, closeModal }: Props) => { +const LoginStepContent = ({ goNext, closeModal, openAuthModal }: Props) => { const router = useRouter(); const { connect, isConnected, address } = useWallet({ source: 'Merits' }); const savedRefCode = cookies.get(cookies.NAMES.REWARDS_REFERRAL_CODE); @@ -34,6 +34,10 @@ const LoginStepContent = ({ goNext, closeModal }: Props) => { profileQuery.data?.address_hash !== address, [ address, profileQuery.data ]); + const isLoggedIntoAccountWithWallet = useMemo(() => + !profileQuery.isLoading && profileQuery.data?.address_hash, + [ profileQuery ]); + const isSignUp = useMemo(() => isConnected && !isAddressMismatch && !checkUserQuery.isFetching && !checkUserQuery.data?.exists, [ isConnected, isAddressMismatch, checkUserQuery ]); @@ -69,20 +73,23 @@ const LoginStepContent = ({ goNext, closeModal }: Props) => { } }, [ refCode, isRefCodeUsed, isSignUp ]); // eslint-disable-line react-hooks/exhaustive-deps - const { start: loginToAccount } = useSignInWithWallet({ - isAuth: Boolean(!profileQuery.isLoading && profileQuery.data?.email), - onSuccess: loginToRewardsProgram, - onError: setIsLoading.off, - }); - const handleLogin = useCallback(async() => { - if (!profileQuery.isLoading && !profileQuery.data?.address_hash) { - setIsLoading.on(); - loginToAccount(); - return; + if (isLoggedIntoAccountWithWallet) { + loginToRewardsProgram(); + } else { + openAuthModal(Boolean(profileQuery.data?.email)); + } + }, [ loginToRewardsProgram, openAuthModal, isLoggedIntoAccountWithWallet, profileQuery ]); + + const buttonText = useMemo(() => { + if (!isConnected) { + return 'Connect wallet'; + } + if (isLoggedIntoAccountWithWallet) { + return 'Get started'; } - loginToRewardsProgram(); - }, [ loginToAccount, loginToRewardsProgram, profileQuery, setIsLoading ]); + return profileQuery.data?.email ? 'Add wallet to account' : 'Log in to account'; + }, [ isConnected, isLoggedIntoAccountWithWallet, profileQuery.data ]); return ( <> @@ -98,7 +105,7 @@ const LoginStepContent = ({ goNext, closeModal }: Props) => { More about Blockscout Merits - { isSignUp && ( + { isSignUp && isLoggedIntoAccountWithWallet && ( @@ -145,7 +152,7 @@ const LoginStepContent = ({ goNext, closeModal }: Props) => { loadingText={ isLoading ? 'Sign message in your wallet' : undefined } isDisabled={ isAddressMismatch || refCodeError } > - { isConnected ? 'Get started' : 'Connect wallet' } + { buttonText } Already registered for Blockscout Merits on another network or chain? Connect the same wallet here. diff --git a/ui/snippets/auth/AuthModal.tsx b/ui/snippets/auth/AuthModal.tsx index c3068a7e9c..24aca1834f 100644 --- a/ui/snippets/auth/AuthModal.tsx +++ b/ui/snippets/auth/AuthModal.tsx @@ -32,9 +32,10 @@ interface Props { source: mixpanel.EventPayload['Source']; }; }; + closeOnError?: boolean; } -const AuthModal = ({ initialScreen, onClose, mixpanelConfig }: Props) => { +const AuthModal = ({ initialScreen, onClose, mixpanelConfig, closeOnError }: Props) => { const [ steps, setSteps ] = React.useState>([ initialScreen ]); const [ isSuccess, setIsSuccess ] = React.useState(false); @@ -66,8 +67,8 @@ const AuthModal = ({ initialScreen, onClose, mixpanelConfig }: Props) => { }, []); const onReset = React.useCallback((isAuth?: boolean) => { - isAuth ? onClose() : setSteps([ initialScreen ]); - }, [ initialScreen, onClose ]); + isAuth || closeOnError ? onClose() : setSteps([ initialScreen ]); + }, [ initialScreen, onClose, closeOnError ]); const onAuthSuccess = React.useCallback(async(screen: ScreenSuccess) => { setIsSuccess(true); diff --git a/ui/snippets/auth/screens/AuthModalScreenSuccessWallet.tsx b/ui/snippets/auth/screens/AuthModalScreenSuccessWallet.tsx index 862cfdebe8..2febd91f29 100644 --- a/ui/snippets/auth/screens/AuthModalScreenSuccessWallet.tsx +++ b/ui/snippets/auth/screens/AuthModalScreenSuccessWallet.tsx @@ -1,9 +1,11 @@ -import { chakra, Box, Text, Button } from '@chakra-ui/react'; +import { chakra, Box, Text, Button, Flex } from '@chakra-ui/react'; import React from 'react'; import type { Screen } from '../types'; import type { UserInfo } from 'types/api/account'; +import config from 'configs/app'; +import { apos } from 'lib/html-entities'; import shortenString from 'lib/shortenString'; interface Props { @@ -47,8 +49,14 @@ const AuthModalScreenSuccessWallet = ({ address, onAddEmail, onClose, isAuth, pr { !profile?.email ? ( <> - Add your email to receive notifications about addresses in your watch list. - + + Add your email to receive exclusive updates about Blockscout { config.features.rewards.isEnabled ? 'Merits ' : ' ' } + and notifications about addresses in your watch list. + + + + + ) : (