From fd4d25b263b651650aae33337e447dc26a55602a Mon Sep 17 00:00:00 2001 From: Ste Vaidis Date: Fri, 9 Dec 2022 20:06:04 +0200 Subject: [PATCH] changing chart lib --- Back/src/application_controller.js | 15 ++ Front/package-lock.json | 195 ++++++++++++++++++++++++++ Front/package.json | 2 + Front/src/coinApi.ts | 18 +-- Front/src/coinDetails/coinDetails.tsx | 159 +++++++++++++++++---- Front/src/coinList/coinList.tsx | 7 +- Front/src/coinList/coinListPager.tsx | 4 +- 7 files changed, 358 insertions(+), 42 deletions(-) diff --git a/Back/src/application_controller.js b/Back/src/application_controller.js index 8cbd458..b16233c 100644 --- a/Back/src/application_controller.js +++ b/Back/src/application_controller.js @@ -57,6 +57,21 @@ router.get('/coin/:id', function (req, res) { }) }) +router.get('/coin/:id/chart', function (req, res) { + let id = req.params['id']; + let url = config.coingecko.api_url + '/coins/' + id + '/market_chart?vs_currency=usd&days=max'; + console.log("chart url:", url) + api_helper.REMOTE_API_call(url) + .then(response => { + res.json(response); + }) + .catch(error => { + console.log("error: ", error); + res.send(error); + }) +}) + + diff --git a/Front/package-lock.json b/Front/package-lock.json index 3495f03..2caeaed 100644 --- a/Front/package-lock.json +++ b/Front/package-lock.json @@ -17,7 +17,9 @@ "@types/react": "^18.0.26", "@types/react-dom": "^18.0.9", "@types/react-redux": "^7.1.24", + "apexcharts": "^3.36.3", "react": "^18.2.0", + "react-apexcharts": "^1.4.0", "react-dom": "^18.2.0", "react-redux": "^8.0.5", "react-router-dom": "^6.4.4", @@ -4600,6 +4602,19 @@ "node": ">= 8" } }, + "node_modules/apexcharts": { + "version": "3.36.3", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.36.3.tgz", + "integrity": "sha512-8/FXEs0ohXMff07Gv28XjhPwEJphIUdq2/wii/pcvi54Tw6z1mjrV8ydN8rlWi/ve8BAPBefJkLmRWv7UOBsLw==", + "dependencies": { + "svg.draggable.js": "^2.2.2", + "svg.easing.js": "^2.0.0", + "svg.filter.js": "^2.0.2", + "svg.pathmorphing.js": "^0.1.3", + "svg.resize.js": "^1.4.3", + "svg.select.js": "^3.0.1" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -13847,6 +13862,18 @@ "node": ">=0.10.0" } }, + "node_modules/react-apexcharts": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.0.tgz", + "integrity": "sha512-DrcMV4aAMrUG+n6412yzyATWEyCDWlpPBBhVbpzBC4PDeuYU6iF84SmExbck+jx5MUm4U5PM3/T307Mc3kzc9Q==", + "dependencies": { + "prop-types": "^15.5.7" + }, + "peerDependencies": { + "apexcharts": "^3.18.0", + "react": ">=0.13" + } + }, "node_modules/react-app-polyfill": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", @@ -15330,6 +15357,89 @@ "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, + "node_modules/svg.draggable.js": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz", + "integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==", + "dependencies": { + "svg.js": "^2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.easing.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz", + "integrity": "sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==", + "dependencies": { + "svg.js": ">=2.3.x" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.filter.js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz", + "integrity": "sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==", + "dependencies": { + "svg.js": "^2.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.js": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz", + "integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==" + }, + "node_modules/svg.pathmorphing.js": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz", + "integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==", + "dependencies": { + "svg.js": "^2.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.resize.js": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz", + "integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==", + "dependencies": { + "svg.js": "^2.6.5", + "svg.select.js": "^2.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.resize.js/node_modules/svg.select.js": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz", + "integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==", + "dependencies": { + "svg.js": "^2.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.select.js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz", + "integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==", + "dependencies": { + "svg.js": "^2.6.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/svgo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", @@ -20135,6 +20245,19 @@ "picomatch": "^2.0.4" } }, + "apexcharts": { + "version": "3.36.3", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.36.3.tgz", + "integrity": "sha512-8/FXEs0ohXMff07Gv28XjhPwEJphIUdq2/wii/pcvi54Tw6z1mjrV8ydN8rlWi/ve8BAPBefJkLmRWv7UOBsLw==", + "requires": { + "svg.draggable.js": "^2.2.2", + "svg.easing.js": "^2.0.0", + "svg.filter.js": "^2.0.2", + "svg.pathmorphing.js": "^0.1.3", + "svg.resize.js": "^1.4.3", + "svg.select.js": "^3.0.1" + } + }, "arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -26656,6 +26779,14 @@ "loose-envify": "^1.1.0" } }, + "react-apexcharts": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.0.tgz", + "integrity": "sha512-DrcMV4aAMrUG+n6412yzyATWEyCDWlpPBBhVbpzBC4PDeuYU6iF84SmExbck+jx5MUm4U5PM3/T307Mc3kzc9Q==", + "requires": { + "prop-types": "^15.5.7" + } + }, "react-app-polyfill": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", @@ -27731,6 +27862,70 @@ "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, + "svg.draggable.js": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz", + "integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==", + "requires": { + "svg.js": "^2.0.1" + } + }, + "svg.easing.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz", + "integrity": "sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==", + "requires": { + "svg.js": ">=2.3.x" + } + }, + "svg.filter.js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz", + "integrity": "sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==", + "requires": { + "svg.js": "^2.2.5" + } + }, + "svg.js": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz", + "integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==" + }, + "svg.pathmorphing.js": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz", + "integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==", + "requires": { + "svg.js": "^2.4.0" + } + }, + "svg.resize.js": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz", + "integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==", + "requires": { + "svg.js": "^2.6.5", + "svg.select.js": "^2.1.2" + }, + "dependencies": { + "svg.select.js": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz", + "integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==", + "requires": { + "svg.js": "^2.2.5" + } + } + } + }, + "svg.select.js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz", + "integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==", + "requires": { + "svg.js": "^2.6.5" + } + }, "svgo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", diff --git a/Front/package.json b/Front/package.json index 719eafa..db36b89 100644 --- a/Front/package.json +++ b/Front/package.json @@ -12,7 +12,9 @@ "@types/react": "^18.0.26", "@types/react-dom": "^18.0.9", "@types/react-redux": "^7.1.24", + "apexcharts": "^3.36.3", "react": "^18.2.0", + "react-apexcharts": "^1.4.0", "react-dom": "^18.2.0", "react-redux": "^8.0.5", "react-router-dom": "^6.4.4", diff --git a/Front/src/coinApi.ts b/Front/src/coinApi.ts index 9ee2cb0..0692dd0 100644 --- a/Front/src/coinApi.ts +++ b/Front/src/coinApi.ts @@ -5,27 +5,29 @@ const baseUrl = "http://127.0.0.1:8080"; const marketsUrl = '/coins/markets'; const countUrl = '/count'; const coinInfoUrl = (id:string) => `/coin/${id}`; -const coinGraphUrl = (id:string) => `/coin/${id}`; +const coinChartUrl = (id:string) => `/coin/${id}/chart`; export const coinListApi = createApi({ baseQuery: fetchBaseQuery({ baseUrl: baseUrl }), endpoints: (builder) => ({ - getMarkets: builder.query({ + getCoinsList: builder.query({ query: (payload: {page: number, per_page: number}) => `${marketsUrl}?per_page=${payload.per_page}&page=${payload.page}`, }), - getCount: builder.query({ + getCoinsCount: builder.query({ query: () => countUrl, }), getCoinInfo: builder.query({ query: (id: string) => coinInfoUrl(id), }), - getCoinGraph: builder.query({ - query: (id: string) => coinGraphUrl(id), + getCoinChart: builder.query({ + query: (id: string) => coinChartUrl(id), }), }), }) export const { - useGetMarketsQuery, - useGetCountQuery, - useGetCoinInfoQuery } = coinListApi; + useGetCoinsListQuery, + useGetCoinsCountQuery, + useGetCoinInfoQuery, + useGetCoinChartQuery + } = coinListApi; diff --git a/Front/src/coinDetails/coinDetails.tsx b/Front/src/coinDetails/coinDetails.tsx index 5bba157..607f9a7 100644 --- a/Front/src/coinDetails/coinDetails.tsx +++ b/Front/src/coinDetails/coinDetails.tsx @@ -1,34 +1,137 @@ import { useParams } from 'react-router-dom'; -import { useGetCoinInfoQuery } from '../coinApi'; +import { useGetCoinInfoQuery, useGetCoinChartQuery } from '../coinApi'; +import Chart from 'react-apexcharts' +import React from 'react'; + +const options = { + chart: { + id: 'area-datetime', + type: 'area', + height: 350, + zoom: { + autoScaleYaxis: true + } + }, + annotations: { + yaxis: [{ + y: 30, + borderColor: '#999', + label: { + show: true, + text: 'Support', + style: { + color: "#fff", + background: '#00E396' + } + } + }], + xaxis: [{ + x: new Date('14 Nov 2012').getTime(), + borderColor: '#999', + yAxisIndex: 0, + label: { + show: true, + text: 'Rally', + style: { + color: "#fff", + background: '#775DD0' + } + } + }] + }, + dataLabels: { + enabled: false + }, + markers: { + size: 0, + style: 'hollow', + }, + xaxis: { + type: 'datetime', + min: new Date('01 Mar 2012').getTime(), + tickAmount: 6, + }, + tooltip: { + x: { + format: 'dd MMM yyyy' + } + }, + fill: { + type: 'gradient', + gradient: { + shadeIntensity: 1, + opacityFrom: 0.7, + opacityTo: 0.9, + stops: [0, 100] + } + }, +} + +const selection = 'one_year'; + const CoinDetails = (): JSX.Element => { - const { id } = useParams(); - console.log("id: ", id) + const { id } = useParams(); + console.log("id: ", id) - const { - data, - error, - isLoading, - isSuccess, - refetch - } = useGetCoinInfoQuery(id || 'btc'); + const { + data: dataInfo, + error: errorInfo, + isLoading: isLoadingInfo, + isSuccess: isSuccessInfo, + refetch: refetchInfo + } = useGetCoinInfoQuery(id || 'btc'); // Todo: 404 - // const { id } = data; - - return ( -
CoinDetails - { - data && -
-
ID: {data.id}
-
-
Homepage: {data.links.homepage}
-
-
Description{data.description.en}
-
- } -
- ) + const { + data: dataChart, + error: errorChart, + isLoading: isLoadingChart, + isSuccess: isSuccessChart, + refetch: refetchChart + } = useGetCoinChartQuery(id || 'btc'); // Todo: 404 + + React.useEffect(() => { + if (dataChart) { + console.log(dataChart['prices']) + } + }, [dataChart]); + + function formatChartData(data: any): any { + return data['prices'].map(function (value: any) { + return { + x: new Date(value[0]), + y: value[1], + }; + }); } - - export default CoinDetails; + + return ( +
CoinDetails + { + dataInfo && +
+
ID: {dataInfo.id}
+
+
Homepage: {dataInfo.links.homepage}
+
+
Description{dataInfo.description.en}
+
+ } + + { + dataChart && isSuccessChart && +
+ +
+ } + +
+ ) +} + +export default CoinDetails; diff --git a/Front/src/coinList/coinList.tsx b/Front/src/coinList/coinList.tsx index 91aa701..348415f 100644 --- a/Front/src/coinList/coinList.tsx +++ b/Front/src/coinList/coinList.tsx @@ -1,5 +1,5 @@ import {useSearchParams} from 'react-router-dom'; -import { useGetMarketsQuery } from '../coinApi'; +import { useGetCoinsListQuery } from '../coinApi'; import Pager from './coinListPager'; const CoinList = (): JSX.Element => { @@ -8,7 +8,7 @@ const CoinList = (): JSX.Element => { const page = Number(searchParams.get('page')) || 1 const per_page = Number(searchParams.get('per_page')) || 20 const payload = {page, per_page} - const { data, error, isLoading, isSuccess, refetch } = useGetMarketsQuery(payload); + const { data, error, isLoading, isSuccess, refetch } = useGetCoinsListQuery(payload); console.log("payload: ", payload); return ( @@ -21,8 +21,7 @@ const CoinList = (): JSX.Element => { - - + { data && isSuccess && data.map((item: any, index: any) => { return ( diff --git a/Front/src/coinList/coinListPager.tsx b/Front/src/coinList/coinListPager.tsx index 9483a9f..99f884c 100644 --- a/Front/src/coinList/coinListPager.tsx +++ b/Front/src/coinList/coinListPager.tsx @@ -1,4 +1,4 @@ -import { useGetCountQuery } from '../coinApi'; +import { useGetCoinsCountQuery } from '../coinApi'; import { useNavigate } from "react-router-dom"; const Pager = (props:any): JSX.Element => { @@ -7,7 +7,7 @@ const Pager = (props:any): JSX.Element => { const { page, per_page, } = props; - const { data, error, isLoading, isSuccess, refetch } = useGetCountQuery(); + const { data, error, isLoading, isSuccess, refetch } = useGetCoinsCountQuery(); const navigate = useNavigate(); const lastPage = Math.ceil(data / per_page)