Commit 24cfa420 authored by Max Alekseenko's avatar Max Alekseenko

rework dapp page header

parent a6aed0e6
import { Alert } from '@chakra-ui/react';
import React from 'react';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
type Props = {
internalWallet: boolean | undefined;
isWalletConnected: boolean;
}
const MarketplaceAppAlert = ({ internalWallet, isWalletConnected }: Props) => {
const message = React.useMemo(() => {
let icon: IconName = 'wallet';
let text = 'Connect your wallet to Blockscout for full-featured access';
let status: 'warning' | 'success' = 'warning';
if (isWalletConnected && internalWallet) {
icon = 'integration/full';
text = 'Your wallet is connected with Blockscout';
status = 'success';
} else if (!internalWallet) {
icon = 'integration/partial';
text = 'Connect your wallet in the app below';
}
return { icon, text, status };
}, [ isWalletConnected, internalWallet ]);
return (
<Alert
status={ message.status }
borderRadius="base"
px={ 3 }
py={{ base: 3, md: 1.5 }}
fontSize="sm"
lineHeight={ 5 }
>
<IconSvg
name={ message.icon }
color={ message.status === 'success' ? 'green.600' : 'current' }
boxSize={ 5 }
flexShrink={ 0 }
mr={ 2 }
/>
{ message.text }
</Alert>
);
};
export default MarketplaceAppAlert;
import { chakra, Flex, Tooltip, Skeleton, useBoolean, Box } from '@chakra-ui/react';
import { chakra, Flex, Tooltip, Skeleton, useBoolean } from '@chakra-ui/react';
import React from 'react';
import type { MarketplaceAppOverview, MarketplaceAppSecurityReport } from 'types/client/marketplace';
......@@ -6,16 +6,19 @@ import { ContractListTypes } from 'types/client/marketplace';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import { useAppContext } from 'lib/contexts/app';
import useFeatureValue from 'lib/growthbook/useFeatureValue';
import useIsMobile from 'lib/hooks/useIsMobile';
import IconSvg from 'ui/shared/IconSvg';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import ProfileMenuDesktop from 'ui/snippets/profileMenu/ProfileMenuDesktop';
import WalletMenuDesktop from 'ui/snippets/walletMenu/WalletMenuDesktop';
import AppSecurityReport from './AppSecurityReport';
import ContractListModal from './ContractListModal';
import MarketplaceAppAlert from './MarketplaceAppAlert';
import MarketplaceAppInfo from './MarketplaceAppInfo';
type Props = {
......@@ -25,7 +28,7 @@ type Props = {
securityReport?: MarketplaceAppSecurityReport;
}
const MarketplaceAppTopBar = ({ data, isLoading, isWalletConnected, securityReport }: Props) => {
const MarketplaceAppTopBar = ({ data, isLoading, /* isWalletConnected, */ securityReport }: Props) => {
const [ showContractList, setShowContractList ] = useBoolean(false);
const appProps = useAppContext();
const isMobile = useIsMobile();
......@@ -46,32 +49,14 @@ const MarketplaceAppTopBar = ({ data, isLoading, isWalletConnected, securityRepo
return (
<>
<Flex alignItems="center" flexWrap="wrap" mb={{ base: 6, md: 2 }} rowGap={ 3 } columnGap={ 2 }>
<Tooltip label="Back to dApps list" order={ 1 }>
<LinkInternal display="inline-flex" href={ goBackUrl } h="32px" isLoading={ isLoading }>
<Flex alignItems="center" flexWrap="wrap" mb={{ base: 3, md: 2 }} rowGap={ 3 } columnGap={ 2 }>
{ !isMobile && <NetworkLogo isCollapsed/> }
<Tooltip label="Back to dApps list">
<LinkInternal display="inline-flex" href={ goBackUrl } h="32px" isLoading={ isLoading } ml={ isMobile ? 0 : 4 }>
<IconSvg name="arrows/east" boxSize={ 6 } transform="rotate(180deg)" margin="auto" color="gray.400"/>
</LinkInternal>
</Tooltip>
<Skeleton width={{ base: '100%', md: 'auto' }} order={{ base: 5, md: 2 }} isLoaded={ !isLoading }>
<MarketplaceAppAlert internalWallet={ data?.internalWallet } isWalletConnected={ isWalletConnected }/>
</Skeleton>
<Skeleton order={{ base: 2, md: 3 }} isLoaded={ !isLoading }>
<MarketplaceAppInfo data={ data }/>
</Skeleton>
{ (isExperiment && (securityReport || isLoading)) && (
<Box order={{ base: 3, md: 4 }}>
<AppSecurityReport
id={ data?.id || '' }
securityReport={ securityReport }
showContractList={ setShowContractList.on }
isLoading={ isLoading }
onlyIcon={ isMobile }
source="App page"
/>
</Box>
) }
<LinkExternal
order={{ base: 4, md: 5 }}
href={ data?.url }
variant="subtle"
fontSize="sm"
......@@ -85,6 +70,25 @@ const MarketplaceAppTopBar = ({ data, isLoading, isWalletConnected, securityRepo
{ getHostname(data?.url) }
</chakra.span>
</LinkExternal>
<Skeleton isLoaded={ !isLoading }>
<MarketplaceAppInfo data={ data }/>
</Skeleton>
{ (isExperiment && (securityReport || isLoading)) && (
<AppSecurityReport
id={ data?.id || '' }
securityReport={ securityReport }
showContractList={ setShowContractList.on }
isLoading={ isLoading }
onlyIcon={ isMobile }
source="App page"
/>
) }
{ !isMobile && (
<Flex flex="1" justifyContent="flex-end">
{ config.features.account.isEnabled && <ProfileMenuDesktop boxSize="32px" fallbackIconSize={ 16 }/> }
{ config.features.blockchainInteraction.isEnabled && <WalletMenuDesktop size="sm"/> }
</Flex>
) }
</Flex>
{ showContractList && (
<ContractListModal
......
......@@ -8,9 +8,10 @@ import IconSvg from 'ui/shared/IconSvg';
interface Props {
size: number;
fallbackIconSize?: number;
}
const UserAvatar = ({ size }: Props) => {
const UserAvatar = ({ size, fallbackIconSize = 20 }: Props) => {
const appProps = useAppContext();
const hasAuth = Boolean(cookies.get(cookies.NAMES.API_TOKEN, appProps.cookies));
const [ isImageLoadError, setImageLoadError ] = React.useState(false);
......@@ -34,7 +35,7 @@ const UserAvatar = ({ size }: Props) => {
boxSize={ `${ size }px` }
borderRadius="full"
overflow="hidden"
fallback={ isImageLoadError || !data?.avatar ? <IconSvg name="profile" boxSize={ 5 }/> : undefined }
fallback={ isImageLoadError || !data?.avatar ? <IconSvg name="profile" boxSize={ `${ fallbackIconSize }px` }/> : undefined }
onError={ handleImageLoadError }
/>
);
......
......@@ -3,7 +3,6 @@ import React from 'react';
import type { Props } from './types';
import AppErrorBoundary from 'ui/shared/AppError/AppErrorBoundary';
import HeaderDesktop from 'ui/snippets/header/HeaderDesktop';
import HeaderMobile from 'ui/snippets/header/HeaderMobile';
import * as Layout from './components';
......@@ -15,14 +14,13 @@ const LayoutDefault = ({ children }: Props) => {
<HeaderMobile/>
<Layout.MainArea>
<Layout.MainColumn
paddingTop={{ base: 16, lg: 6 }}
paddingTop={{ base: 16, lg: 0 }}
paddingBottom={ 0 }
paddingX={{ base: 4, lg: 6 }}
height={{ base: 'calc(100vh - 92px)', sm: 'auto' }} // 92px = Layout.TopRow + HeaderMobile
>
<HeaderDesktop isMarketplaceAppPage/>
<AppErrorBoundary>
<Layout.Content pt={{ base: 0, lg: 4 }} flexGrow={ 1 }>
<Layout.Content pt={{ base: 0, lg: 2 }} flexGrow={ 1 }>
{ children }
</Layout.Content>
</AppErrorBoundary>
......
import type { IconButtonProps } from '@chakra-ui/react';
import { Popover, PopoverContent, PopoverBody, PopoverTrigger, IconButton, Tooltip, Box } from '@chakra-ui/react';
import { Popover, PopoverContent, PopoverBody, PopoverTrigger, IconButton, Tooltip, Box, chakra } from '@chakra-ui/react';
import React from 'react';
import useFetchProfileInfo from 'lib/hooks/useFetchProfileInfo';
......@@ -12,9 +12,11 @@ import useMenuButtonColors from '../useMenuButtonColors';
type Props = {
isHomePage?: boolean;
className?: string;
fallbackIconSize?: number;
};
const ProfileMenuDesktop = ({ isHomePage }: Props) => {
const ProfileMenuDesktop = ({ isHomePage, className, fallbackIconSize }: Props) => {
const { data, error, isPending } = useFetchProfileInfo();
const loginUrl = useLoginUrl();
const { themedBackground, themedBorderColor, themedColor } = useMenuButtonColors();
......@@ -81,8 +83,9 @@ const ProfileMenuDesktop = ({ isHomePage }: Props) => {
<Box>
<PopoverTrigger>
<IconButton
className={ className }
aria-label="profile menu"
icon={ <UserAvatar size={ 20 }/> }
icon={ <UserAvatar size={ 20 } fallbackIconSize={ fallbackIconSize }/> }
variant={ variant }
colorScheme="blue"
boxSize="40px"
......@@ -104,4 +107,4 @@ const ProfileMenuDesktop = ({ isHomePage }: Props) => {
);
};
export default ProfileMenuDesktop;
export default chakra(ProfileMenuDesktop);
import type { ButtonProps } from '@chakra-ui/react';
import { Popover, PopoverContent, PopoverBody, PopoverTrigger, Button, Box, useBoolean } from '@chakra-ui/react';
import { Popover, PopoverContent, PopoverBody, PopoverTrigger, Button, Box, useBoolean, chakra } from '@chakra-ui/react';
import React from 'react';
import useIsMobile from 'lib/hooks/useIsMobile';
......@@ -14,9 +14,11 @@ import WalletTooltip from './WalletTooltip';
type Props = {
isHomePage?: boolean;
className?: string;
size?: 'sm' | 'md';
};
const WalletMenuDesktop = ({ isHomePage }: Props) => {
const WalletMenuDesktop = ({ isHomePage, className, size = 'md' }: Props) => {
const { isWalletConnected, address, connect, disconnect, isModalOpening, isModalOpen } = useWallet({ source: 'Header' });
const { themedBackground, themedBorderColor, themedColor } = useMenuButtonColors();
const [ isPopoverOpen, setIsPopoverOpen ] = useBoolean(false);
......@@ -67,6 +69,7 @@ const WalletMenuDesktop = ({ isHomePage }: Props) => {
<Box ml={ 2 }>
<PopoverTrigger>
<Button
className={ className }
variant={ variant }
colorScheme="blue"
flexShrink={ 0 }
......@@ -74,6 +77,7 @@ const WalletMenuDesktop = ({ isHomePage }: Props) => {
loadingText="Connect wallet"
onClick={ isWalletConnected ? openPopover : connect }
fontSize="sm"
size={ size }
{ ...buttonStyles }
>
{ isWalletConnected ? (
......@@ -99,4 +103,4 @@ const WalletMenuDesktop = ({ isHomePage }: Props) => {
);
};
export default WalletMenuDesktop;
export default chakra(WalletMenuDesktop);
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