Skip to content

Instantly share code, notes, and snippets.

@Joachimchisom1
Forked from adrianhajdin/App.css
Created May 4, 2022 17:08
Show Gist options
  • Save Joachimchisom1/b9081f60982f617a61b71b321985518a to your computer and use it in GitHub Desktop.
Save Joachimchisom1/b9081f60982f617a61b71b321985518a to your computer and use it in GitHub Desktop.
Develop a React Cryptocurrency App and Master Redux Toolkit in One Video
: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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment