From e33dba4584f37a6312209b94cb145dc15fd8f26e Mon Sep 17 00:00:00 2001 From: "ste.vaidis" Date: Sun, 11 Dec 2022 17:36:04 +0200 Subject: [PATCH] responsive chart --- Back/src/application_controller.js | 16 +-- Front/src/coinApi-types.ts | 45 +++++++ Front/src/coinApi.ts | 65 +++------- Front/src/coinDetails/coinChart-types.ts | 20 +++ Front/src/coinDetails/coinChart.tsx | 150 +++++++++++++++-------- Front/src/coinDetails/coinInfo.tsx | 6 +- Front/src/index.css | 6 + 7 files changed, 193 insertions(+), 115 deletions(-) create mode 100644 Front/src/coinApi-types.ts create mode 100644 Front/src/coinDetails/coinChart-types.ts diff --git a/Back/src/application_controller.js b/Back/src/application_controller.js index 678ae1f..64e5d62 100644 --- a/Back/src/application_controller.js +++ b/Back/src/application_controller.js @@ -3,11 +3,6 @@ var router = express.Router(); const api_helper = require('./thirdparty_api') const config = require('./config'); -// total coins 13081 -// per page coins 100 -// max page 131 -// last lenth 81 - router.get('/coins/markets', function (req, res) { let page = req.query.page || 1; let per_page = req.query.per_page || 100; @@ -15,9 +10,6 @@ router.get('/coins/markets', function (req, res) { api_helper.REMOTE_API_call(url) .then(response => { - console.log("response.length : ", response.length); - console.log("response.page : ", page); -//console.log("url : ", url); res.json(response); }) .catch(error => { @@ -29,7 +21,6 @@ router.get('/coins/markets', function (req, res) { router.get('/count', function (req, res) { let url = config.coingecko.api_url + '/global'; - console.log("url: ", url); api_helper.REMOTE_API_call(url) .then(response => { @@ -45,7 +36,6 @@ router.get('/count', function (req, res) { router.get('/coin/:id', function (req, res) { let id = req.params['id']; let url = config.coingecko.api_url + '/coins/' + id; - console.log("id: ", id); api_helper.REMOTE_API_call(url) .then(response => { @@ -57,9 +47,11 @@ router.get('/coin/:id', function (req, res) { }) }) -router.get('/coin/:id/chart', function (req, res) { +router.get('/coin/:id/chart/:days?', function (req, res) { let id = req.params['id']; - let url = config.coingecko.api_url + '/coins/' + id + '/market_chart?vs_currency=usd&days=max'; + let days = req.params['days'] || 'max'; + let url = config.coingecko.api_url + '/coins/' + id + '/market_chart?vs_currency=usd&days=' + days; + console.log("chart url:", url) api_helper.REMOTE_API_call(url) .then(response => { diff --git a/Front/src/coinApi-types.ts b/Front/src/coinApi-types.ts new file mode 100644 index 0000000..29312a1 --- /dev/null +++ b/Front/src/coinApi-types.ts @@ -0,0 +1,45 @@ +export interface IGetGlobalResponse { + active_cryptocurrencies: number; + markets: number; +} + +export interface IGetCoinsListRequest { + page: number; + per_page: number; +} + +export interface IGetCoinsListResponse { + [key: string]: any; +} + +export interface IGetCoinsCountResponse { + count: number; +} + +export interface IGetCoinInfoResponse { + [key: string]: any; +} + +export interface IGetCoinInfoRequest { + id: string; +} + +// export interface IGetCoinChartRequest { +// page: number; +// per_page: number; +// } + +export interface IChartDataItem { + [index: number]: number, +} + +export interface IGetCoinChartRequest { + coin: string; + days: string; +} + +export interface IGetCoinChartResponse { + market_caps: Array; + prices: Array; + total_volumes: Array; +} diff --git a/Front/src/coinApi.ts b/Front/src/coinApi.ts index 5285a6b..50e17c4 100644 --- a/Front/src/coinApi.ts +++ b/Front/src/coinApi.ts @@ -1,48 +1,21 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' +import { + IGetGlobalResponse, + IGetCoinsListRequest, + IGetCoinsListResponse, + IGetCoinsCountResponse, + IGetCoinInfoRequest, + IGetCoinInfoResponse, + IGetCoinChartRequest, + IGetCoinChartResponse, +} from './coinApi-types' -// URL's const baseUrl = "http://127.0.0.1:8080"; const marketsUrl = '/coins/markets'; const countUrl = '/count'; const globalUrl = '/global'; -const coinInfoUrl = (id:string) => `/coin/${id}`; -const coinChartUrl = (id:string) => `/coin/${id}/chart`; - -export interface IGetGlobalResponse { - active_cryptocurrencies: number; - markets: number; -} - -export interface IGetCoinsListResponse { - [key: string]: any; -} - -export interface IGetCoinsCountResponse { - count: number; -} - -export interface IGetCoinsInfoResponse { - [key: string]: any; -} - -export interface IGetCoinsInfoRequest { - id: string; -} - -export interface IGetCoinsChartRequest { - page: number; - per_page: number; -} - -export interface IChartDataItem { - [index: number]: number, -} - -export interface IGetCoinsChartResponse { - market_caps: Array; - prices: Array; - total_volumes: Array; -} +const coinInfoUrl = (id: string) => `/coin/${id}`; +const coinChartUrl = (coin: string, days: string) => `/coin/${coin}/chart/${days}`; export const coinListApi = createApi({ baseQuery: fetchBaseQuery({ baseUrl: baseUrl }), @@ -50,18 +23,18 @@ export const coinListApi = createApi({ getGlobal: builder.query({ query: () => globalUrl, }), - getCoinsList: builder.query({ - query: (payload: IGetCoinsChartRequest) => `${marketsUrl}?per_page=${payload.per_page}&page=${payload.page}`, + getCoinsList: builder.query({ + query: (payload: IGetCoinsListRequest) => `${marketsUrl}?per_page=${payload.per_page}&page=${payload.page}`, }), getCoinsCount: builder.query({ query: () => countUrl, }), - getCoinInfo: builder.query({ + getCoinInfo: builder.query({ query: (id: string) => coinInfoUrl(id), }), - getCoinChart: builder.query({ - query: (id: string) => coinChartUrl(id), - }), + getCoinChart: builder.query({ + query: (payload: {coin: string, days: string}) => coinChartUrl(payload.coin, payload.days), + }), }), }) @@ -71,4 +44,4 @@ export const { useGetCoinsCountQuery, useGetCoinInfoQuery, useGetCoinChartQuery - } = coinListApi; +} = coinListApi; diff --git a/Front/src/coinDetails/coinChart-types.ts b/Front/src/coinDetails/coinChart-types.ts new file mode 100644 index 0000000..0a8c8c4 --- /dev/null +++ b/Front/src/coinDetails/coinChart-types.ts @@ -0,0 +1,20 @@ +export interface ICoinChartProps { + coin: string; +} + +export interface IChartDataItem { + [index: number]: number, +} + +export interface IChartData { + market_caps: Array; + prices: Array; + total_volumes: Array; +} + +export interface IChartDataFormattedItem { + x: Date; + y: number; +} + +export interface IChartDataFormatted extends Array { }; diff --git a/Front/src/coinDetails/coinChart.tsx b/Front/src/coinDetails/coinChart.tsx index d2cf6bb..77f5882 100644 --- a/Front/src/coinDetails/coinChart.tsx +++ b/Front/src/coinDetails/coinChart.tsx @@ -1,3 +1,4 @@ +import React from 'react'; import { Chart as ChartJS, CategoryScale, @@ -17,6 +18,13 @@ import Button from '@mui/material/Button'; import ButtonGroup from '@mui/material/ButtonGroup'; import Grid from '@mui/material/Grid'; +import { + ICoinChartProps, + IChartDataItem, + IChartData, + IChartDataFormatted +} from './coinChart-types'; + ChartJS.register( CategoryScale, LinearScale, @@ -28,82 +36,118 @@ ChartJS.register( Legend ); - -export interface ICoinChartProps { - coin: string; +export interface IDurationOption { + label: string; + value: string; } -export interface IChartDataItem { - [index: number]: number, -} - -export interface IChartData { - market_caps: Array; - prices: Array; - total_volumes: Array; -} - -export interface IChartDataFormattedItem { - x: Date; - y: number; -} - -export interface IChartDataFormatted extends Array { }; - - - - -export const options = { - responsive: false, - maintainAspectRatio: false, - plugins: {}, -}; +export interface IDurationOptions extends Array { } const CoinChart = (props: ICoinChartProps): JSX.Element => { - // console.log("props: ", props); - const { data, isSuccess: isSuccessChart } = useGetCoinChartQuery(props.coin); + + const ref = React.useRef(null); + const [duration, setDuration] = React.useState('max') + const [redraw, setRedraw] = React.useState(false); + + // BUG: responsive and redraw toghether cause double render + React.useEffect(() => { + function handleResize() { + setTimeout(function () { setRedraw(true) }, 1000); + setTimeout(function () { setRedraw(false) }, 2000); + } + window.addEventListener('resize', handleResize) + }, []); + + + const chartRequest = { + coin: props.coin, + days: duration + } + + const { data, isSuccess, refetch } = useGetCoinChartQuery(chartRequest); + + + const durationOptions: IDurationOptions = [ + { label: "1D", value: '1' }, + { label: "2W", value: '14' }, + { label: "1M", value: '30' }, + { label: "3M", value: '90' }, + { label: "1Y", value: '365' }, + { label: "MAX", value: 'max' } + ]; function formatChartData(data: IChartData): IChartDataFormatted { - const chartData = data['prices'].map(function (value: IChartDataItem) { + return data['prices'].map(function (value: IChartDataItem) { return { x: new Date(value[0]), y: value[1], }; }); - return chartData; } function formatChartLabels(data: any): any { - const labels = data['prices'].map((value: (string | number | Date)[]) => format(new Date(value[0]), 'MM/dd/yyyy')); - return labels; + return data['prices'].map((value: (string | number | Date)[]) => + format(new Date(value[0]), 'MM/dd/yyyy') + ); } + function durationHandler(value: string): void { + setDuration(value) + refetch() + } + + const chartOptions = { + elements: { + point: { + radius: 0 + } + }, + color: '#444444', + borderColor: '#444444', + backgroundColor: '#444444', + responsive: true, + maintainAspectRatio: true, + aspectRatio: 2, + pointRadius: 0, + plugins: { + legend: { + display: false + }, + }, + }; + return ( -
+
{ data && <> - - - - - - + { + durationOptions.map(item => + ) + } -
- - - +
+
} diff --git a/Front/src/coinDetails/coinInfo.tsx b/Front/src/coinDetails/coinInfo.tsx index c5cc3a3..467a9ee 100644 --- a/Front/src/coinDetails/coinInfo.tsx +++ b/Front/src/coinDetails/coinInfo.tsx @@ -40,25 +40,23 @@ const CoinInfo = (props: ICoinInfoProps): JSX.Element => { - + {/* {data.links.subreddit_url && } - {data.links.twitter_screen_name && } - {data.links.chat_url && } - + */}
) } diff --git a/Front/src/index.css b/Front/src/index.css index 606d554..b71c7c9 100644 --- a/Front/src/index.css +++ b/Front/src/index.css @@ -32,6 +32,12 @@ header a { color: #e15241 } + +/* #chart { + position: absolute; + height: 400px; +} */ + .coinName { font-weight: bold; margin-left: 10px;