better info response types
This commit is contained in:
parent
496c096531
commit
24c99868e1
@ -1,3 +1,5 @@
|
|||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
export interface IGetGlobalResponse {
|
export interface IGetGlobalResponse {
|
||||||
active_cryptocurrencies: number;
|
active_cryptocurrencies: number;
|
||||||
markets: number;
|
markets: number;
|
||||||
@ -17,18 +19,37 @@ export interface IGetCoinsCountResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IGetCoinInfoResponse {
|
export interface IGetCoinInfoResponse {
|
||||||
[key: string]: any;
|
name: string;
|
||||||
|
id: string;
|
||||||
|
image: {
|
||||||
|
large: string;
|
||||||
|
};
|
||||||
|
description: {
|
||||||
|
en: string;
|
||||||
|
}
|
||||||
|
market_data: {
|
||||||
|
low_24h: { usd: number };
|
||||||
|
high_24h: { usd: number };
|
||||||
|
ath: { usd: number };
|
||||||
|
atl: { usd: number };
|
||||||
|
price_change_percentage_24h: number;
|
||||||
|
price_change_percentage_7d: number;
|
||||||
|
price_change_percentage_14d: number;
|
||||||
|
price_change_percentage_30d: number;
|
||||||
|
price_change_percentage_60d: number;
|
||||||
|
price_change_percentage_200d: number;
|
||||||
|
price_change_percentage_1y: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGetCoinInfoData {
|
||||||
|
data: IGetCoinInfoResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGetCoinInfoRequest {
|
export interface IGetCoinInfoRequest {
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// export interface IGetCoinChartRequest {
|
|
||||||
// page: number;
|
|
||||||
// per_page: number;
|
|
||||||
// }
|
|
||||||
|
|
||||||
export interface IChartDataItem {
|
export interface IChartDataItem {
|
||||||
[index: number]: number,
|
[index: number]: number,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import React from 'react'
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { useGetCoinInfoQuery } from '../coinApi';
|
import { useGetCoinInfoQuery } from '../coinApi';
|
||||||
|
|
||||||
@ -12,22 +13,25 @@ import CoinInfo from './coinInfo';
|
|||||||
const CoinDetails = (): JSX.Element => {
|
const CoinDetails = (): JSX.Element => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const {
|
const {
|
||||||
data: data,
|
data,
|
||||||
error: errorInfo,
|
error,
|
||||||
isLoading: isLoadingInfo,
|
isLoading,
|
||||||
isSuccess: isSuccessInfo,
|
isSuccess,
|
||||||
refetch: refetchInfo
|
|
||||||
} = useGetCoinInfoQuery(id ? id : '');
|
} = useGetCoinInfoQuery(id ? id : '');
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
console.log(data)
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="details">
|
<div className="details">
|
||||||
|
{isLoading && <div>Loading...</div>}
|
||||||
{
|
{
|
||||||
data && isSuccessInfo && <>
|
data && isSuccess && <>
|
||||||
<div className="details-title">
|
<div className="details-title">
|
||||||
<img src={data.image.large} width="28" height="28" />
|
<img src={data.image.large} width="28" height="28" />
|
||||||
<h1>{data.name}</h1>
|
<h1>{data.name}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid item xs={12} sm={12} md={8}>
|
<Grid item xs={12} sm={12} md={8}>
|
||||||
@ -39,8 +43,8 @@ const CoinDetails = (): JSX.Element => {
|
|||||||
<Grid item xs={12} style={{marginTop: 20}}>
|
<Grid item xs={12} style={{marginTop: 20}}>
|
||||||
<CoinChart coin={data.id} />
|
<CoinChart coin={data.id} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12} style={{marginTop: 40}}>
|
||||||
<div dangerouslySetInnerHTML={{ __html: data.description.en }} />
|
<div style={{lineHeight: 2}} dangerouslySetInnerHTML={{ __html: data.description.en }} />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@ -27,7 +27,7 @@ const CoinInfo = (props: ICoinInfoProps): JSX.Element => {
|
|||||||
Current price: ${data.tickers[0].converted_last.usd}
|
Current price: ${data.tickers[0].converted_last.usd}
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} style={{ marginTop: 20 }}>
|
<Grid item xs={12} style={{ marginTop: 20 }}>
|
||||||
Homepage: <a target="_blank" href={data.links.homepage}>{data.links.homepage}</a>
|
Homepage: <a target="_blank" href={data.links.homepage[0]}>{data.links.homepage[0]}</a>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item style={{ marginTop: 20 }}>
|
<Grid item style={{ marginTop: 20 }}>
|
||||||
Votes: {data.sentiment_votes_up_percentage}%
|
Votes: {data.sentiment_votes_up_percentage}%
|
||||||
@ -38,27 +38,35 @@ const CoinInfo = (props: ICoinInfoProps): JSX.Element => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
<Grid container justifyContent="flex-start" style={{ marginTop: 30, marginBottom: 30 }}>
|
<Grid container justifyContent="flex-start" style={{ marginTop: 30, marginBottom: 30 }}>
|
||||||
{data.links.subreddit_url &&
|
{data.links.subreddit_url &&
|
||||||
<Button style={{ marginRight: 10 }} variant="outlined" startIcon={<RedditIcon />} href={data.links.subreddit_url}>
|
<Button style={{ marginRight: 10, marginTop: 10 }} variant="outlined" startIcon={<RedditIcon />} href={data.links.subreddit_url}>
|
||||||
Reddit
|
Reddit
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
{data.links.twitter_screen_name &&
|
{data.links.twitter_screen_name &&
|
||||||
<Button style={{ marginRight: 10 }} variant="outlined" startIcon={<TwitterIcon />} href={`https://twitter.com/${data.links.twitter_screen_name}`}>
|
<Button style={{ marginRight: 10, marginTop: 10 }} variant="outlined" startIcon={<TwitterIcon />} href={`https://twitter.com/${data.links.twitter_screen_name}`}>
|
||||||
Twitter
|
Twitter
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Object.entries(data.links.chat_url).map(
|
Object.entries(data.links.chat_url).map(
|
||||||
([key, value]) => Boolean(value)
|
([key, value]) => {
|
||||||
&& <Button
|
if (Boolean(value)) {
|
||||||
key={key}
|
console.log(value);
|
||||||
style={{ marginRight: 10 }}
|
const domain = new URL(String(value));
|
||||||
variant="outlined"
|
const label = domain.hostname.split(".")[0]
|
||||||
href={String(value)}
|
return (
|
||||||
startIcon={<LinkIcon />}
|
<Button
|
||||||
|
key={key}
|
||||||
|
style={{ marginRight: 10, marginTop: 10 }}
|
||||||
|
variant="outlined"
|
||||||
|
href={String(value)}
|
||||||
|
startIcon={<LinkIcon />}
|
||||||
>
|
>
|
||||||
Discord
|
{label}
|
||||||
</Button>
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@ -5,12 +5,17 @@ import TableContainer from '@mui/material/TableContainer';
|
|||||||
import TableHead from '@mui/material/TableHead';
|
import TableHead from '@mui/material/TableHead';
|
||||||
import TableRow from '@mui/material/TableRow';
|
import TableRow from '@mui/material/TableRow';
|
||||||
|
|
||||||
export interface ICoinStatsProps {
|
import { IGetCoinInfoResponse, IGetCoinInfoData } from '../coinApi-types'
|
||||||
[key: string]: any;
|
|
||||||
|
interface ICoinStatsProps {
|
||||||
|
data: IGetCoinInfoResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CoinStats = (props: ICoinStatsProps): JSX.Element => {
|
const CoinStats = (props: ICoinStatsProps): JSX.Element => {
|
||||||
|
console.log("CoinStats props", props)
|
||||||
|
|
||||||
const { data } = props;
|
const { data } = props;
|
||||||
|
|
||||||
const tableData = [
|
const tableData = [
|
||||||
{title: "24h Hight", value: `$${data.market_data.low_24h.usd}`},
|
{title: "24h Hight", value: `$${data.market_data.low_24h.usd}`},
|
||||||
{title: "24h Low", value: `$${data.market_data.high_24h.usd}`},
|
{title: "24h Low", value: `$${data.market_data.high_24h.usd}`},
|
||||||
|
|||||||
@ -12,7 +12,17 @@ import { useGetCoinsListQuery, useGetGlobalQuery } from '../coinApi';
|
|||||||
|
|
||||||
import Pager from './coinListPager';
|
import Pager from './coinListPager';
|
||||||
|
|
||||||
|
export interface IData {
|
||||||
|
id: string;
|
||||||
|
image: string;
|
||||||
|
name: string;
|
||||||
|
market_cap_rank: number;
|
||||||
|
symbol: string;
|
||||||
|
current_price: string;
|
||||||
|
high_24h: number;
|
||||||
|
low_24h: number;
|
||||||
|
price_change_percentage_24h: number;
|
||||||
|
}
|
||||||
|
|
||||||
const CoinList = (): JSX.Element => {
|
const CoinList = (): JSX.Element => {
|
||||||
|
|
||||||
@ -74,7 +84,7 @@ const CoinList = (): JSX.Element => {
|
|||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{
|
{
|
||||||
data.map((row: any, index: any) => (
|
data.map((row: IData, index: number) => (
|
||||||
<TableRow
|
<TableRow
|
||||||
key={row.name}
|
key={row.name}
|
||||||
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
|
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
|
||||||
@ -119,7 +129,7 @@ const CoinList = (): JSX.Element => {
|
|||||||
</Table>
|
</Table>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
}
|
}
|
||||||
<Pager page={page} per_page={per_page} setSearchParams={setSearchParams} />
|
<Pager page={page} per_page={per_page}/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,32 +6,37 @@ import ButtonGroup from '@mui/material/ButtonGroup';
|
|||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import Grid from '@mui/material/Grid';
|
import Grid from '@mui/material/Grid';
|
||||||
|
|
||||||
const Pager = (props:any): JSX.Element => {
|
export interface IPagerProps {
|
||||||
const { page, per_page, } = props;
|
page: number;
|
||||||
const { data, error, isLoading, isSuccess, refetch } = useGetCoinsCountQuery();
|
per_page: number;
|
||||||
const navigate = useNavigate();
|
}
|
||||||
const lastPage = (data: number) => Math.ceil(data / per_page)
|
|
||||||
|
|
||||||
function handlePager(page: number) {
|
const Pager = (props: IPagerProps): JSX.Element => {
|
||||||
const url = `/?page=${page}`
|
const { page, per_page, } = props;
|
||||||
navigate(url)
|
const { data, error, isLoading, isSuccess, refetch } = useGetCoinsCountQuery();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const lastPage = (data: number) => Math.ceil(data / per_page)
|
||||||
|
|
||||||
|
function handlePager(page: number) {
|
||||||
|
const url = `/?page=${page}`
|
||||||
|
navigate(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (<>
|
||||||
|
{
|
||||||
|
data && isSuccess &&
|
||||||
|
<Grid container justifyContent="center" style={{ marginTop: 60 }}>
|
||||||
|
<ButtonGroup variant="contained" aria-label="outlined primary button group">
|
||||||
|
<Button disabled={page === 1} onClick={() => navigate("/")}>First</Button>
|
||||||
|
<Button disabled={page === 1} onClick={() => handlePager(page - 1)}>Prev</Button>
|
||||||
|
<Typography style={{ padding: 10 }}>Page {page} from {lastPage(data.count)}</Typography>
|
||||||
|
<Button disabled={page === lastPage(data.count)} onClick={() => handlePager(page + 1)}>Next</Button>
|
||||||
|
<Button disabled={page === lastPage(data.count)} onClick={() => handlePager(lastPage(data.count))}>Last</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
</Grid>
|
||||||
}
|
}
|
||||||
|
</>
|
||||||
return (<>
|
)
|
||||||
{
|
|
||||||
data && isSuccess &&
|
|
||||||
<Grid container justifyContent="center" style={{marginTop: 60}}>
|
|
||||||
<ButtonGroup variant="contained" aria-label="outlined primary button group">
|
|
||||||
<Button disabled={page === 1} onClick={() => navigate("/")}>First</Button>
|
|
||||||
<Button disabled={page === 1} onClick={() => handlePager(page - 1)}>Prev</Button>
|
|
||||||
<Typography style={{ padding: 10}}>Page {page} from {lastPage(data.count)}</Typography>
|
|
||||||
<Button disabled={page === lastPage(data.count)} onClick={() => handlePager(page + 1)}>Next</Button>
|
|
||||||
<Button disabled={page === lastPage(data.count)} onClick={() => handlePager(lastPage(data.count))}>Last</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
</Grid>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Pager;
|
export default Pager;
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
## What's inside
|
## What's inside
|
||||||
|
|
||||||
- **Frontend:** Typescript using React, Redux-Toolkit, MaterialUI, react-charts-2
|
- **Frontend:** Typescript using React, Redux-Toolkit, Material-UI, react-chartjs-2
|
||||||
- **Backend:** Javascript using Express
|
- **Backend:** Javascript using Express
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user