Commit e2abc9e5 authored by tom's avatar tom

simple profile button and auth modal layout

parent 99446524
......@@ -3,6 +3,7 @@ import React from 'react';
import config from 'configs/app';
import AdBanner from 'ui/shared/ad/AdBanner';
import ProfileDesktop from 'ui/snippets/profile/ProfileDesktop';
import ProfileMenuDesktop from 'ui/snippets/profileMenu/ProfileMenuDesktop';
import SearchBar from 'ui/snippets/searchBar/SearchBar';
import WalletMenuDesktop from 'ui/snippets/walletMenu/WalletMenuDesktop';
......@@ -56,6 +57,7 @@ const HeroBanner = () => {
<Box display={{ base: 'none', lg: 'flex' }}>
{ config.features.account.isEnabled && <ProfileMenuDesktop isHomePage/> }
{ config.features.blockchainInteraction.isEnabled && <WalletMenuDesktop isHomePage/> }
{ config.features.account.isEnabled && <ProfileDesktop isHomePage/> }
</Box>
) }
</Flex>
......
......@@ -12,6 +12,7 @@ import IconSvg from 'ui/shared/IconSvg';
import LinkExternal from 'ui/shared/links/LinkExternal';
import LinkInternal from 'ui/shared/links/LinkInternal';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import ProfileDesktop from 'ui/snippets/profile/ProfileDesktop';
import ProfileMenuDesktop from 'ui/snippets/profileMenu/ProfileMenuDesktop';
import WalletMenuDesktop from 'ui/snippets/walletMenu/WalletMenuDesktop';
......@@ -101,6 +102,7 @@ const MarketplaceAppTopBar = ({ appId, data, isLoading, securityReport }: Props)
<Flex flex="1" justifyContent="flex-end">
{ config.features.account.isEnabled && <ProfileMenuDesktop boxSize="32px" fallbackIconSize={ 16 }/> }
{ config.features.blockchainInteraction.isEnabled && <WalletMenuDesktop size="sm"/> }
{ config.features.account.isEnabled && <ProfileDesktop buttonSize="sm"/> }
</Flex>
) }
</Flex>
......
import { Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay } from '@chakra-ui/react';
import React from 'react';
import type { Screen } from './types';
import IconSvg from 'ui/shared/IconSvg';
import AuthModalScreenEmail from './screens/AuthModalScreenEmail';
import AuthModalScreenOtpCode from './screens/AuthModalScreenOtpCode';
import AuthModalScreenSelectMethod from './screens/AuthModalScreenSelectMethod';
import AuthModalScreenSuccessCreatedEmail from './screens/AuthModalScreenSuccessCreatedEmail';
interface Props {
initialScreen: Screen;
onClose: () => void;
}
const AuthModal = ({ initialScreen, onClose }: Props) => {
const [ steps, setSteps ] = React.useState<Array<Screen>>([ initialScreen ]);
const onNextStep = React.useCallback((screen: Screen) => {
setSteps((prev) => [ ...prev, screen ]);
}, []);
const onPrevStep = React.useCallback(() => {
setSteps((prev) => prev.length > 1 ? prev.slice(0, -1) : prev);
}, []);
const header = (() => {
const currentStep = steps[steps.length - 1];
switch (currentStep.type) {
case 'select_method':
return 'Select a way to connect';
case 'email':
return 'Continue with email';
case 'otp_code':
return 'Confirmation code';
case 'success_created_email':
return 'Congrats!';
}
})();
const content = (() => {
const currentStep = steps[steps.length - 1];
switch (currentStep.type) {
case 'select_method':
return <AuthModalScreenSelectMethod onSelectMethod={ onNextStep }/>;
case 'email':
return <AuthModalScreenEmail onSubmit={ onNextStep }/>;
case 'otp_code':
return <AuthModalScreenOtpCode email={ currentStep.email } onSubmit={ onNextStep }/>;
case 'success_created_email':
return <AuthModalScreenSuccessCreatedEmail/>;
}
})();
return (
<Modal isOpen onClose={ onClose } size={{ base: 'full', lg: 'sm' }}>
<ModalOverlay/>
<ModalContent p={ 6 } maxW={{ lg: '400px' }}>
<ModalHeader fontWeight="500" textStyle="h3" mb={ 2 } display="flex" alignItems="center" columnGap={ 2 }>
{ steps.length > 1 && !steps[steps.length - 1].type.startsWith('success') && (
<IconSvg
name="arrows/east"
boxSize={ 6 }
transform="rotate(180deg)"
color="gray.400"
flexShrink={ 0 }
onClick={ onPrevStep }
cursor="pointer"
/>
) }
{ header }
</ModalHeader>
<ModalCloseButton top={ 6 } right={ 6 } color="gray.400"/>
<ModalBody mb={ 0 }>
{ content }
</ModalBody>
</ModalContent>
</Modal>
);
};
export default React.memo(AuthModal);
import { Box, Button, Input, Text } from '@chakra-ui/react';
import React from 'react';
import type { Screen } from '../types';
interface Props {
onSubmit: (screen: Screen) => void;
}
const AuthModalScreenEmail = ({ onSubmit }: Props) => {
const handleSubmitClick = React.useCallback(() => {
onSubmit({ type: 'otp_code', email: 'tom@ohhhh.me' });
}, [ onSubmit ]);
return (
<Box>
<Text>Account email, used for transaction notifications from your watchlist.</Text>
<Input placeholder="Email" mt={ 6 }/>
<Button mt={ 6 } onClick={ handleSubmitClick }>Send a code</Button>
</Box>
);
};
export default React.memo(AuthModalScreenEmail);
import { chakra, Box, Text, Input, Button, Link } from '@chakra-ui/react';
import React from 'react';
import type { Screen } from '../types';
import IconSvg from 'ui/shared/IconSvg';
interface Props {
email: string;
onSubmit: (screen: Screen) => void;
}
const AuthModalScreenOtpCode = ({ email, onSubmit }: Props) => {
const handleSubmitClick = React.useCallback(() => {
onSubmit({ type: 'success_created_email' });
}, [ onSubmit ]);
return (
<Box>
<Text>
Please check{ ' ' }
<chakra.span fontWeight="700">{ email }</chakra.span>{ ' ' }
and enter your code below.
</Text>
<Input placeholder="Confirmation code" mt={ 6 }/>
<Link display="flex" alignItems="center" gap={ 2 } mt={ 3 } w="fit-content">
<IconSvg name="repeat" boxSize={ 5 }/>
<Box fontSize="sm">Resend code</Box>
</Link>
<Button mt={ 6 } onClick={ handleSubmitClick }>Submit</Button>
</Box>
);
};
export default React.memo(AuthModalScreenOtpCode);
import { Button, VStack } from '@chakra-ui/react';
import React from 'react';
import type { Screen } from '../types';
interface Props {
onSelectMethod: (screen: Screen) => void;
}
const AuthModalScreenSelectMethod = ({ onSelectMethod }: Props) => {
const handleEmailClick = React.useCallback(() => {
onSelectMethod({ type: 'email' });
}, [ onSelectMethod ]);
return (
<VStack spacing={ 3 } mt={ 4 } align="stretch">
<Button variant="outline">Connect Web3 wallet</Button>
<Button variant="outline" onClick={ handleEmailClick }>Continue with email</Button>
</VStack>
);
};
export default React.memo(AuthModalScreenSelectMethod);
import { Box, Text, Button } from '@chakra-ui/react';
import React from 'react';
const AuthModalScreenSuccessCreatedEmail = () => {
return (
<Box>
<Text>Your account was successfully created!</Text>
<Text mt={ 6 }>Connect a web3 wallet to safely interact with smart contracts and dapps inside Blockscout.</Text>
<Button mt={ 6 }>Connect wallet</Button>
</Box>
);
};
export default React.memo(AuthModalScreenSuccessCreatedEmail);
export type Screen = {
type: 'select_method';
} | {
type: 'email';
} | {
type: 'otp_code';
email: string;
} | {
type: 'success_created_email';
}
......@@ -3,6 +3,7 @@ import React from 'react';
import config from 'configs/app';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import ProfileDesktop from 'ui/snippets/profile/ProfileDesktop';
import ProfileMenuDesktop from 'ui/snippets/profileMenu/ProfileMenuDesktop';
import SearchBar from 'ui/snippets/searchBar/SearchBar';
import WalletMenuDesktop from 'ui/snippets/walletMenu/WalletMenuDesktop';
......@@ -40,6 +41,7 @@ const HeaderDesktop = ({ renderSearchBar, isMarketplaceAppPage }: Props) => {
<Box display="flex">
{ config.features.account.isEnabled && <ProfileMenuDesktop/> }
{ config.features.blockchainInteraction.isEnabled && <WalletMenuDesktop/> }
{ config.features.account.isEnabled && <ProfileDesktop/> }
</Box>
) }
</HStack>
......
......@@ -5,6 +5,7 @@ import config from 'configs/app';
import useNavItems, { isGroupItem } from 'lib/hooks/useNavItems';
import { CONTENT_MAX_WIDTH } from 'ui/shared/layout/utils';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import ProfileDesktop from 'ui/snippets/profile/ProfileDesktop';
import ProfileMenuDesktop from 'ui/snippets/profileMenu/ProfileMenuDesktop';
import WalletMenuDesktop from 'ui/snippets/walletMenu/WalletMenuDesktop';
......@@ -40,6 +41,7 @@ const NavigationDesktop = () => {
</chakra.nav>
{ config.features.account.isEnabled && <ProfileMenuDesktop buttonBoxSize="32px"/> }
{ config.features.blockchainInteraction.isEnabled && <WalletMenuDesktop size="sm"/> }
{ config.features.account.isEnabled && <ProfileDesktop buttonSize="sm"/> }
</Flex>
</Box>
);
......
import type { ButtonProps } from '@chakra-ui/react';
import { Button, Tooltip } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import React from 'react';
import type { UserInfo } from 'types/api/account';
interface Props {
profileQuery: UseQueryResult<UserInfo, unknown>;
size?: ButtonProps['size'];
variant?: 'hero' | 'header';
onClick: () => void;
}
const ProfileButton = ({ profileQuery, size, variant, onClick }: Props) => {
const { data, isPending } = profileQuery;
return (
<Tooltip
label={ <span>Sign in to My Account to add tags,<br/>create watchlists, access API keys and more</span> }
textAlign="center"
padding={ 2 }
isDisabled={ isPending || Boolean(data) }
openDelay={ 500 }
>
<Button size={ size } variant={ variant } onClick={ onClick }>Connect</Button>
</Tooltip>
);
};
export default React.memo(ProfileButton);
import { useDisclosure, type ButtonProps } from '@chakra-ui/react';
import React from 'react';
import useFetchProfileInfo from 'lib/hooks/useFetchProfileInfo';
import AuthModal from 'ui/snippets/auth/AuthModal';
import ProfileButton from './ProfileButton';
interface Props {
buttonSize?: ButtonProps['size'];
isHomePage?: boolean;
}
const ProfileDesktop = ({ buttonSize, isHomePage }: Props) => {
const profileQuery = useFetchProfileInfo();
const authModal = useDisclosure();
return (
<>
<ProfileButton
profileQuery={ profileQuery }
size={ buttonSize }
variant={ isHomePage ? 'hero' : 'header' }
onClick={ authModal.onOpen }
/>
{ authModal.isOpen && <AuthModal onClose={ authModal.onClose } initialScreen={{ type: 'select_method' }}/> }
</>
);
};
export default React.memo(ProfileDesktop);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment