diff --git a/src/apps/explorer/components/SummaryCardsWidget/SummaryCards.tsx b/src/apps/explorer/components/SummaryCardsWidget/SummaryCards.tsx new file mode 100644 index 000000000..447aed6ce --- /dev/null +++ b/src/apps/explorer/components/SummaryCardsWidget/SummaryCards.tsx @@ -0,0 +1,97 @@ +import React from 'react' +import styled from 'styled-components' +import { media } from 'theme/styles/media' + +import { Card, CardContent } from 'components/common/Card' +import { TotalSummaryResponse } from '.' + +const Wrapper = styled.div` + display: grid; + grid-template-columns: 0.7fr 2.35fr; + grid-template-areas: 'one two'; + + > div:first-child { + justify-content: flex-end; + } +` + +const WrapperDoubleContent = styled.div<{ column?: boolean }>` + display: flex; + flex-direction: ${({ column }): string => (column ? 'column' : 'row')}; + justify-content: flex-start; + flex: 1; + gap: 3.5rem; + + > div { + text-align: center; + } + + ${media.mediumDown} { + flex-direction: column; + } +` +const CardRow = styled.div` + grid-area: one; + display: flex; + flex-wrap: wrap; + align-items: stretch; +` +const WrapperTwo = styled.div` + grid-area: two; + display: flex; + flex: 1; +` + +export function SummaryCards({ summaryData }: { summaryData: TotalSummaryResponse }): JSX.Element { + const { batchInfo, dailyTransactions, totalTokens, dailyFees, monthSurplus, isLoading } = summaryData + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/src/apps/explorer/components/SummaryCardsWidget/index.tsx b/src/apps/explorer/components/SummaryCardsWidget/index.tsx new file mode 100644 index 000000000..bb206f436 --- /dev/null +++ b/src/apps/explorer/components/SummaryCardsWidget/index.tsx @@ -0,0 +1,43 @@ +import React, { useEffect, useState } from 'react' +import { SummaryCards } from './SummaryCards' + +import summaryData from './summaryGraphResp.json' + +const DELAY_SECONDS = 3 // Emulating API request + +interface TotalSummary { + batchInfo: { lastBatchDate: string; batchId: string } + dailyTransactions: { now: number; before: string } + totalTokens: number + dailyFees: { now: string; before: string } + monthSurplus: { now: string; before: string } +} + +export type TotalSummaryResponse = TotalSummary & { + isLoading: boolean +} + +function useGetTotalSummary(): TotalSummaryResponse { + const [summary, setSummary] = useState({ + batchInfo: { lastBatchDate: '', batchId: '' }, + dailyTransactions: { now: 0, before: '' }, + totalTokens: 0, + dailyFees: { now: '', before: '' }, + monthSurplus: { now: '', before: '' }, + isLoading: true, + }) + + useEffect(() => { + const timer = setTimeout(() => setSummary({ ...summaryData, isLoading: false }), DELAY_SECONDS * 1000) + + return (): void => clearTimeout(timer) + }, []) + + return summary +} + +export function SummaryCardsWidget(): JSX.Element { + const summary = useGetTotalSummary() + + return +} diff --git a/src/apps/explorer/components/SummaryCardsWidget/summaryGraphResp.json b/src/apps/explorer/components/SummaryCardsWidget/summaryGraphResp.json new file mode 100644 index 000000000..5c720a0f4 --- /dev/null +++ b/src/apps/explorer/components/SummaryCardsWidget/summaryGraphResp.json @@ -0,0 +1,8 @@ +{ + + "batchInfo": { "lastBatchDate": "3m 42s Ago", "batchId": "fd3f932" }, + "dailyTransactions": {"now": 194, "before": "+1.2%"}, + "totalTokens": 193, + "dailyFees": {"now": "$33.3K", "before": "-3.23%"}, + "monthSurplus": {"now": "$53.9K", "before": "14.49%"} +} \ No newline at end of file diff --git a/src/apps/explorer/components/common/ShimmerBar/index.tsx b/src/apps/explorer/components/common/ShimmerBar/index.tsx new file mode 100644 index 000000000..134f72c7b --- /dev/null +++ b/src/apps/explorer/components/common/ShimmerBar/index.tsx @@ -0,0 +1,31 @@ +import styled, { keyframes } from 'styled-components' + +const ShimmerKeyframe = keyframes` + 0% { + background-position: 0px top; + } + 90% { + background-position: 300px top; + } + 100% { + background-position: 300px top; + } +` + +const ShimmerBar = styled.div` + width: 100%; + height: 12px; + border-radius: 2px; + margin-bottom: 20px; + color: white; + background: ${({ theme }): string => + `${theme.greyOpacity} -webkit-gradient(linear, 100% 0, 0 0, from(${theme.greyOpacity}), color-stop(0.5, ${theme.borderPrimary}), to(${theme.gradient1}))`}; + background-position: -5rem top; + background-repeat: no-repeat; + -webkit-animation-name: ${ShimmerKeyframe}; + -webkit-animation-duration: 1.3s; + -webkit-animation-iteration-count: infinite; + -webkit-background-size: 5rem 100%; +` + +export default ShimmerBar diff --git a/src/apps/explorer/pages/Home/index.tsx b/src/apps/explorer/pages/Home/index.tsx index 497c8715c..b08bd2d11 100644 --- a/src/apps/explorer/pages/Home/index.tsx +++ b/src/apps/explorer/pages/Home/index.tsx @@ -3,11 +3,12 @@ import { Search } from 'apps/explorer/components/common/Search' import { Wrapper as WrapperMod } from 'apps/explorer/pages/styled' import styled from 'styled-components' import { media } from 'theme/styles/media' +import { SummaryCardsWidget } from 'apps/explorer/components/SummaryCardsWidget' const Wrapper = styled(WrapperMod)` max-width: 140rem; flex-flow: column wrap; - justify-content: center; + justify-content: flex-start; display: flex; > h1 { @@ -23,9 +24,19 @@ const Wrapper = styled(WrapperMod)` } ` +const SummaryWrapper = styled.section` + display: grid; + /* grid-template-columns: 35fr 65fr; // There will be 2 sections */ + grid-gap: 1 rem; + padding-bottom: 5rem; +` + export const Home: React.FC = () => { return ( + + +

Search on CoW Protocol Explorer

diff --git a/src/components/common/Card/Card.tsx b/src/components/common/Card/Card.tsx new file mode 100644 index 000000000..e591a7ffa --- /dev/null +++ b/src/components/common/Card/Card.tsx @@ -0,0 +1,54 @@ +import React from 'react' +import styled from 'styled-components' + +import { COLOURS } from 'styles' +import { Theme } from 'theme' + +const { white, fadedGreyishWhite, blackLight } = COLOURS + +const DefaultCard = styled.div` + height: inherit; + min-width: 200px; + min-height: 100px; + background-color: #f5f5f5; + border-radius: 6px; + box-shadow: 0 10px 15px -3px rgb(0 0 0 / 7%), 0 4px 6px -2px rgb(0 0 0 / 5%); + margin: 10px; +` + +const CardComponent = styled(DefaultCard)` + display: flex; + flex-direction: column; + border-top-right-radius: 6px; + border-top-left-radius: 6px; + background: ${({ theme }): string => (theme.mode == Theme.DARK ? fadedGreyishWhite : white)}; + color: ${({ theme }): string => (theme.mode == Theme.DARK ? white : blackLight)}; +` + +// CARD CONTENT STYLES +const CardContent = styled.div` + flex: 1; + display: flex; + justify-content: center; + align-items: center; + font-size: 15px; + padding: 16px; + line-height: normal; +` + +export interface CardBaseProps { + children?: React.ReactElement | string +} + +/** + * Card component. + * + * An extensible content container. + */ +export const Card: React.FC = ({ children, ...rest }) => { + return ( + + {children} + + ) +} diff --git a/src/components/common/Card/CardContent.tsx b/src/components/common/Card/CardContent.tsx index 32197b088..c4c9a5154 100644 --- a/src/components/common/Card/CardContent.tsx +++ b/src/components/common/Card/CardContent.tsx @@ -1,6 +1,8 @@ import React from 'react' import styled from 'styled-components' +import ShimmerBar from 'apps/explorer/components/common/ShimmerBar' + export type statusType = 'success' | 'danger' export interface CardContentProps { @@ -8,10 +10,10 @@ export interface CardContentProps { direction?: string icon1?: React.ReactElement label1: string - value1: string + value1: string | number valueSize?: number labelWidth?: number - caption1?: string + caption1?: string | number captionColor?: string hint1?: string hintColor?: string @@ -20,6 +22,7 @@ export interface CardContentProps { value2?: string caption2?: string hint2?: string + loading?: boolean } const CardBody = styled.div<{ @@ -98,6 +101,7 @@ export const CardContent: React.FC = ({ value2, caption2, hint2, + loading, }): JSX.Element => { return ( = ({ {label1}

-

{value1}

- {caption1 && ( + {loading ? :

{value1}

} + {!loading && caption1 && ( {caption1} {hint1} @@ -123,7 +127,7 @@ export const CardContent: React.FC = ({ )}
- {label2 && ( + {!loading && label2 && (

{icon2 && {icon2}  } diff --git a/src/components/common/Card/index.tsx b/src/components/common/Card/index.tsx index 9c5a9dfd7..68ae5954a 100644 --- a/src/components/common/Card/index.tsx +++ b/src/components/common/Card/index.tsx @@ -1,63 +1,2 @@ -import React from 'react' -import styled from 'styled-components' -import Grid from '@material-ui/core/Grid' - -import { COLOURS } from 'styles' -import { Theme } from 'theme' - -const { white, fadedGreyishWhite, blackLight } = COLOURS - -const DefaultCard = styled.div` - height: inherit; - min-width: 200px; - min-height: 100px; - background-color: #f5f5f5; - border-radius: 6px; - box-shadow: 0 10px 15px -3px rgb(0 0 0 / 7%), 0 4px 6px -2px rgb(0 0 0 / 5%); - margin: 10px; -` - -const CardComponent = styled(DefaultCard)` - display: flex; - flex-direction: column; - border-top-right-radius: 6px; - border-top-left-radius: 6px; - background: ${({ theme }): string => (theme.mode == Theme.DARK ? fadedGreyishWhite : white)}; - color: ${({ theme }): string => (theme.mode == Theme.DARK ? white : blackLight)}; -` - -// CARD CONTENT STYLES -const CardContent = styled.div` - flex: 1; - display: flex; - justify-content: center; - align-items: center; - font-size: 15px; - padding: 16px; - line-height: normal; -` - -type CardBreakdown = boolean | 1 | 'auto' | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | undefined - -export interface CardBaseProps { - children?: React.ReactElement | string - xs?: CardBreakdown - sm?: CardBreakdown - md?: CardBreakdown - lg?: CardBreakdown -} - -/** - * Card component. - * - * An extensible content container. - */ -export const Card: React.FC = ({ children, xs = 12, sm = 6, md = 4, lg = 3, ...rest }) => { - return ( - - - {children} - - - ) -} +export * from './Card' +export * from './CardContent' diff --git a/src/components/common/CardRow/CardRow.stories.tsx b/src/components/common/CardRow/CardRow.stories.tsx index 7df39f5ce..1db014ada 100644 --- a/src/components/common/CardRow/CardRow.stories.tsx +++ b/src/components/common/CardRow/CardRow.stories.tsx @@ -4,9 +4,8 @@ import { Story, Meta } from '@storybook/react/types-6-0' import { GlobalStyles, ThemeToggler } from 'storybook/decorators' -import { Card } from '../Card/index' +import { Card, CardContent } from 'components/common/Card' import { CardRow, CardRowProps } from '.' -import { CardContent } from '../Card/CardContent' import QuestionIcon from '../../../assets/img/question1.svg' @@ -46,7 +45,7 @@ const Template: Story = (args) => ( Dummy Card - + = ({ children }) => { - return {children} + return {children} }