Skip to content

Commit

Permalink
feat: block page layout A
Browse files Browse the repository at this point in the history
  • Loading branch information
He1DAr committed Feb 1, 2024
1 parent d71d688 commit e9bda0c
Show file tree
Hide file tree
Showing 28 changed files with 1,528 additions and 326 deletions.
11 changes: 6 additions & 5 deletions src/app/PageClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import { SkeletonBlockList } from './_components/BlockList/SkeletonBlockList';
import { PageTitle } from './_components/PageTitle';
import { Stats } from './_components/Stats/Stats';

const BLOCK_LIST_LAYOUT_A_LIMIT = 19;

const BlocksListA = dynamic(
() => import('./_components/BlockList/LayoutA').then(mod => mod.BlockListLayoutA),
const NonPaginatedBlockListLayoutA = dynamic(
() =>
import('./_components/BlockList/LayoutA/NonPaginated').then(
mod => mod.NonPaginatedBlockListLayoutA

Check warning on line 17 in src/app/PageClient.tsx

View check run for this annotation

Codecov / codecov/patch

src/app/PageClient.tsx#L16-L17

Added lines #L16 - L17 were not covered by tests
),
{
loading: () => <SkeletonBlockList />,
ssr: false,
Expand All @@ -40,7 +41,7 @@ export default function Home() {
<TxListTabs limit={DEFAULT_LIST_LIMIT_SMALL} />

{activeNetworkKey.indexOf('naka') !== -1 ? (
<BlocksListA limit={BLOCK_LIST_LAYOUT_A_LIMIT} />
<NonPaginatedBlockListLayoutA />
) : (
<BlocksList limit={DEFAULT_BLOCKS_LIST_LIMIT} />
)}
Expand Down
72 changes: 9 additions & 63 deletions src/app/_components/BlockList/Controls.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,27 @@
import { useColorModeValue } from '@chakra-ui/react';
import { keyframes } from '@emotion/react';
import React from 'react';
import { TfiReload } from 'react-icons/tfi';

import { Flex } from '../../../ui/Flex';
import { FormControl } from '../../../ui/FormControl';
import { FormLabel } from '../../../ui/FormLabel';
import { Icon } from '../../../ui/Icon';
import { Stack } from '../../../ui/Stack';
import { Switch, SwitchProps } from '../../../ui/Switch';
import { Text } from '../../../ui/Text';
import { TextLink } from '../../../ui/TextLink';

const spin = keyframes`
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
`;

interface ControlsProps {
groupByBtc: SwitchProps;
liveUpdates: SwitchProps;
update?: {
isLoading: boolean;
onClick: () => void;
};
latestBlocksCount: number;
horizontal?: boolean;
}

export function Controls({ groupByBtc, liveUpdates, update, latestBlocksCount }: ControlsProps) {
const bgColor = useColorModeValue('purple.100', 'slate.900');
const buttonColor = useColorModeValue('brand', 'purple.400');
const textColor = useColorModeValue('slate.800', 'slate.400');
export function Controls({ groupByBtc, liveUpdates, horizontal }: ControlsProps) {
return (
<>
<Stack borderBottom={update ? undefined : '1px'} py={4} marginX={-6} px={6}>
<Stack
borderBottom={'1px'}
py={4}
marginX={-6}
px={6}
direction={horizontal ? 'row' : 'column'}
>
<Flex justifyContent={'space-between'}>
<FormControl display="flex" alignItems="center" gap={'12px'} minW={0}>
<Switch id="group-by-btc" {...groupByBtc} />
Expand Down Expand Up @@ -67,48 +55,6 @@ export function Controls({ groupByBtc, liveUpdates, update, latestBlocksCount }:
</FormLabel>
</FormControl>
</Stack>

{update && (
<Flex
justifyContent={'space-between'}
backgroundColor={bgColor}
marginX={-6}
px={6}
py={2.5}
gap={1}
>
<Text
fontSize={'14px'}
color={textColor}
textOverflow={'ellipsis'}
overflow={'hidden'}
whiteSpace={'nowrap'}
>
<Text display={'inline'} fontWeight={700}>
{latestBlocksCount}
</Text>{' '}
new Stacks blocks have come in
</Text>
<TextLink href={'javascript:void(0)'} onClick={update.onClick}>
<Flex alignItems={'center'} gap={'6px'}>
<Icon
color={buttonColor}
as={TfiReload}
w={'12px'}
h={'12px'}
transform={'rotate(90deg) scaleX(-1)'}
css={{
animation: `${spin} 0.5s linear infinite`,
animationPlayState: update.isLoading ? 'running' : 'paused',
}}
/>
<Text fontSize={'14px'} color={buttonColor}>
Update
</Text>
</Flex>
</TextLink>
</Flex>
)}
</>
);
}
71 changes: 71 additions & 0 deletions src/app/_components/BlockList/LayoutA/BlockListWithControls.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React from 'react';

import { ListFooter } from '../../../../common/components/ListFooter';
import { Section } from '../../../../common/components/Section';
import { Box } from '../../../../ui/Box';
import { Controls } from '../Controls';
import { UIBlock } from '../types';
import { Blocks } from './Blocks';
import { UpdateBar } from './UpdateBar';
import { useBlockListContext } from './context';

export function BlockListWithControls({
blockList,
latestBlocksCount,
updateList,
enablePagination,
isFetchingNextPage,
hasNextPage,
fetchNextPage,
horizontalControls,
}: {
blockList: UIBlock[];
latestBlocksCount: number;
updateList: () => void;
enablePagination?: boolean;
isFetchingNextPage?: boolean;
hasNextPage?: boolean;
fetchNextPage?: () => void;
horizontalControls?: boolean;
}) {
const { fadeEffect, setFadeEffect, groupedByBtc, setGroupedByBtc, liveUpdates, setLiveUpdates } =
useBlockListContext();
return (
<Section title="Recent Blocks">
<Box pb={6}>
<Controls
groupByBtc={{
onChange: () => {
setGroupedByBtc(!groupedByBtc);

Check warning on line 39 in src/app/_components/BlockList/LayoutA/BlockListWithControls.tsx

View check run for this annotation

Codecov / codecov/patch

src/app/_components/BlockList/LayoutA/BlockListWithControls.tsx#L38-L39

Added lines #L38 - L39 were not covered by tests
},
isChecked: groupedByBtc,
isDisabled: true,
}}
liveUpdates={{
onChange: () => setLiveUpdates(!liveUpdates),

Check warning on line 45 in src/app/_components/BlockList/LayoutA/BlockListWithControls.tsx

View check run for this annotation

Codecov / codecov/patch

src/app/_components/BlockList/LayoutA/BlockListWithControls.tsx#L45

Added line #L45 was not covered by tests
isChecked: liveUpdates,
}}
horizontal={horizontalControls}
/>
{!liveUpdates && (
<UpdateBar
fadeEffect={fadeEffect}
latestBlocksCount={latestBlocksCount}
onClick={updateList}
/>
)}
<Blocks blockList={blockList} fadeEffect={fadeEffect} />
<Box pt={4}>
{(!liveUpdates || !enablePagination) && (
<ListFooter
isLoading={isFetchingNextPage}
hasNextPage={hasNextPage}
fetchNextPage={fetchNextPage}
label={'blocks'}
/>
)}
</Box>
</Box>
</Section>
);
}
56 changes: 56 additions & 0 deletions src/app/_components/BlockList/LayoutA/Blocks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';

import { Icon } from '../../../../ui/Icon';
import { Stack } from '../../../../ui/Stack';
import { StxIcon } from '../../../../ui/icons';
import { UIBlock, UIBlockType } from '../types';
import { BlockCount } from './BlockCount';
import { BurnBlock } from './BurnBlock';
import { StxBlock } from './StxBlock';
import { FADE_DURATION } from './consts';

export function Blocks({ blockList, fadeEffect }: { blockList: UIBlock[]; fadeEffect: boolean }) {
return (
<Stack
pl={4}
pr={2}
gap={0}
width={'full'}
style={{
transition: `opacity ${FADE_DURATION / 1000}s`,
opacity: fadeEffect ? 0 : 1,
}}
>
{blockList.map((block, i) => {
switch (block.type) {
case UIBlockType.Block:
return (
<StxBlock
key={block.hash}
hash={block.hash}
height={block.height}
timestamp={block.timestamp}
txsCount={block.txsCount}
icon={
i === 0 || (i > 0 && blockList[i - 1].type === UIBlockType.BurnBlock) ? (
<Icon as={StxIcon} size={2.5} color={'white'} />
) : undefined
}
/>
);
case UIBlockType.BurnBlock:
return (
<BurnBlock
key={block.hash}
hash={block.hash}
height={block.height}
timestamp={block.timestamp}
/>
);
case UIBlockType.Count:
return <BlockCount key={block.count} count={block.count} />;
}
})}
</Stack>
);
}
6 changes: 4 additions & 2 deletions src/app/_components/BlockList/LayoutA/BurnBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ export const BurnBlock = memo(function ({ timestamp, height, hash }: ListItemPro
justifyContent={'space-between'}
alignItems={'center'}
borderBottom={'1px'}
px={4}
pl={4}
pr={8}
height={14}
backgroundColor={bgColor}
marginX={'-6'}
mr={'-8'}
ml={'-10'}
color={textColor}
>
<HStack gap={1.5}>
Expand Down
54 changes: 54 additions & 0 deletions src/app/_components/BlockList/LayoutA/NonPaginated.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use client';

import React, { useCallback, useState } from 'react';

Check warning on line 3 in src/app/_components/BlockList/LayoutA/NonPaginated.tsx

View check run for this annotation

Codecov / codecov/patch

src/app/_components/BlockList/LayoutA/NonPaginated.tsx#L3

Added line #L3 was not covered by tests

import { ListFooter } from '../../../../common/components/ListFooter';
import { Section } from '../../../../common/components/Section';

Check warning on line 6 in src/app/_components/BlockList/LayoutA/NonPaginated.tsx

View check run for this annotation

Codecov / codecov/patch

src/app/_components/BlockList/LayoutA/NonPaginated.tsx#L6

Added line #L6 was not covered by tests
import { Box } from '../../../../ui/Box';
import { Icon } from '../../../../ui/Icon';
import { Stack } from '../../../../ui/Stack';
import { StxIcon } from '../../../../ui/icons';
import { ExplorerErrorBoundary } from '../../ErrorBoundary';

Check warning on line 11 in src/app/_components/BlockList/LayoutA/NonPaginated.tsx

View check run for this annotation

Codecov / codecov/patch

src/app/_components/BlockList/LayoutA/NonPaginated.tsx#L11

Added line #L11 was not covered by tests
import { Controls } from '../Controls';
import { UIBlockType } from '../types';
import { BlockCount } from './BlockCount';
import { BlockListWithControls } from './BlockListWithControls';

Check warning on line 15 in src/app/_components/BlockList/LayoutA/NonPaginated.tsx

View check run for this annotation

Codecov / codecov/patch

src/app/_components/BlockList/LayoutA/NonPaginated.tsx#L15

Added line #L15 was not covered by tests
import { BurnBlock } from './BurnBlock';
import { BlockListProvider } from './Provider';

Check warning on line 17 in src/app/_components/BlockList/LayoutA/NonPaginated.tsx

View check run for this annotation

Codecov / codecov/patch

src/app/_components/BlockList/LayoutA/NonPaginated.tsx#L17

Added line #L17 was not covered by tests
import { StxBlock } from './StxBlock';
import { UpdateBar } from './UpdateBar';
import { useBlockListContext } from './context';
import { useBlockList } from './useBlockList';

Check warning on line 21 in src/app/_components/BlockList/LayoutA/NonPaginated.tsx

View check run for this annotation

Codecov / codecov/patch

src/app/_components/BlockList/LayoutA/NonPaginated.tsx#L21

Added line #L21 was not covered by tests

const LIST_LENGTH = 17;

Check warning on line 23 in src/app/_components/BlockList/LayoutA/NonPaginated.tsx

View check run for this annotation

Codecov / codecov/patch

src/app/_components/BlockList/LayoutA/NonPaginated.tsx#L23

Added line #L23 was not covered by tests

function NonPaginatedBlockListLayoutABase() {
const { blockList, updateList, latestBlocksCount } = useBlockList(LIST_LENGTH);

Check warning on line 26 in src/app/_components/BlockList/LayoutA/NonPaginated.tsx

View check run for this annotation

Codecov / codecov/patch

src/app/_components/BlockList/LayoutA/NonPaginated.tsx#L25-L26

Added lines #L25 - L26 were not covered by tests

return (
<BlockListWithControls
blockList={blockList}
latestBlocksCount={latestBlocksCount}
updateList={updateList}
/>
);
}

export function NonPaginatedBlockListLayoutA() {

Check warning on line 37 in src/app/_components/BlockList/LayoutA/NonPaginated.tsx

View check run for this annotation

Codecov / codecov/patch

src/app/_components/BlockList/LayoutA/NonPaginated.tsx#L37

Added line #L37 was not covered by tests
return (
<ExplorerErrorBoundary
Wrapper={Section}
wrapperProps={{
title: 'Recent Blocks',
gridColumnStart: ['1', '1', '2'],
gridColumnEnd: ['2', '2', '3'],
minWidth: 0,
}}
tryAgainButton
>
<BlockListProvider>
<NonPaginatedBlockListLayoutABase />
</BlockListProvider>
</ExplorerErrorBoundary>
);
}
Loading

0 comments on commit e9bda0c

Please sign in to comment.