Commit 2352a973 authored by tom's avatar tom

refactor page layout

parent 7f300dbe
import type { GetStaticPaths } from 'next';
export const getStaticPaths: GetStaticPaths = async() => {
return { paths: [], fallback: true };
};
import type { NextPage } from 'next';
import Head from 'next/head';
import React from 'react';
import App from 'ui/pages/App';
const AppPage: NextPage = () => {
return (
<>
<Head><title>App Card Page</title></Head>
<App/>
</>
);
};
export default AppPage;
export { getStaticPaths } from 'lib/next/apps/getStaticPaths';
export { getStaticProps } from 'lib/next/getStaticProps';
import { VStack, Textarea, Button, Alert, AlertTitle, AlertDescription, Link, Code } from '@chakra-ui/react'; import type { NextPage } from 'next';
import type { NextPage, GetStaticPaths } from 'next'; import Head from 'next/head';
import { useRouter } from 'next/router';
import type { ChangeEvent } from 'react';
import React from 'react'; import React from 'react';
import * as cookies from 'lib/cookies'; import Home from 'ui/pages/Home';
import useNetwork from 'lib/hooks/useNetwork';
import useToast from 'lib/hooks/useToast';
import getAvailablePaths from 'lib/networks/getAvailablePaths';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
const Home: NextPage = () => {
const router = useRouter();
const selectedNetwork = useNetwork();
const toast = useToast();
const [ isFormVisible, setFormVisibility ] = React.useState(false);
const [ token, setToken ] = React.useState('');
React.useEffect(() => {
const token = cookies.get(cookies.NAMES.API_TOKEN);
setFormVisibility(Boolean(!token && selectedNetwork?.isAccountSupported));
}, [ selectedNetwork?.isAccountSupported ]);
const handleTokenChange = React.useCallback((event: ChangeEvent<HTMLTextAreaElement>) => {
setToken(event.target.value);
}, []);
const handleSetTokenClick = React.useCallback(() => {
cookies.set(cookies.NAMES.API_TOKEN, token);
setToken('');
toast({
position: 'top-right',
title: 'Success 🥳',
description: 'Successfully set cookie',
status: 'success',
variant: 'subtle',
isClosable: true,
onCloseComplete: () => {
setFormVisibility(false);
},
});
}, [ toast, token ]);
const prodUrl = new URL(`/${ router.query.network_type }/${ router.query.network_sub_type }`, 'https://blockscout.com').toString();
const HomePage: NextPage = () => {
return ( return (
<Page>
<VStack gap={ 4 } alignItems="flex-start" maxW="800px">
<PageTitle text={
`Home Page for ${ selectedNetwork?.name } network`
}/>
{ /* will be deleted when we move to new CI */ }
{ isFormVisible && (
<> <>
<Alert status="error" flexDirection="column" alignItems="flex-start"> <Head><title>Home Page</title></Head>
<AlertTitle fontSize="md"> <Home/>
!!! Temporary solution for authentication !!!
</AlertTitle>
<AlertDescription mt={ 3 }>
To Sign in go to <Link href={ prodUrl } target="_blank">{ prodUrl }</Link> first, sign in there, copy obtained API token from cookie
<Code ml={ 1 }>{ cookies.NAMES.API_TOKEN }</Code> and paste it in the form below. After submitting the form you should be successfully
authenticated in current environment
</AlertDescription>
</Alert>
<Textarea value={ token } onChange={ handleTokenChange } placeholder="API token"/>
<Button onClick={ handleSetTokenClick }>Set cookie</Button>
</> </>
) }
</VStack>
</Page>
); );
}; };
export default Home; export default HomePage;
export const getStaticPaths: GetStaticPaths = async() => {
return { paths: getAvailablePaths(), fallback: false };
};
export const getStaticProps = async() => { export { getStaticPaths } from 'lib/next/account/getStaticPaths';
return { export { getStaticProps } from 'lib/next/getStaticProps';
props: {},
};
};
...@@ -45,6 +45,8 @@ const Header = () => { ...@@ -45,6 +45,8 @@ const Header = () => {
width="100%" width="100%"
alignItems="center" alignItems="center"
justifyContent="center" justifyContent="center"
paddingX={ 12 }
paddingTop={ 9 }
gap={ 12 } gap={ 12 }
> >
<SearchBar/> <SearchBar/>
......
import { Center, useColorModeValue } from '@chakra-ui/react';
import React from 'react';
import Page from 'ui/shared/Page/Page';
const App = () => {
return (
<Page wrapChildren={ false } rowGap={ 10 }>
<Center bgColor={ useColorModeValue('blackAlpha.200', 'whiteAlpha.200') } h="100%" w="100%" flexGrow={ 1 }>
3rd party app content
</Center>
</Page>
);
};
export default App;
import { VStack, Textarea, Button, Alert, AlertTitle, AlertDescription, Link, Code } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import type { ChangeEvent } from 'react';
import React from 'react';
import * as cookies from 'lib/cookies';
import useNetwork from 'lib/hooks/useNetwork';
import useToast from 'lib/hooks/useToast';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
const Home = () => {
const router = useRouter();
const selectedNetwork = useNetwork();
const toast = useToast();
const [ isFormVisible, setFormVisibility ] = React.useState(false);
const [ token, setToken ] = React.useState('');
React.useEffect(() => {
const token = cookies.get(cookies.NAMES.API_TOKEN);
setFormVisibility(Boolean(!token && selectedNetwork?.isAccountSupported));
}, [ selectedNetwork?.isAccountSupported ]);
const handleTokenChange = React.useCallback((event: ChangeEvent<HTMLTextAreaElement>) => {
setToken(event.target.value);
}, []);
const handleSetTokenClick = React.useCallback(() => {
cookies.set(cookies.NAMES.API_TOKEN, token);
setToken('');
toast({
position: 'top-right',
title: 'Success 🥳',
description: 'Successfully set cookie',
status: 'success',
variant: 'subtle',
isClosable: true,
onCloseComplete: () => {
setFormVisibility(false);
},
});
}, [ toast, token ]);
const prodUrl = new URL(`/${ router.query.network_type }/${ router.query.network_sub_type }`, 'https://blockscout.com').toString();
return (
<Page>
<VStack gap={ 4 } alignItems="flex-start" maxW="800px">
<PageTitle text={
`Home Page for ${ selectedNetwork?.name } network`
}/>
{ /* will be deleted when we move to new CI */ }
{ isFormVisible && (
<>
<Alert status="error" flexDirection="column" alignItems="flex-start">
<AlertTitle fontSize="md">
!!! Temporary solution for authentication !!!
</AlertTitle>
<AlertDescription mt={ 3 }>
To Sign in go to <Link href={ prodUrl } target="_blank">{ prodUrl }</Link> first, sign in there, copy obtained API token from cookie
<Code ml={ 1 }>{ cookies.NAMES.API_TOKEN }</Code> and paste it in the form below. After submitting the form you should be successfully
authenticated in current environment
</AlertDescription>
</Alert>
<Textarea value={ token } onChange={ handleTokenChange } placeholder="API token"/>
<Button onClick={ handleSetTokenClick }>Set cookie</Button>
</>
) }
</VStack>
</Page>
);
};
export default Home;
import { ArrowBackIcon } from '@chakra-ui/icons'; import { ArrowBackIcon } from '@chakra-ui/icons';
import { Box, Link, Text } from '@chakra-ui/react'; import { Link, Text } from '@chakra-ui/react';
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import { animateScroll } from 'react-scroll'; import { animateScroll } from 'react-scroll';
...@@ -77,7 +77,6 @@ const PublicTagsComponent: React.FC = () => { ...@@ -77,7 +77,6 @@ const PublicTagsComponent: React.FC = () => {
return ( return (
<Page> <Page>
<Box h="100%">
{ isMobile && screen === 'form' && ( { isMobile && screen === 'form' && (
<Link display="inline-flex" alignItems="center" mb={ 6 } onClick={ onGoBack }> <Link display="inline-flex" alignItems="center" mb={ 6 } onClick={ onGoBack }>
<ArrowBackIcon w={ 6 } h={ 6 }/> <ArrowBackIcon w={ 6 } h={ 6 }/>
...@@ -86,7 +85,6 @@ const PublicTagsComponent: React.FC = () => { ...@@ -86,7 +85,6 @@ const PublicTagsComponent: React.FC = () => {
) } ) }
<PageTitle text={ header }/> <PageTitle text={ header }/>
{ content } { content }
</Box>
</Page> </Page>
); );
}; };
......
import { Box, HStack, VStack } from '@chakra-ui/react'; import { chakra, VStack, Grid, GridItem } from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
...@@ -8,12 +8,15 @@ import useFetch from 'lib/hooks/useFetch'; ...@@ -8,12 +8,15 @@ import useFetch from 'lib/hooks/useFetch';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import Header from 'ui/blocks/header/Header'; import Header from 'ui/blocks/header/Header';
import NavigationDesktop from 'ui/blocks/navigation/NavigationDesktop'; import NavigationDesktop from 'ui/blocks/navigation/NavigationDesktop';
import PageContent from 'ui/shared/Page/PageContent';
interface Props { interface Props {
children: React.ReactNode; children: React.ReactNode;
wrapChildren?: boolean;
className?: string;
} }
const Page = ({ children }: Props) => { const Page = ({ children, wrapChildren = true, className }: Props) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const router = useRouter(); const router = useRouter();
const fetch = useFetch(); const fetch = useFetch();
...@@ -32,25 +35,32 @@ const Page = ({ children }: Props) => { ...@@ -32,25 +35,32 @@ const Page = ({ children }: Props) => {
} }
}, [ networkType, networkSubType ]); }, [ networkType, networkSubType ]);
const renderedChildren = wrapChildren ? (
<PageContent>{ children }</PageContent>
) : children;
if (isMobile) {
return ( return (
<HStack <VStack width="100%" minH="100vh" spacing={ 0 } className={ className }>
w="100%"
minH="100vh"
alignItems="stretch"
>
{ !isMobile && <NavigationDesktop/> }
<VStack width="100%" paddingX={ isMobile ? 4 : 8 } paddingTop={ isMobile ? 0 : 9 } paddingBottom={ 10 } spacing={ 0 }>
<Header/> <Header/>
<Box { renderedChildren }
as="main"
w="100%"
paddingTop={ isMobile ? '138px' : '52px' }
>
{ children }
</Box>
</VStack> </VStack>
</HStack> );
}
return (
<Grid templateColumns="auto 1fr" templateRows="auto 1fr" rowGap="52px" className={ className }>
<GridItem rowSpan={ 2 } colSpan={ 1 }>
<NavigationDesktop/>
</GridItem>
<GridItem>
<Header/>
</GridItem>
<GridItem>
{ renderedChildren }
</GridItem>
</Grid>
); );
}; };
export default Page; export default chakra(Page);
import { Box } from '@chakra-ui/react';
import React from 'react';
interface Props {
children: React.ReactNode;
}
const PageContent = ({ children }: Props) => {
return (
<Box
as="main"
w="100%"
paddingX={{ base: 4, lg: 12 }}
paddingBottom={ 10 }
paddingTop={{ base: '138px', lg: 0 }}
>
{ children }
</Box>
);
};
export default PageContent;
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