-
-
Save adrianhajdin/1008c664fe7896b316f5efbff8d97935 to your computer and use it in GitHub Desktop.
:root{ | |
--text-primary:#000; | |
--bgPrimary:#fff; | |
--bgSecondary: #F9F9F9; | |
--pink: #0071bd; | |
--light-blue: #e6f7ff; | |
--border: #d9d9d9; | |
} | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
} | |
a:hover{ | |
color: var(--pink) !important; | |
} | |
.app{ | |
display: flex; | |
overflow: hidden; | |
} | |
.navbar{ | |
flex: 0.2; | |
background-color: rgb(0, 21, 41); | |
} | |
.main{ | |
flex: 0.8; | |
width: 100%; | |
} | |
.routes{ | |
padding: 20px; | |
} | |
.nav-container{ | |
position: fixed; | |
left: 0; | |
margin: 10px; | |
height: 100vh; | |
margin: 0px; | |
background-color: rgb(0, 21, 41); | |
} | |
.logo-container{ | |
background-color: #001529; | |
display: flex; | |
padding: 20px; | |
align-items: center; | |
width: 100%; | |
} | |
.logo{ | |
margin:0 0 0 15px; | |
} | |
.logo a{ | |
color: white; | |
} | |
.menu-control-container{ | |
display: none !important; | |
position: absolute !important; | |
right: 10px !important; | |
top: 25px !important; | |
font-size: 1.2rem !important; | |
background-color: var(--bgSecondary) !important; | |
border: none !important; | |
} | |
.loader{ | |
height: 81vh; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
} | |
@media screen and (max-width:1300px){ | |
.main{ | |
margin-left: 50px; | |
} | |
} | |
@media screen and (max-width:1170px){ | |
.main{ | |
margin-left: 50px; | |
} | |
} | |
@media screen and (max-width:1000px){ | |
.main{ | |
margin-left: 100px; | |
} | |
} | |
@media screen and (max-width:800px){ | |
.app{ | |
flex-direction: column; | |
overflow: hidden; | |
} | |
.navbar{ | |
flex: 1; | |
} | |
.main{ | |
flex: 1; | |
margin-top: 90px; | |
margin-left: 0px; | |
margin-right: 10px; | |
} | |
.nav-container{ | |
height: 8vh; | |
position:fixed; | |
width: 100%; | |
z-index: 100; | |
background-color: var(--bgSecondary); | |
} | |
.menu-control-container{ | |
display: block !important; | |
} | |
.ant-menu{ | |
position: absolute; | |
right: 0px; | |
} | |
.home-title{ | |
font-size: 1.4rem !important; | |
} | |
.show-more{ | |
font-size: 1.3rem !important; | |
} | |
} | |
.coin-detail-container{ | |
margin: 30px; | |
} | |
.coin-heading-container{ | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
flex-direction: column; | |
border-bottom: 1px solid var(--border); | |
padding-top: 20px; | |
padding-bottom: 20px; | |
gap: 10px; | |
} | |
.coin-heading-container .coin-name{ | |
font-weight: 900; | |
color: var(--pink); | |
} | |
.coin-heading-container p{ | |
font-size: 1rem; | |
opacity: 0.9; | |
margin-bottom: 20px; | |
} | |
.stats-container{ | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
gap: 40px; | |
} | |
.stats-container h2{ | |
font-weight: 700; | |
font-size: 1.4rem; | |
margin-top: 20px; | |
color: var(--pink); | |
} | |
.coin-details-heading{ | |
font-weight: 700 !important; | |
margin-top: 20px !important; | |
color: var(--pink) !important; | |
} | |
.coin-stats{ | |
display: flex; | |
justify-content: space-between; | |
border-bottom: 1px solid var(--border); | |
font-size: 1rem; | |
opacity: 0.9; | |
padding: 20px; | |
} | |
.coin-stats-name{ | |
display: flex; | |
gap: 10px; | |
font-size: 1rem; | |
} | |
.stats{ | |
font-weight: 800; | |
} | |
.coin-value-statistics-heading p{ | |
font-size: 1rem; | |
opacity: 0.9; | |
} | |
.coin-desc-link{ | |
display: flex; | |
gap: 40px; | |
margin-top: 40px; | |
padding-top: 20px; | |
} | |
.coin-desc-link h2{ | |
font-weight: 700; | |
color: var(--pink); | |
} | |
.coin-desc-link p{ | |
font-size: 1rem; | |
opacity: 0.9; | |
} | |
.coin-desc-link a{ | |
color: var(--pink); | |
} | |
.coin-desc-link h3{ | |
font-weight: 700; | |
} | |
.coin-desc{ | |
flex: 0.5; | |
} | |
.coin-links{ | |
padding: 0px 20px; | |
flex: 0.5; | |
} | |
.coin-link{ | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
border-bottom: 1px solid var(--border); | |
padding: 20px; | |
} | |
.link-name{ | |
text-transform: capitalize; | |
font-size: 1rem; | |
} | |
.coin-link a{ | |
color: var(--pink); | |
font-weight: 700; | |
font-size: 1rem; | |
} | |
.coin-link:hover, .coin-stats:hover{ | |
background-color: var(--bgSecondary); | |
} | |
@media screen and (max-width:1000px){ | |
.stats-container{ | |
flex-direction: column; | |
} | |
.coin-desc-link{ | |
flex-direction: column; | |
} | |
.stats-container h2{ | |
margin-top: 0px; | |
} | |
} | |
@media screen and (max-width: 500px){ | |
.coin-links{ | |
padding: 0px; | |
} | |
.coin-detail-container{ | |
margin: 0; | |
} | |
} | |
@media screen and (max-width: 500px){ | |
.heading{ | |
margin-top: 20px; | |
} | |
} | |
.select-news{ | |
width: 180px; | |
} | |
.news-card{ | |
min-height: 300px !important; | |
} | |
.news-image-container{ | |
display: flex !important; | |
justify-content: space-between !important; | |
} | |
.news-title{ | |
width: 70%; | |
} | |
.news-image-container .img{ | |
width:100px; | |
height:100px; | |
} | |
.news-card p{ | |
color: black; | |
margin: 10px 0px !important; | |
} | |
.provider-container{ | |
display: flex; | |
justify-content: space-between; | |
} | |
.provider-name{ | |
margin-left: 10px; | |
} | |
.chart-header{ | |
display: flex; | |
justify-content: space-between; | |
gap: 50px; | |
color: #0071bd; | |
} | |
.chart-title{ | |
color: #0071bd !important; | |
} | |
.price-container{ | |
display: flex !important; | |
gap: 20px !important; | |
align-items: center !important; | |
flex-wrap: wrap !important; | |
} | |
.price-change{ | |
font-weight: 900 !important; | |
} | |
.current-price{ | |
margin-top: 0px !important; | |
font-weight: 900 !important; | |
} | |
.home-heading-container{ | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
margin-top: 40px; | |
} | |
.show-more{ | |
margin-top: 0px !important; | |
} | |
.exchange-image{ | |
margin: 0px 10px !important; | |
} | |
.search-crypto{ | |
margin: 20px auto 30px auto; | |
width: 250px; | |
} | |
.crypto-card-container{ | |
min-height: 65vh !important; | |
} | |
.crypto-card{ | |
min-width: 250px; | |
} | |
.crypto-card .crypto-image{ | |
width:35px; | |
} | |
.select-timeperiod{ | |
width: 200px !important; | |
margin-top: 20px !important; | |
} | |
.footer { | |
background-color: #001529; | |
display: flex; | |
flex-direction: column; | |
padding: 20px; | |
align-items: center; | |
} |
import React, { useState } from 'react'; | |
import HTMLReactParser from 'html-react-parser'; | |
import { useParams } from 'react-router-dom'; | |
import millify from 'millify'; | |
import { Col, Row, Typography, Select } from 'antd'; | |
import { MoneyCollectOutlined, DollarCircleOutlined, FundOutlined, ExclamationCircleOutlined, StopOutlined, TrophyOutlined, CheckOutlined, NumberOutlined, ThunderboltOutlined } from '@ant-design/icons'; | |
import { useGetCryptoDetailsQuery, useGetCryptoHistoryQuery } from '../services/cryptoApi'; | |
import Loader from './Loader'; | |
import LineChart from './LineChart'; | |
const { Title, Text } = Typography; | |
const { Option } = Select; | |
const CryptoDetails = () => { | |
const { coinId } = useParams(); | |
const [timeperiod, setTimeperiod] = useState('7d'); | |
const { data, isFetching } = useGetCryptoDetailsQuery(coinId); | |
const { data: coinHistory } = useGetCryptoHistoryQuery({ coinId, timeperiod }); | |
const cryptoDetails = data?.data?.coin; | |
if (isFetching) return <Loader />; | |
const time = ['3h', '24h', '7d', '30d', '1y', '3m', '3y', '5y']; | |
const stats = [ | |
{ title: 'Price to USD', value: `$ ${cryptoDetails.price && millify(cryptoDetails.price)}`, icon: <DollarCircleOutlined /> }, | |
{ title: 'Rank', value: cryptoDetails.rank, icon: <NumberOutlined /> }, | |
{ title: '24h Volume', value: `$ ${cryptoDetails.volume && millify(cryptoDetails.volume)}`, icon: <ThunderboltOutlined /> }, | |
{ title: 'Market Cap', value: `$ ${cryptoDetails.marketCap && millify(cryptoDetails.marketCap)}`, icon: <DollarCircleOutlined /> }, | |
{ title: 'All-time-high(daily avg.)', value: `$ ${millify(cryptoDetails.allTimeHigh.price)}`, icon: <TrophyOutlined /> }, | |
]; | |
const genericStats = [ | |
{ title: 'Number Of Markets', value: cryptoDetails.numberOfMarkets, icon: <FundOutlined /> }, | |
{ title: 'Number Of Exchanges', value: cryptoDetails.numberOfExchanges, icon: <MoneyCollectOutlined /> }, | |
{ title: 'Aprroved Supply', value: cryptoDetails.approvedSupply ? <CheckOutlined /> : <StopOutlined />, icon: <ExclamationCircleOutlined /> }, | |
{ title: 'Total Supply', value: `$ ${millify(cryptoDetails.totalSupply)}`, icon: <ExclamationCircleOutlined /> }, | |
{ title: 'Circulating Supply', value: `$ ${millify(cryptoDetails.circulatingSupply)}`, icon: <ExclamationCircleOutlined /> }, | |
]; | |
return ( | |
<Col className="coin-detail-container"> | |
<Col className="coin-heading-container"> | |
<Title level={2} className="coin-name"> | |
{data?.data?.coin.name} ({data?.data?.coin.slug}) Price | |
</Title> | |
<p>{cryptoDetails.name} live price in US Dollar (USD). View value statistics, market cap and supply.</p> | |
</Col> | |
<Select defaultValue="7d" className="select-timeperiod" placeholder="Select Timeperiod" onChange={(value) => setTimeperiod(value)}> | |
{time.map((date) => <Option key={date}>{date}</Option>)} | |
</Select> | |
<LineChart coinHistory={coinHistory} currentPrice={millify(cryptoDetails.price)} coinName={cryptoDetails.name} /> | |
<Col className="stats-container"> | |
<Col className="coin-value-statistics"> | |
<Col className="coin-value-statistics-heading"> | |
<Title level={3} className="coin-details-heading">{cryptoDetails.name} Value Statistics</Title> | |
<p>An overview showing the statistics of {cryptoDetails.name}, such as the base and quote currency, the rank, and trading volume.</p> | |
</Col> | |
{stats.map(({ icon, title, value }) => ( | |
<Col className="coin-stats"> | |
<Col className="coin-stats-name"> | |
<Text>{icon}</Text> | |
<Text>{title}</Text> | |
</Col> | |
<Text className="stats">{value}</Text> | |
</Col> | |
))} | |
</Col> | |
<Col className="other-stats-info"> | |
<Col className="coin-value-statistics-heading"> | |
<Title level={3} className="coin-details-heading">Other Stats Info</Title> | |
<p>An overview showing the statistics of {cryptoDetails.name}, such as the base and quote currency, the rank, and trading volume.</p> | |
</Col> | |
{genericStats.map(({ icon, title, value }) => ( | |
<Col className="coin-stats"> | |
<Col className="coin-stats-name"> | |
<Text>{icon}</Text> | |
<Text>{title}</Text> | |
</Col> | |
<Text className="stats">{value}</Text> | |
</Col> | |
))} | |
</Col> | |
</Col> | |
<Col className="coin-desc-link"> | |
<Row className="coin-desc"> | |
<Title level={3} className="coin-details-heading">What is {cryptoDetails.name}?</Title> | |
{HTMLReactParser(cryptoDetails.description)} | |
</Row> | |
<Col className="coin-links"> | |
<Title level={3} className="coin-details-heading">{cryptoDetails.name} Links</Title> | |
{cryptoDetails.links?.map((link) => ( | |
<Row className="coin-link" key={link.name}> | |
<Title level={5} className="link-name">{link.type}</Title> | |
<a href={link.url} target="_blank" rel="noreferrer">{link.name}</a> | |
</Row> | |
))} | |
</Col> | |
</Col> | |
</Col> | |
); | |
}; | |
export default CryptoDetails; |
import React from 'react'; | |
import millify from 'millify'; | |
import { Collapse, Row, Col, Typography, Avatar } from 'antd'; | |
import HTMLReactParser from 'html-react-parser'; | |
import { useGetExchangesQuery } from '../services/cryptoApi'; | |
import Loader from './Loader'; | |
const { Text } = Typography; | |
const { Panel } = Collapse; | |
const Exchanges = () => { | |
const { data, isFetching } = useGetExchangesQuery(); | |
const exchangesList = data?.data?.exchanges; | |
if (isFetching) return <Loader />; | |
return ( | |
<> | |
<Row> | |
<Col span={6}>Exchanges</Col> | |
<Col span={6}>24h Trade Volume</Col> | |
<Col span={6}>Markets</Col> | |
<Col span={6}>Change</Col> | |
</Row> | |
<Row> | |
{exchangesList.map((exchange) => ( | |
<Col span={24}> | |
<Collapse> | |
<Panel | |
key={exchange.id} | |
showArrow={false} | |
header={( | |
<Row key={exchange.id}> | |
<Col span={6}> | |
<Text><strong>{exchange.rank}.</strong></Text> | |
<Avatar className="exchange-image" src={exchange.iconUrl} /> | |
<Text><strong>{exchange.name}</strong></Text> | |
</Col> | |
<Col span={6}>${millify(exchange.volume)}</Col> | |
<Col span={6}>{millify(exchange.numberOfMarkets)}</Col> | |
<Col span={6}>{millify(exchange.marketShare)}%</Col> | |
</Row> | |
)} | |
> | |
{HTMLReactParser(exchange.description || '')} | |
</Panel> | |
</Collapse> | |
</Col> | |
))} | |
</Row> | |
</> | |
); | |
}; | |
export default Exchanges; |
import React from 'react'; | |
import { Line } from 'react-chartjs-2'; | |
import { Col, Row, Typography } from 'antd'; | |
const { Title } = Typography; | |
const LineChart = ({ coinHistory, currentPrice, coinName }) => { | |
const coinPrice = []; | |
const coinTimestamp = []; | |
for (let i = 0; i < coinHistory?.data?.history?.length; i += 1) { | |
coinPrice.push(coinHistory?.data?.history[i].price); | |
} | |
for (let i = 0; i < coinHistory?.data?.history?.length; i += 1) { | |
coinTimestamp.push(new Date(coinHistory?.data?.history[i].timestamp).toLocaleDateString()); | |
} | |
const data = { | |
labels: coinTimestamp, | |
datasets: [ | |
{ | |
label: 'Price In USD', | |
data: coinPrice, | |
fill: false, | |
backgroundColor: '#0071bd', | |
borderColor: '#0071bd', | |
}, | |
], | |
}; | |
const options = { | |
scales: { | |
yAxes: [ | |
{ | |
ticks: { | |
beginAtZero: true, | |
}, | |
}, | |
], | |
}, | |
}; | |
return ( | |
<> | |
<Row className="chart-header"> | |
<Title level={2} className="chart-title">{coinName} Price Chart </Title> | |
<Col className="price-container"> | |
<Title level={5} className="price-change">Change: {coinHistory?.data?.change}%</Title> | |
<Title level={5} className="current-price">Current {coinName} Price: $ {currentPrice}</Title> | |
</Col> | |
</Row> | |
<Line data={data} options={options} /> | |
</> | |
); | |
}; | |
export default LineChart; |
Can someone please help me with this error?
The particular lines above GIVING ERROR BELOWUncaught runtime errors:
×
ERROR
Cannot read properties of undefined (reading 'total')
TypeError: Cannot read properties of undefined (reading 'total')
at Homepage (http://localhost:3000/main.e7235f78e0ce46c0d4d8.hot-update.js:60:30)
at renderWithHooks (http://localhost:3000/static/js/bundle.js:57449:22)
at updateFunctionComponent (http://localhost:3000/static/js/bundle.js:61016:24)
at beginWork (http://localhost:3000/static/js/bundle.js:62735:20)
at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:47705:18)
at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:47749:20)
at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:47806:35)
at beginWork$1 (http://localhost:3000/static/js/bundle.js:67704:11)
at performUnitOfWork (http://localhost:3000/static/js/bundle.js:66952:16)
at workLoopSync (http://localhost:3000/static/js/bundle.js:66875:9)
It is due to difference between the version of React router, the newer version of react router has made it easier
you can simply use instead of for nesting your components.