mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
marketplace app page
This commit is contained in:
+2
-2
@@ -16,7 +16,7 @@ import config from 'configs/app';
|
||||
import getQueryParamString from 'lib/router/getQueryParamString';
|
||||
import LayoutApp from 'ui/shared/layout/LayoutApp';
|
||||
|
||||
// const MarketplaceApp = dynamic(() => import('ui/pages/MarketplaceApp'), { ssr: false });
|
||||
const MarketplaceApp = dynamic(() => import('ui/pages/MarketplaceApp'), { ssr: false });
|
||||
|
||||
const pathname: Route['pathname'] = '/apps/[id]';
|
||||
const feature = config.features.marketplace;
|
||||
@@ -24,7 +24,7 @@ const feature = config.features.marketplace;
|
||||
const Page: NextPageWithLayout<Props<typeof pathname>> = (props: Props<typeof pathname>) => {
|
||||
return (
|
||||
<PageNextJs pathname={ pathname } query={ props.query } apiData={ props.apiData }>
|
||||
{ /* <MarketplaceApp/> */ }
|
||||
<MarketplaceApp/>
|
||||
</PageNextJs>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { LinkBox, Flex, LinkOverlay } from '@chakra-ui/react';
|
||||
import { LinkBox, Flex, LinkOverlay, Text } from '@chakra-ui/react';
|
||||
import type { MouseEvent } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
@@ -143,15 +143,11 @@ const FeaturedApp = ({
|
||||
|
||||
<Skeleton
|
||||
loading={ isLoading }
|
||||
textStyle="sm"
|
||||
WebkitLineClamp={ 2 }
|
||||
style={{
|
||||
WebkitBoxOrient: 'vertical',
|
||||
}}
|
||||
display="-webkit-box"
|
||||
overflow="hidden"
|
||||
asChild
|
||||
>
|
||||
{ shortDescription }
|
||||
<Text lineClamp={ 2 } textStyle="sm">
|
||||
{ shortDescription }
|
||||
</Text>
|
||||
</Skeleton>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { LinkBox, Flex } from '@chakra-ui/react';
|
||||
import { LinkBox, Flex, Text } from '@chakra-ui/react';
|
||||
import type { MouseEvent } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
@@ -125,15 +125,11 @@ const FeaturedAppMobile = ({
|
||||
|
||||
<Skeleton
|
||||
loading={ isLoading }
|
||||
textStyle="xs"
|
||||
WebkitLineClamp={ 3 }
|
||||
style={{
|
||||
WebkitBoxOrient: 'vertical',
|
||||
}}
|
||||
display="-webkit-box"
|
||||
overflow="hidden"
|
||||
asChild
|
||||
>
|
||||
{ shortDescription }
|
||||
<Text lineClamp={ 3 } textStyle="xs">
|
||||
{ shortDescription }
|
||||
</Text>
|
||||
</Skeleton>
|
||||
</Flex>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { LinkBox, chakra, Flex } from '@chakra-ui/react';
|
||||
import { LinkBox, chakra, Flex, Text } from '@chakra-ui/react';
|
||||
import type { MouseEvent } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
@@ -161,15 +161,11 @@ const MarketplaceAppCard = ({
|
||||
|
||||
<Skeleton
|
||||
loading={ isLoading }
|
||||
textStyle="sm"
|
||||
WebkitLineClamp={{ base: 2, md: 3 }}
|
||||
style={{
|
||||
WebkitBoxOrient: 'vertical',
|
||||
}}
|
||||
display="-webkit-box"
|
||||
overflow="hidden"
|
||||
asChild
|
||||
>
|
||||
{ shortDescription }
|
||||
<Text lineClamp={{ base: 2, md: 3 }} textStyle="sm">
|
||||
{ shortDescription }
|
||||
</Text>
|
||||
</Skeleton>
|
||||
|
||||
{ !isLoading && (
|
||||
|
||||
@@ -18,8 +18,9 @@ const MarketplaceAppCardLink = ({ url, external, id, title, onClick, className }
|
||||
onClick?.(event, id);
|
||||
}, [ onClick, id ]);
|
||||
|
||||
// TODO @tom2drum create LinkOverlay component
|
||||
return external ? (
|
||||
<LinkOverlay href={ url } marginRight={ 2 } className={ className }>
|
||||
<LinkOverlay href={ url } marginRight={ 2 } className={ className } target="_blank">
|
||||
{ title }
|
||||
</LinkOverlay>
|
||||
) : (
|
||||
|
||||
@@ -8,11 +8,12 @@ import Content from './MarketplaceAppInfo/Content';
|
||||
|
||||
interface Props {
|
||||
data: MarketplaceAppOverview | undefined;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const MarketplaceAppInfo = ({ data }: Props) => {
|
||||
const MarketplaceAppInfo = ({ data, isLoading }: Props) => {
|
||||
return (
|
||||
<InfoButton>
|
||||
<InfoButton isLoading={ isLoading }>
|
||||
<Content data={ data }/>
|
||||
</InfoButton>
|
||||
);
|
||||
|
||||
@@ -34,13 +34,13 @@ const Content = ({ data }: Props) => {
|
||||
return (
|
||||
<Flex fontSize="sm" flexDir="column" rowGap={ 5 }>
|
||||
<div>
|
||||
<Text variant="secondary" fontSize="xs">Project info</Text>
|
||||
<Text color="text.secondary" textStyle="xs">Project info</Text>
|
||||
<Text fontSize="sm" mt={ 3 }>{ data?.shortDescription }</Text>
|
||||
<WebsiteLink url={ data?.site }/>
|
||||
</div>
|
||||
{ socialLinks.length > 0 && (
|
||||
<div>
|
||||
<Text variant="secondary" fontSize="xs">Links</Text>
|
||||
<Text color="text.secondary" textStyle="xs">Links</Text>
|
||||
<Grid templateColumns={{ base: 'repeat(2, 1fr)', lg: 'repeat(3, 1fr)' }} columnGap={ 4 } rowGap={ 3 } mt={ 3 }>
|
||||
{ socialLinks.map((link, index) => <SocialLink key={ index } { ...link }/>) }
|
||||
</Grid>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Link } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import makePrettyLink from 'lib/makePrettyLink';
|
||||
import { Link } from 'toolkit/chakra/link';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
@@ -12,23 +13,18 @@ const WebsiteLink = ({ url }: Props) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
function getHostname(url: string) {
|
||||
try {
|
||||
return new URL(url).hostname;
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
return (
|
||||
<Link
|
||||
external
|
||||
noIcon
|
||||
href={ url }
|
||||
target="_blank"
|
||||
display="inline-flex"
|
||||
alignItems="center"
|
||||
columnGap={ 1 }
|
||||
mt={ 3 }
|
||||
>
|
||||
<IconSvg name="link" boxSize={ 5 } color="text_secondary"/>
|
||||
<span>{ getHostname(url) }</span>
|
||||
<IconSvg name="link" boxSize={ 5 } color="text.secondary"/>
|
||||
<span>{ makePrettyLink(url)?.domain }</span>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ import config from 'configs/app';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import { nbsp } from 'lib/html-entities';
|
||||
import isBrowser from 'lib/isBrowser';
|
||||
import makePrettyLink from 'lib/makePrettyLink';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
import { Badge } from 'toolkit/chakra/badge';
|
||||
import { Button } from 'toolkit/chakra/button';
|
||||
@@ -129,12 +130,6 @@ const MarketplaceAppModal = ({
|
||||
const isMobile = useIsMobile();
|
||||
const logoUrl = useColorModeValue(logo, logoDarkMode || logo);
|
||||
|
||||
function getHostname(url: string | undefined) {
|
||||
try {
|
||||
return new URL(url || '').hostname;
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
const iconColor = { _light: 'blue.600', _dark: 'gray.400' };
|
||||
|
||||
return (
|
||||
@@ -323,7 +318,7 @@ const MarketplaceAppModal = ({
|
||||
overflow="hidden"
|
||||
textOverflow="ellipsis"
|
||||
>
|
||||
{ getHostname(site) }
|
||||
{ makePrettyLink(site)?.domain }
|
||||
</Text>
|
||||
</Link>
|
||||
) }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { chakra, Flex, Tooltip } from '@chakra-ui/react';
|
||||
import { chakra, Flex } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { MarketplaceAppOverview, MarketplaceAppSecurityReport, ContractListTypes } from 'types/client/marketplace';
|
||||
@@ -8,11 +8,10 @@ import { route } from 'nextjs-routes';
|
||||
import config from 'configs/app';
|
||||
import { useAppContext } from 'lib/contexts/app';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import makePrettyLink from 'lib/makePrettyLink';
|
||||
import { Link } from 'toolkit/chakra/link';
|
||||
import RewardsButton from 'ui/rewards/RewardsButton';
|
||||
import Skeleton from 'ui/shared/chakra/Skeleton';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import LinkExternal from 'ui/shared/links/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/links/LinkInternal';
|
||||
import ButtonBackTo from 'ui/shared/buttons/ButtonBackTo';
|
||||
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
|
||||
import UserProfileDesktop from 'ui/snippets/user/profile/UserProfileDesktop';
|
||||
import UserWalletDesktop from 'ui/snippets/user/wallet/UserWalletDesktop';
|
||||
@@ -44,41 +43,34 @@ const MarketplaceAppTopBar = ({ appId, data, isLoading, securityReport }: Props)
|
||||
return route({ pathname: '/apps' });
|
||||
}, [ appProps.referrer ]);
|
||||
|
||||
function getHostname(url: string | undefined) {
|
||||
try {
|
||||
return new URL(url || '').hostname;
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
const showContractList = React.useCallback((id: string, type: ContractListTypes) => setContractListType(type), []);
|
||||
const hideContractList = React.useCallback(() => setContractListType(undefined), []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex alignItems="center" 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>
|
||||
<LinkExternal
|
||||
{ !isMobile && <NetworkLogo isCollapsed mr={ 4 }/> }
|
||||
<ButtonBackTo
|
||||
href={ goBackUrl }
|
||||
hint="Back to dApps list"
|
||||
size="sm"
|
||||
loading={ isLoading }
|
||||
/>
|
||||
<Link
|
||||
external
|
||||
href={ data?.url }
|
||||
variant="subtle"
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
variant="underlaid"
|
||||
textStyle="sm"
|
||||
minW={ 0 }
|
||||
maxW={{ base: 'calc(100% - 114px)', md: 'auto' }}
|
||||
display="flex"
|
||||
isLoading={ isLoading }
|
||||
loading={ isLoading }
|
||||
>
|
||||
<chakra.span isTruncated>
|
||||
{ getHostname(data?.url) }
|
||||
<chakra.span truncate>
|
||||
{ makePrettyLink(data?.url)?.domain }
|
||||
</chakra.span>
|
||||
</LinkExternal>
|
||||
<Skeleton isLoaded={ !isLoading }>
|
||||
<MarketplaceAppInfo data={ data }/>
|
||||
</Skeleton>
|
||||
</Link>
|
||||
<MarketplaceAppInfo data={ data } isLoading={ isLoading }/>
|
||||
{ (securityReport || isLoading) && (
|
||||
<AppSecurityReport
|
||||
id={ data?.id || '' }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Center, useColorMode, Flex } from '@chakra-ui/react';
|
||||
import { Center, chakra, Flex } from '@chakra-ui/react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { DappscoutIframeProvider, useDappscoutIframe } from 'dappscout-iframe';
|
||||
import { useRouter } from 'next/router';
|
||||
@@ -16,6 +16,7 @@ import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
|
||||
import useFetch from 'lib/hooks/useFetch';
|
||||
import * as metadata from 'lib/metadata';
|
||||
import getQueryParamString from 'lib/router/getQueryParamString';
|
||||
import { useColorMode } from 'toolkit/chakra/color-mode';
|
||||
import ContentLoader from 'ui/shared/ContentLoader';
|
||||
|
||||
import MarketplaceAppTopBar from '../marketplace/MarketplaceAppTopBar';
|
||||
@@ -82,12 +83,11 @@ const MarketplaceAppContent = ({ address, data, isPending, appUrl }: Props) => {
|
||||
) }
|
||||
|
||||
{ (data && isReady) && (
|
||||
<Box
|
||||
<chakra.iframe
|
||||
key={ iframeKey }
|
||||
allow={ IFRAME_ALLOW_ATTRIBUTE }
|
||||
ref={ iframeRef }
|
||||
sandbox={ IFRAME_SANDBOX_ATTRIBUTE }
|
||||
as="iframe"
|
||||
h="100%"
|
||||
w="100%"
|
||||
display={ isFrameLoading ? 'none' : 'block' }
|
||||
|
||||
@@ -346,15 +346,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading, addressFormat }: Pr
|
||||
}
|
||||
case 'app': {
|
||||
return (
|
||||
<Text
|
||||
overflow="hidden"
|
||||
textOverflow="ellipsis"
|
||||
style={{
|
||||
WebkitLineClamp: 3,
|
||||
WebkitBoxOrient: 'vertical',
|
||||
display: '-webkit-box',
|
||||
}}
|
||||
>
|
||||
<Text lineClamp={ 3 }>
|
||||
{ data.app.description }
|
||||
</Text>
|
||||
);
|
||||
|
||||
@@ -8,9 +8,10 @@ import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const InfoButton = ({ children }: Props) => {
|
||||
const InfoButton = ({ children, isLoading }: Props) => {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const triggerButton = (
|
||||
@@ -22,6 +23,7 @@ const InfoButton = ({ children }: Props) => {
|
||||
fontWeight={ 500 }
|
||||
pl={ 1 }
|
||||
pr={ isMobile ? 1 : 2 }
|
||||
loadingSkeleton={ isLoading }
|
||||
>
|
||||
<IconSvg name="info" boxSize={ 6 } mr={ isMobile ? 0 : 1 }/>
|
||||
{ !isMobile && <span>Info</span> }
|
||||
|
||||
@@ -49,13 +49,7 @@ const SearchBarSuggestApp = ({ data, isMobile, searchTerm, onClick }: Props) =>
|
||||
</Flex>
|
||||
<Text
|
||||
color="text.secondary"
|
||||
overflow="hidden"
|
||||
textOverflow="ellipsis"
|
||||
style={{
|
||||
WebkitLineClamp: 3,
|
||||
WebkitBoxOrient: 'vertical',
|
||||
display: '-webkit-box',
|
||||
}}
|
||||
lineClamp={ 3 }
|
||||
>
|
||||
{ data.description }
|
||||
</Text>
|
||||
|
||||
Reference in New Issue
Block a user