Table of Contents
npx create-react-app my-sales cd my-salesmy-sales is the working directory where the React Boilerplate will be installed along with all the utilities and dependencies.
npm install bootstrap --save
npm install fusioncharts --saveThe React-component provided by FusionCharts can be used to add JS charts in our app without any difficulty. To check them out, click here.
npm install react-fusioncharts --save
npm install fusionmaps
import React from 'react'; import FusionCharts from 'fusioncharts'; import Charts from 'fusioncharts/fusioncharts.charts'; import Maps from 'fusioncharts/fusioncharts.maps'; import World from 'fusionmaps/maps/es/fusioncharts.world'; import PowerCharts from 'fusioncharts/fusioncharts.powercharts'; import ReactFC from 'react-fusioncharts'; import FusionTheme from 'fusioncharts/themes/fusioncharts.theme.fusion'; ReactFC.fcRoot(FusionCharts, Charts, PowerCharts, Maps, World, FusionTheme);We have added all the dependencies for our dashboard app, so let’s set up the Google Sheets API.
componentDidMount()
is invoked immediately after a component is mounted. This is exactly where AJAX requests and DOM or state updates should occur. Below is the code to fetch the response from the JSON data: const url = `https://sheets.googleapis.com/v4/spreadsheets/${config.spreadsheetId}/ values:batchGet?ranges=SalesDataFinal&majorDimension=ROWS&key=${config.apiKey}`; componentDidMount() { fetch(url).then(response => response.json()).then(data => { let batchRowValues = data.valueRanges[0].values; const rows = []; for (let i = 1; i < batchRowValues.length; i++) { let rowObject = {}; for (let j = 0; j < batchRowValues[i].length; j++) { rowObject[batchRowValues[0][j]] = batchRowValues[i][j]; } rows.push(rowObject); } this.setState({ items: rows}, () => this.getData('All','2016')); }); }
<nav className ="navbar navbar-expand-sm text-sm-center text-md-left fixed-top"> <div className="navbar-brand"><span className="logo">S</span>ales Dashboard</div> <ul className="navbar-nav flex-row ml-sm-auto"> <li className="nav-item"> <div className="profile"> <img alt="" className="mr-3 rounded-circle border" width="42" src="./Image-Tim.png" /> <span className="name d-none d-sm-inline-flex">Hey, Tim </span> </div> </li> </ul> <div className="row mb-5"> <div className="col-2"> </div> <div className="col text-right time-selector"> <ul className="list-inline"> <li className="list-inline-item"> <div className="dropdown active-item"> <button className="btn btn-secondary dropdown-toggl type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> {this.state.value} </button> <div className="dropdown-menu" aria-labelledby="dropdownMenuButton"> <div className="dropdown-item" value ="2018" id="btn-2018" onClick ={this.updateDashboard} >2018</div> <div className="dropdown-item" value ="2017" id="btn-2017" onClick ={this.updateDashboard} >2017</div> <div className="dropdown-item" value ="2016" id="btn-2016"onClick ={this.updateDashboard} >2016</div> </div> </div> </li> <li className="list-inline-item"> <div className="dropdown"> <button className="btn btn-secondary dropdown-toggl type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> {this.state.quarterValue} </button> <div className="dropdown-menu" for="navbarDropdown" aria-labelledby="navbarDropdown"> <div className="dropdown-item" disabled>--Select Quarter--</div> <div id ="btn-q1" className="dropdown-item" onClick ={this.updateDashboardQuarter}>Quarter 1</div> <div id ="btn-q2" className="dropdown-item" onClick ={this.updateDashboardQuarter}>Quarter 2</div> <div id ="btn-q3" className="dropdown-item" onClick ={this.updateDashboardQuarter}>Quarter 3</div> <div id ="btn-q4" className="dropdown-item" onClick ={this.updateDashboardQuarter}>Quarter 4</div> <div id ="btn-q5" className="dropdown-item" onClick ={this.updateDashboardQuarter}>Quarter 1</div> <div id ="btn-q6" className="dropdown-item" onClick ={this.updateDashboardQuarter}>Quarter 2</div> <div id ="btn-q7" className="dropdown-item" onClick ={this.updateDashboardQuarter}>Quarter 3</div> <div id ="btn-q8" className="dropdown-item" onClick ={this.updateDashboardQuarter}>Quarter 4</div> <div id ="btn-q9" className="dropdown-item" onClick ={this.updateDashboardQuarter}>Quarter 1</div> <div id ="btn-q10" className="dropdown-item" onClick ={this.updateDashboardQuarter}>Quarter 2</div> <div id ="btn-q11" className="dropdown-item" onClick ={this.updateDashboardQuarter}>Quarter 3</div> <div id ="btn-q12" className="dropdown-item" onClick ={this.updateDashboardQuarter}>Quarter 4</div> </div> </div> </li> </ul> </div> </div></nav>We will now create a container to house both the KPI and Chart sections of the dashboard. Take a look at the HTML snippet below:
<div className="card c-portlet c-portlet--height-fluid-half d-flex align-items-start flex-column"> <div className="d-flex"> <span className="oval d-flex justify-content-center "> <img src={'./revenuetarget.svg'} alt="fireSpot" className= "img-responsive rounded-circle" width="20"/> </span> <p className="c-portlet-title">Revenue Target</p> </div> <div className="kpi-block mt-3"> <div className="c-portlet-value"> <span className="h1">$</span> {this.state.targetRevenue} </div> <div id="added-meta-target" className="targetRevenue"> <span className="h5 poa meta-value-text1">Target in <span className="defaultQtr_value"> {this.state.quarterValue}</span>, {this.state.value}</span> </div> </div> <div className="d-flex align-items-center kpi-block mt-4 mb-2"> <span className="rectangle d-flex justify-content-center "> </span> <div id ="kpi-target" data-up=" more" data-down=" less"></div> <span className ="h5 mb-0"> of target achieved</span> </div> </div>Now that our layout is ready, we will define functionality for elements and feed data to them from Google Sheets. For this, we will define a function called getData in our component which will take the year and quarter as arguments to de-structure google sheets data present in the app’s state.
getData = (arg,arg2) => { // google sheet data const arr = this.state.items; const arrLen = arr.length; let chartDataArr = []; let targetRevenueVal =0; let targetRevenueFlag =false; //KPI 1 - Target achieved const targetElem = document.getElementById('kpi-target'); targetElem.classList.remove('has-up-val'); targetElem.classList.remove('has-down-val'); //Annual Data for (let i = 0; i < arrLen; i++) { let monthStr = (arr[i])['year']; if (monthStr.includes(arg2)) { chartDataArr.push(arr[i]); if(targetRevenueFlag===false) { targetRevenueVal=parseInt(arr[i].revenueTarget_Annual); targetRevenueFlag = true; } } } //Quarterly Data if(arg !== "All") { chartDataArr = []; targetRevenueFlag =false; for (let i = 0; i < arrLen; i++) { let quarterStr = (arr[i])['quarter']; if (quarterStr.includes(arg)) { if(targetRevenueFlag===false) { targetRevenueVal=parseInt(arr[i].revenueTarget); targetRevenueFlag = true; } chartDataArr.push(arr[i]); } } } //Percent of targets achieved let target = (oppClosedVal/targetRevenueVal)*100; const targetPercent =(target).toFixed(2); if(target < 100 ) { target = 100-target; targetElem.innerHTML = Math.abs(target) + '%'; targetElem.classList.add('has-down-val'); } else if(target >= 100 ) { target = target -100; targetElem.innerHTML = Math.abs(target) +'%'; targetElem.classList.add('has-up-val'); } document.getElementById("kpi-target").innerHTML = (target.toFixed(2))+'%'; }The above code snippet will create one KPI for Revenue Target. Likewise, we will make cards for all four KPIs for the Sales Dashboard.
containerBackgroundOpacity
is an attribute that is used to manipulate the background opacity of the charts. /*Multi-series line chart*/ <div className="col-md-6 col-xl-9 order-2 order-md-1 order-xl-1 "> <div className="card c-portlet c-portlet--height-fluid pipeline-card full-height"> </div> </div> /*Multi-series column 2D Chart*/ <div className="col-md-6 col-xl-8 order-2 order-md-1 order-xl-1 "> <div className="card c-portlet c-portlet--height-fluid full-height pipelineClosing-card"> </div> </div> /*Map Chart*/ <div className="col-md-12 col-xl-6 order-2 order-md-1 order-xl-1 "> <div className="card c-portlet c-portlet--height-fluid full-height map-card"> </div> </div></pre>The above code snippet will create one chart card each for Multi-series Charts, StackedLine, and Map. Follow the steps to build the chart cards and you will have the chart layout. And to make sure you are getting it right, take a look at the code files in my Github repository. Now, we will form the JSON data array for each chart and consume the cosmetic options defined and add it to the apps’ state.
//Multi-series column 2D chart type: 'mscolumn2d', width: '100%', height: '100%', dataFormat: 'json', dataSource: {datasource } } this.setState({stackData: chartConfigs1}); //World Map const chartConfigs2 = { type : "world", width : '100%', height : '95%', dataFormat : "JSON", dataSource :{datasource} } this.setState({mapData: chartConfigs2}); //Multi-series line chart const chartConfigs3 = { type: 'msline', width: '100%', height: '150%', dataFormat: 'json', dataSource: {datasource} } this.setState({mslineData: chartConfigs3});We will now pass the JSON data to the FusionCharts’ React component under the element which we have created for each chart.
<div className="card c-portlet c-portlet--height-fluid pipeline-card full-height"> <div className="card c-portlet c-portlet--height-fluid pipeline-card full-height"> <reactfc {...this.state.mslineData} containerBackgroundOpacity ="0"></reactfc> </div> <div className="card c-portlet c-portlet--height-fluid pipeline-card full-height"> <reactfc {...this.state.stackData} containerBackgroundOpacity ="0"></reactfc> </div> <div className="card c-portlet c-portlet--height-fluid full-height map-card"> <reactfc {...this.state.mapData} containerBackgroundOpacity ="0"></reactfc> </div></div>If you’ve followed these steps till now, then you should have a functional dashboard as in the image below:
We’re excited to announce the upcoming release of FusionCharts v4.1—a groundbreaking step forward in the…
Have you ever been overwhelmed by a massive data set and wondered, "How do I…
If you’ve ever tried to make sense of the stock market, you’ve probably come across…
Imagine you’re comparing the sales performance of your top product lines across different regions, or…
Have you ever spent hours buried in documentation, hunting for a specific piece of code?…
Do you feel like your data is a cryptic puzzle, locked away from revealing its…
View Comments
Amazing post !