diff --git a/README.md b/README.md index 923d569..a3263ec 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +# ReactJS with storybook + This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). ## Available Scripts diff --git a/package-lock.json b/package-lock.json index 0617e44..cfea5b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4262,6 +4262,47 @@ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, + "chart.js": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.8.0.tgz", + "integrity": "sha512-Di3wUL4BFvqI5FB5K26aQ+hvWh8wnP9A3DWGvXHVkO13D3DSnaSsdZx29cXlEsYKVkn1E2az+ZYFS4t0zi8x0w==", + "requires": { + "chartjs-color": "^2.1.0", + "moment": "^2.10.2" + } + }, + "chartjs-color": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.3.0.tgz", + "integrity": "sha512-hEvVheqczsoHD+fZ+tfPUE+1+RbV6b+eksp2LwAhwRTVXEjCSEavvk+Hg3H6SZfGlPh/UfmWKGIvZbtobOEm3g==", + "requires": { + "chartjs-color-string": "^0.6.0", + "color-convert": "^0.5.3" + }, + "dependencies": { + "color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" + } + } + }, + "chartjs-color-string": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", + "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", + "requires": { + "color-name": "^1.0.0" + } + }, + "chartjs-plugin-annotation": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/chartjs-plugin-annotation/-/chartjs-plugin-annotation-0.5.7.tgz", + "integrity": "sha1-G/DjAZmmqf+Yic4PN6HnVagNEL8=", + "requires": { + "chart.js": "^2.4.0" + } + }, "chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", @@ -9866,6 +9907,11 @@ } } }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -11888,6 +11934,15 @@ "whatwg-fetch": "3.0.0" } }, + "react-chartjs-2": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-2.8.0.tgz", + "integrity": "sha512-BPpC+qfnh37DkcXvxRwA1rdD9rX/0AQrwru4VZTLofCCuZBwRsc7PbfxjilvoB6YlHhorwZu40YDWEQkoz7xfQ==", + "requires": { + "lodash": "^4.17.4", + "prop-types": "^15.5.8" + } + }, "react-clientside-effect": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.2.tgz", diff --git a/package.json b/package.json index c334a42..a1ee62a 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,11 @@ "dependencies": { "@material-ui/core": "^4.5.0", "@material-ui/icons": "^4.4.3", + "chart.js": "^2.8.0", + "chartjs-plugin-annotation": "^0.5.7", "prop-types": "^15.7.2", "react": "^16.10.1", + "react-chartjs-2": "^2.8.0", "react-dom": "^16.10.1", "react-scripts": "3.2.0" }, diff --git a/src/serviceWorker.js b/serviceWorker.js similarity index 100% rename from src/serviceWorker.js rename to serviceWorker.js diff --git a/src/modules/common/components/ChartComponent.js b/src/modules/common/components/ChartComponent.js new file mode 100644 index 0000000..2823252 --- /dev/null +++ b/src/modules/common/components/ChartComponent.js @@ -0,0 +1,226 @@ +import React, { useState } from 'react'; +import { Line } from 'react-chartjs-2'; +import annotationPlugin from 'chartjs-plugin-annotation'; +import PropTypes from 'prop-types'; +import '../styles/ChartComponent.css'; +import sampleData from '../constants/chartSample'; + +// styles options for the Chart +const options = { + layout: { + padding: { + left: 40, + right: 40, + top: 40, + bottom: 20, + }, + }, + legend: { + display: false, + }, + scales: { + yAxes: [{ + ticks: { + beginAtZero: true, + suggestedMax: 10, + callback: () => '', + }, + gridLines: { + display: false, + drawBorder: false, + }, + }], + xAxes: [{ + ticks: { + fontFamily: 'Nunito', + fontColor: '#727272', + fontSize: 10, + }, + gridLines: { + display: false, + drawBorder: false, + }, + }], + }, + plugins: [annotationPlugin], + annotation: { + annotations: [{ + type: 'line', + mode: 'horizontal', + scaleID: 'y-axis-0', + value: 5, + borderColor: 'rgba(0, 0, 0, 0.4)', + borderWidth: 1, + label: { + enabled: false, + content: 'Test label', + }, + }], + }, +}; + +// default months array used for labels in the chart +const listMonth = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']; + +// the Data configuration for charts +const dataChart = (propData, monthLabels, lengthArray) => ({ + labels: propData.mind.length < monthLabels.length + ? monthLabels.slice(0, propData.mind.length).reverse() + : monthLabels.reverse(), + datasets: [ + { + label: 'MIND', + fill: false, + pointRadius: 0, + borderColor: '#5065CB', + data: propData.mind.slice(0, lengthArray).reverse(), + }, + { + label: 'BODY', + fill: false, + pointRadius: 0, + borderColor: '#CB50C4', + data: propData.body.slice(0, lengthArray).reverse(), + }, + { + label: 'SOUL', + fill: false, + pointRadius: 0, + borderColor: '#50ADCB', + data: propData.soul.slice(0, lengthArray).reverse(), + }, + { + label: 'WORK', + fill: false, + pointRadius: 0, + borderColor: '#FFB800', + data: propData.work.slice(0, lengthArray).reverse(), + }, + { + label: 'PLAY', + fill: false, + pointRadius: 0, + borderColor: '#FD9184', + data: propData.play.slice(0, lengthArray).reverse(), + }, + { + label: 'LOVE', + fill: false, + pointRadius: 0, + borderColor: '#A0AEF6', + data: propData.love.slice(0, lengthArray).reverse(), + }, + ], +}); + +// A helper funcion used to get an array of a category +// if the array length is 1 month, add 0 values to compare +const buildCategoryArray = (data, category) => { + const wellnessList = []; + data.map((record) => !!record[category] && wellnessList.push(record[category])); + if (wellnessList.length === 1) wellnessList.push(0); + + return wellnessList; +}; + +// A function that return an object of each category with array of values +const data = (propData) => ({ + mind: buildCategoryArray(propData, 'mind'), + body: buildCategoryArray(propData, 'body'), + soul: buildCategoryArray(propData, 'soul'), + work: buildCategoryArray(propData, 'work'), + play: buildCategoryArray(propData, 'play'), + love: buildCategoryArray(propData, 'love'), +}); + +// A function that return a months array from current Month to last 'X' months +// the 'X' value can be 12, 6 or 3. +const calculateMonths = (lengthArray) => { + const currentMonth = new Date().getMonth(); + const ordererMonth = []; + + listMonth.forEach((val, index) => { + if (currentMonth < index) { + ordererMonth.push(listMonth[(listMonth.length - index) + currentMonth]); + } else ordererMonth.push(listMonth[currentMonth - index]); + }); + return ordererMonth.slice(0, lengthArray); +}; + +const ColoredLine = ({ color }) => ( +