diff --git a/src/components/DataProductCard.tsx b/src/components/DataProductCard.tsx index e81985128c1..b6c6e91e880 100644 --- a/src/components/DataProductCard.tsx +++ b/src/components/DataProductCard.tsx @@ -105,6 +105,7 @@ export interface IProps { url: string background: string image: string + alt?: string name: string description?: string data?: Array @@ -114,13 +115,14 @@ const DataProductCard: React.FC = ({ url, background, image, + alt, name, description, data, }) => ( - {`${name} + {alt
diff --git a/src/components/ExpandableCard.tsx b/src/components/ExpandableCard.tsx index c7906a9ab82..9e591c1782a 100644 --- a/src/components/ExpandableCard.tsx +++ b/src/components/ExpandableCard.tsx @@ -1,5 +1,5 @@ // Libraries -import React, { ComponentType, SVGProps, useState } from "react" +import React, { ComponentType, ReactNode, SVGProps, useState } from "react" import styled from "styled-components" import { motion } from "framer-motion" @@ -90,8 +90,8 @@ const ButtonLink = styled.button` ` export interface IProps { - contentPreview?: string - title: string + contentPreview?: ReactNode + title: ReactNode svg?: ComponentType> eventCategory?: string eventName?: string diff --git a/src/components/ExpandableInfo.tsx b/src/components/ExpandableInfo.tsx index 536164d127a..2c5e77bbdb8 100644 --- a/src/components/ExpandableInfo.tsx +++ b/src/components/ExpandableInfo.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react" +import React, { ReactNode, useState } from "react" import styled from "styled-components" import { motion } from "framer-motion" import { GatsbyImage } from "gatsby-plugin-image" @@ -99,8 +99,8 @@ const ButtonContainer = styled(motion.div)` export interface IProps { image?: string - title: string - contentPreview: string + title: ReactNode + contentPreview: ReactNode background: string forceOpen: boolean className?: string diff --git a/src/components/Layer2/Layer2Onboard.tsx b/src/components/Layer2/Layer2Onboard.tsx index a1356827c8c..776d754b666 100644 --- a/src/components/Layer2/Layer2Onboard.tsx +++ b/src/components/Layer2/Layer2Onboard.tsx @@ -165,8 +165,6 @@ const RightSelected = styled.div` ` interface Exchange { - label?: string - value?: string name: string supports_deposits: Array supports_withdrawals: Array @@ -174,13 +172,24 @@ interface Exchange { } interface Layer2 { - label: string name: string - value: string bridgeWallets: Array bridge: string } +interface Option { + value: string + label: string +} + +interface Layer2Option extends Option { + l2: Layer2 +} + +interface ExchangeOption extends Option { + cex: Exchange +} + export interface IProps { layer2DataCombined: Array ethIcon: string @@ -197,6 +206,24 @@ const Layer2Onboard: React.FC = ({ const [selectedExchange, setSelectedExchange] = useState() const [selectedL2, setSelectedL2] = useState() + const layer2Options: Array = layer2DataCombined.map((l2) => { + return { + label: l2.name, + value: l2.name, + l2, + } + }) + + const cexSupportOptions: Array = cexSupport.map( + (cex: Exchange) => { + return { + label: cex.name, + value: cex.name, + cex, + } + } + ) + return ( @@ -225,19 +252,15 @@ const Layer2Onboard: React.FC = ({ { - l2.label = l2.name - l2.value = l2.name - return l2 - })} - onChange={(selectedOption: Layer2) => { + options={layer2Options} + onChange={(selectedOption: Layer2Option) => { trackCustomEvent({ eventCategory: `Selected layer 2 to bridge to`, eventAction: `Clicked`, - eventName: `${selectedOption.name} bridge selected`, - eventValue: `${selectedOption.name}`, + eventName: `${selectedOption.l2.name} bridge selected`, + eventValue: `${selectedOption.l2.name}`, }) - setSelectedL2(selectedOption) + setSelectedL2(selectedOption.l2) }} placeholder={translateMessageId( "layer-2-onboard-wallet-input-placeholder", @@ -285,19 +308,15 @@ const Layer2Onboard: React.FC = ({ { - cex.label = cex.name - cex.value = cex.name - return cex - })} - onChange={(selectedOption: Exchange) => { + options={cexSupportOptions} + onChange={(selectedOption: ExchangeOption) => { trackCustomEvent({ eventCategory: `Selected cex to onboard`, eventAction: `Clicked`, - eventName: `${selectedOption.name} selected`, - eventValue: `${selectedOption.name}`, + eventName: `${selectedOption.cex.name} selected`, + eventValue: `${selectedOption.cex.name}`, }) - setSelectedExchange(selectedOption) + setSelectedExchange(selectedOption.cex) }} placeholder={translateMessageId( "layer-2-onboard-exchange-input-placeholder", @@ -318,7 +337,7 @@ const Layer2Onboard: React.FC = ({
    {selectedExchange.supports_deposits.map((l2) => ( -
  • {l2}
  • +
  • {l2}
  • ))}
@@ -328,7 +347,7 @@ const Layer2Onboard: React.FC = ({
    {selectedExchange.supports_withdrawals.map((l2) => ( -
  • {l2}
  • +
  • {l2}
  • ))}
diff --git a/src/components/PageHero.tsx b/src/components/PageHero.tsx index 43efcb6826b..50857fca4bb 100644 --- a/src/components/PageHero.tsx +++ b/src/components/PageHero.tsx @@ -1,4 +1,4 @@ -import React from "react" +import React, { ReactNode } from "react" import styled from "styled-components" import { GatsbyImage } from "gatsby-plugin-image" import ButtonLink, { IProps as IButtonLinkProps } from "./ButtonLink" @@ -94,14 +94,14 @@ const StyledButtonLink = styled(ButtonLink)` ` export interface IButton extends Partial { - content: string + content: ReactNode } export interface IContent { buttons?: Array - title: string - header: string - subtitle: string + title: ReactNode + header: ReactNode + subtitle: ReactNode image: string alt: string } @@ -109,7 +109,7 @@ export interface IContent { export interface IProps { content: IContent isReverse?: boolean - children?: React.ReactNode + children?: ReactNode className?: string } diff --git a/src/components/SimpleTable.tsx b/src/components/SimpleTable.tsx index c273ec9de67..f2a8e5c8689 100644 --- a/src/components/SimpleTable.tsx +++ b/src/components/SimpleTable.tsx @@ -118,7 +118,7 @@ export interface TableRow { } export interface IProps { - columns: Array + columns: Array content: Array hasError: boolean } diff --git a/src/components/StablecoinBoxGrid.tsx b/src/components/StablecoinBoxGrid.tsx index e40c91e46b4..b60ed83165c 100644 --- a/src/components/StablecoinBoxGrid.tsx +++ b/src/components/StablecoinBoxGrid.tsx @@ -152,7 +152,7 @@ interface ILink { text: string } -export interface IPropsGridItem { +interface IPropsGridItem { description: string columnNumber: number rowNumber: number @@ -259,8 +259,17 @@ const GridItem: React.FC = ({ ) } +export interface IPropsBoxItem { + description: string + emoji: string + title: string + pros?: Array + cons?: Array + links: Array +} + export interface IProps { - items: Array + items: Array } const StablecoinBoxGrid: React.FC = ({ items }) => { diff --git a/src/pages/layer-2.js b/src/pages/layer-2.tsx similarity index 94% rename from src/pages/layer-2.js rename to src/pages/layer-2.tsx index fc5b0d97d1c..7af97cb607d 100644 --- a/src/pages/layer-2.js +++ b/src/pages/layer-2.tsx @@ -1,6 +1,6 @@ // Libraries import React, { useEffect, useState } from "react" -import { graphql } from "gatsby" +import { graphql, PageProps } from "gatsby" import { getImage, GatsbyImage } from "gatsby-plugin-image" import styled from "styled-components" import { useIntl } from "react-intl" @@ -32,10 +32,12 @@ import { getData } from "../utils/cache" import { translateMessageId, getLocaleForNumberFormat, + TranslationKey, } from "../utils/translations" // Constants import { GATSBY_FUNCTIONS_PATH } from "../constants" +import { Lang } from "../utils/languages" // Styles @@ -61,7 +63,7 @@ const LightGrayContent = styled(PaddedContent)` background: ${(props) => props.theme.colors.layer2ContentSecondary}; ` -const FlexContainer = styled.div` +const FlexContainer = styled.div<{ flexPercent: string | number }>` flex: ${(props) => props.flexPercent}%; @media (max-width: ${({ theme }) => theme.breakpoints.m}) { flex: 100%; @@ -184,18 +186,30 @@ const StatDivider = styled.div` } ` -const Layer2Page = ({ data }) => { +interface L2DataResponse { + data: Array<[string, number, number]> +} + +interface FeeDataResponse { + data: Array<{ id: string; results: { feeTransferEth: number } }> +} + +const Layer2Page = ({ data }: PageProps) => { const intl = useIntl() const [tvl, setTVL] = useState("loading...") const [percentChangeL2, setL2PercentChange] = useState("loading...") const [averageFee, setAverageFee] = useState("loading...") useEffect(() => { - const localeForStatsBoxNumbers = getLocaleForNumberFormat(intl.locale) + const localeForStatsBoxNumbers = getLocaleForNumberFormat( + intl.locale as Lang + ) - const fetchL2Beat = async () => { + const fetchL2Beat = async (): Promise => { try { - const l2BeatData = await getData(`${GATSBY_FUNCTIONS_PATH}/l2beat`) + const l2BeatData = await getData( + `${GATSBY_FUNCTIONS_PATH}/l2beat` + ) // formatted TVL from L2beat API formatted const TVL = new Intl.NumberFormat(localeForStatsBoxNumbers, { style: "currency", @@ -206,14 +220,15 @@ const Layer2Page = ({ data }) => { }).format(l2BeatData.data[l2BeatData.data.length - 1][1]) setTVL(`${TVL}`) // Calculate percent change ((new value - old value) / old value) *100) - const percentage = ( + const percentage = ((l2BeatData.data[l2BeatData.data.length - 1][1] - l2BeatData.data[l2BeatData.data.length - 31][1]) / l2BeatData.data[l2BeatData.data.length - 31][1]) * 100 - ).toFixed(2) setL2PercentChange( - percentage > 0 ? `+${percentage}%` : `${percentage}%` + percentage > 0 + ? `+${percentage.toFixed(2)}%` + : `${percentage.toFixed(2)}%` ) } catch (error) { console.error(error) @@ -223,15 +238,15 @@ const Layer2Page = ({ data }) => { } fetchL2Beat() - const fetchCryptoStats = async () => { + const fetchCryptoStats = async (): Promise => { try { // Average eth transfer fee from L2's supported by cryptostats API - let feeData = await getData( + const feeDataResponse = await getData( "https://api.cryptostats.community/api/v1/l2-fees/feeTransferEth?metadata=false" ) - // Filter out layer 2 networks not listed - feeData = feeData.data.filter((l2) => l2.id !== "hermez") + // filtering out L2's we arent listing + const feeData = feeDataResponse.data.filter((l2) => l2.id !== "hermez") const feeAverage = feeData.reduce( @@ -264,17 +279,17 @@ const Layer2Page = ({ data }) => { buttons: [ { content: translateMessageId("layer-2-hero-button-1", intl), - pathId: "what-is-layer-2", + toId: "what-is-layer-2", }, { content: translateMessageId("layer-2-hero-button-2", intl), - pathId: "use-layer-2", - isSecondary: "isSecondary", + toId: "use-layer-2", + isSecondary: true, }, { content: translateMessageId("layer-2-hero-button-3", intl), - pathId: "how-to-get-onto-layer-2", - isSecondary: "isSecondary", + toId: "how-to-get-onto-layer-2", + isSecondary: true, }, ], } @@ -398,7 +413,10 @@ const Layer2Page = ({ data }) => { const layer2DataCombined = [...layer2Data.optimistic, ...layer2Data.zk] - const tooltipContent = (metric) => ( + const tooltipContent = (metric: { + apiUrl: string + apiProvider: string + }): JSX.Element => (
{" "} {metric.apiProvider} @@ -634,7 +652,7 @@ const Layer2Page = ({ data }) => { {rollupCards.map( ({ image, title, description, childSentence, childLink }) => ( - + { key={idx} background={l2.background} image={getImage(data[l2.imageKey])} - description={translateMessageId(l2.descriptionKey, intl)} + description={translateMessageId( + l2.descriptionKey as TranslationKey, + intl + )} url={l2.website} - note={translateMessageId(l2.noteKey, intl)} + note={translateMessageId(l2.noteKey as TranslationKey, intl)} name={l2.name} bridge={l2.bridge} ecosystemPortal={l2.ecosystemPortal} @@ -724,16 +745,19 @@ const Layer2Page = ({ data }) => { key={idx} background={l2.background} image={getImage(data[l2.imageKey])} - description={translateMessageId(l2.descriptionKey, intl)} + description={translateMessageId( + l2.descriptionKey as TranslationKey, + intl + )} url={l2.website} - note={translateMessageId(l2.noteKey, intl)} + note={translateMessageId(l2.noteKey as TranslationKey, intl)} name={l2.name} bridge={l2.bridge} ecosystemPortal={l2.ecosystemPortal} tokenLists={l2.tokenLists} > - {l2.purpose.map((purpose) => ( - {purpose} + {l2.purpose.map((purpose, index) => ( + {purpose} ))} ) diff --git a/src/pages/run-a-node.js b/src/pages/run-a-node.tsx similarity index 96% rename from src/pages/run-a-node.js rename to src/pages/run-a-node.tsx index 4dedf829903..e2e1c9c963e 100644 --- a/src/pages/run-a-node.js +++ b/src/pages/run-a-node.tsx @@ -1,6 +1,6 @@ // Libraries -import React from "react" -import { graphql } from "gatsby" +import React, { ComponentType, SVGProps } from "react" +import { graphql, PageProps } from "gatsby" import { GatsbyImage, getImage } from "gatsby-plugin-image" import { useIntl } from "react-intl" import styled from "styled-components" @@ -40,7 +40,7 @@ import Icon from "../components/Icon" import NakedButton from "../components/NakedButton" // Utils -import { translateMessageId } from "../utils/translations" +import { translateMessageId, TranslationKey } from "../utils/translations" import { scrollIntoView } from "../utils/scrollIntoView" // Styles @@ -127,7 +127,7 @@ const ResponsiveButtonLink = styled(ButtonLink)` } ` -const Highlight = styled(Content)` +const Highlight = styled(Content)<{ backgroundColor: string }>` display: flex; justify-content: center; align-items: center; @@ -406,28 +406,36 @@ const StrongParagraph = styled.p` font-weight: 600; ` -const RunANodePage = ({ data }) => { +interface RunANodeCard { + image: ComponentType> + title: TranslationKey + preview: TranslationKey + body: Array + alt: TranslationKey +} + +const RunANodePage = ({ data }: PageProps) => { const intl = useIntl() const heroContent = { title: , header: , subtitle: , image: getImage(data.ethereumInside), - alt: , + alt: translateMessageId("page-run-a-node-hero-alt", intl), buttons: [ { content: , - pathId: "what-is-a-node", + toId: "what-is-a-node", }, { content: , - pathId: "getting-started", - isSecondary: "isSecondary", + toId: "getting-started", + isSecondary: true, }, ], } - const whyRunANodeCards = [ + const whyRunANodeCards: Array = [ { image: PrivacyGlyph, title: "page-run-a-node-privacy-title", @@ -562,6 +570,8 @@ const RunANodePage = ({ data }) => { } title={translateMessageId(title, intl)} + // TODO: make a11y svgs (using ) + // @ts-ignore alt={translateMessageId(alt, intl)} svg={image} key={idx} @@ -599,6 +609,8 @@ const RunANodePage = ({ data }) => { </ColumnFill> <ColumnNarrow> <Terminal + // TODO: make a11y svgs (using <title>) + // @ts-ignore alt={translateMessageId( "page-run-a-node-glyph-alt-terminal", intl @@ -615,6 +627,8 @@ const RunANodePage = ({ data }) => { </ColumnFill> <ColumnNarrow> <Dappnode + // TODO: make a11y svgs (using <title>) + // @ts-ignore alt={translateMessageId( "page-run-a-node-glyph-alt-dappnode", intl @@ -634,6 +648,8 @@ const RunANodePage = ({ data }) => { </ColumnFill> <ColumnNarrow> <Dapptap + // TODO: make a11y svgs (using <title>) + // @ts-ignore alt={translateMessageId( "page-run-a-node-glyph-alt-phone", intl @@ -711,7 +727,6 @@ const RunANodePage = ({ data }) => { </div> <ScrollButtonSecondary onClick={() => scrollIntoView("build-your-own")} - isSecondary > <Translation id="page-run-a-node-choose-your-adventure-build-start" /> </ScrollButtonSecondary> @@ -727,6 +742,8 @@ const RunANodePage = ({ data }) => { <BuildContainer> <SvgTitle> <HardwareGlyph + // TODO: make a11y svgs (using <title>) + // @ts-ignore alt={translateMessageId( "page-run-a-node-glyph-alt-hardware", intl @@ -812,6 +829,8 @@ const RunANodePage = ({ data }) => { <BuildContainer> <SvgTitle> <DownloadGlyph + // TODO: make a11y svgs (using <title>) + // @ts-ignore alt={translateMessageId( "page-run-a-node-glyph-alt-software", intl diff --git a/src/pages/stablecoins.js b/src/pages/stablecoins.tsx similarity index 97% rename from src/pages/stablecoins.js rename to src/pages/stablecoins.tsx index cb51959a40a..b21c2f64b6b 100644 --- a/src/pages/stablecoins.js +++ b/src/pages/stablecoins.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState, useMemo } from "react" import styled from "styled-components" import { GatsbyImage, getImage } from "gatsby-plugin-image" -import { graphql } from "gatsby" +import { graphql, PageProps } from "gatsby" import { useIntl } from "react-intl" import ButtonLink from "../components/ButtonLink" @@ -270,8 +270,37 @@ const tooltipContent = ( </div> ) -const StablecoinsPage = ({ data }) => { - const [state, setState] = useState({ +type EthereumDataResponse = Array<{ + id: string + name: string + market_cap: number + image: string + symbol: string +}> + +type StablecoinDataResponse = Array<{ + id: string + name: string + market_cap: number + image: string + symbol: string +}> + +interface Market { + name: string + marketCap: string + image: string + type: string + url: string +} + +interface State { + markets: Array<Market> + marketsHasError: boolean +} + +const StablecoinsPage = ({ data }: PageProps<Queries.StablecoinsPageQuery>) => { + const [state, setState] = useState<State>({ markets: [], marketsHasError: false, }) @@ -323,11 +352,11 @@ const StablecoinsPage = ({ data }) => { ;(async () => { try { // Fetch token data in the Ethereum ecosystem - const ethereumData = await getData( + const ethereumData = await getData<EthereumDataResponse>( "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&category=ethereum-ecosystem&order=market_cap_desc&per_page=100&page=1&sparkline=false" ) // Fetch token data for stablecoins - const stablecoinData = await getData( + const stablecoinData = await getData<StablecoinDataResponse>( "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&category=stablecoins&order=market_cap_desc&per_page=100&page=1&sparkline=false" ) @@ -549,15 +578,15 @@ const StablecoinsPage = ({ data }) => { buttons: [ { content: translateMessageId("page-stablecoins-hero-button", intl), - path: "#explore", + toId: "explore", }, { content: translateMessageId( "page-stablecoins-how-they-work-button", intl ), - path: "#how", - isSecondary: "isSecondary", + toId: "how", + isSecondary: true, }, ], } @@ -615,7 +644,7 @@ const StablecoinsPage = ({ data }) => { ))} </LeftColumn> <StyledGhostCard> - <Emoji svg size={3} text=":pizza:" /> + <Emoji size={3} text=":pizza:" /> <h3> <Translation id="page-stablecoins-bitcoin-pizza" /> </h3> @@ -811,7 +840,6 @@ const StablecoinsPage = ({ data }) => { alt={dapp.alt} image={dapp.image} name={dapp.name} - data={dapp.data} description={dapp.description} /> ))}