This dashboard example for healthcare data analysis explains how the pivot table for React can be used to create a dashboard view.
To create a dashboard on your web page, add multiple instances of Flexmonster, fill them with data, and create custom reports. With both tables and charts, you'll receive a robust yet lightweight dashboard.
You can further improve the dashboard for your React application with online data visualizations: use 3rd party charting libraries and add a little bit of eccentricity.
import React from "react";
import * as FlexmonsterReact from "react-flexmonster";
class FlexmonsterDashboard extends React.Component {
render() {
return (
<>
<div className="demo-box">
<div className="demo-title">Treatment Costs by Departments</div>
<FlexmonsterReact.Pivot
componentFolder="https://cdn.flexmonster.com/"
height={385}
licenseFilePath="https://cdn.flexmonster.com/jsfiddle.charts.key"
report={{
dataSource: {
type: "json",
filename: "https://cdn.flexmonster.com/data/dashboad-demo-data.json",
},
slice: {
rows: [
{
uniqueName: "Division",
},
],
columns: [
{
uniqueName: "Patient Status",
},
{
uniqueName: "[Measures]",
},
],
measures: [
{
uniqueName: "Treatment Cost",
aggregation: "sum",
format: "currency",
},
],
},
conditions: [
{
formula: "#value < 6000",
measure: "Treatment Cost",
aggregation: "sum",
format: {
backgroundColor: "#00A45A",
color: "#fff",
fontFamily: "Arial",
fontSize: "12px",
},
isTotal: false,
},
{
formula: "#value > 12000",
measure: "Treatment Cost",
aggregation: "sum",
format: {
backgroundColor: "#df3800",
color: "#fff",
fontFamily: "Arial",
fontSize: "12px",
},
isTotal: false,
},
],
options: {
configuratorButton: false,
drillThrough: false,
timePattern: "m'h' ss'min'",
},
formats: [
{
name: "",
thousandsSeparator: ",",
decimalSeparator: ".",
decimalPlaces: 2,
},
{
name: "currency",
currencySymbol: "$",
},
],
tableSizes: {
columns: [
{
tuple: [],
measure: {
uniqueName: "Treatment Cost",
aggregation: "sum",
},
width: 180,
},
{
tuple: ["patient status.[inpatient]"],
measure: {
uniqueName: "Treatment Cost",
aggregation: "sum",
},
width: 180,
},
{
tuple: ["patient status.[outpatient]"],
measure: {
uniqueName: "Treatment Cost",
aggregation: "sum",
},
width: 180,
},
],
},
}}
/>
</div>
<div className="demo-box">
<div className="row">
<div className="col-6">
<div className="demo-title">Overall Customer Satisfaction</div>
<FlexmonsterReact.Pivot
componentFolder="https://cdn.flexmonster.com/"
height={390}
licenseFilePath="https://cdn.flexmonster.com/jsfiddle.charts.key"
report={{
dataSource: {
type: "json",
filename: "https://cdn.flexmonster.com/data/dashboad-demo-data.json",
},
slice: {
rows: [
{
uniqueName: "Satisfaction",
},
],
columns: [
{
uniqueName: "[Measures]",
},
],
measures: [
{
uniqueName: "Satisfaction Percentage",
formula: 'count("Patient Status") / 200',
caption: "Satisfaction Percentage",
format: "satisfaction_perc",
},
],
},
options: {
viewType: "charts",
configuratorButton: false,
drillThrough: false,
chart: {
type: "pie",
showFilter: false,
showLegend: false,
showMeasures: false,
},
},
formats: [
{
name: "currency",
currencySymbol: "$",
},
{
name: "",
decimalPlaces: 2,
},
{
name: "satisfaction_perc",
isPercent: true,
},
],
}}
/>
</div>
<div className="col-6">
<div className="demo-title right-text">
Customer Satisfaction by Patient Status
</div>
<div id="column-chart">
<FlexmonsterReact.Pivot
componentFolder="https://cdn.flexmonster.com/"
height={390}
licenseFilePath="https://cdn.flexmonster.com/jsfiddle.charts.key"
report={{
dataSource: {
type: "json",
filename: "https://cdn.flexmonster.com/data/dashboad-demo-data.json",
},
slice: {
rows: [
{
uniqueName: "Satisfaction",
},
],
columns: [
{
uniqueName: "Patient Status",
},
{
uniqueName: "[Measures]",
},
],
measures: [
{
uniqueName: "Satisfaction Percentage",
formula: "count('Patient Status') / 200",
caption: "Satisfaction Percentage",
format: "satisfaction_perc",
},
],
},
options: {
viewType: "charts",
configuratorButton: false,
drillThrough: false,
chart: {
type: "stacked_column",
showFilter: false,
showMeasures: false,
},
},
formats: [
{
name: "",
decimalPlaces: 2,
},
{
name: "satisfaction_perc",
isPercent: true,
},
],
}}
/>
</div>
</div>
</div>
</div>
<div className="demo-box">
<div className="demo-title">Overall Customer Satisfaction</div>
<div className="row">
<div className="col-6">
<FlexmonsterReact.Pivot
componentFolder="https://cdn.flexmonster.com/"
height={300}
licenseFilePath="https://cdn.flexmonster.com/jsfiddle.charts.key"
report={{
dataSource: {
type: "json",
filename: "https://cdn.flexmonster.com/data/dashboad-demo-data.json",
},
slice: {
rows: [
{
uniqueName: "Satisfaction",
},
],
columns: [
{
uniqueName: "Patient Status",
},
{
uniqueName: "[Measures]",
},
],
measures: [
{
uniqueName: "Average Waiting Time",
formula: 'average("Waiting Time")',
caption: "Waiting Time",
format: "time_format",
},
{
uniqueName: "Treatment Cost",
aggregation: "sum",
active: false,
format: "currency",
},
],
sorting: {
column: {
type: "asc",
tuple: [],
measure: {
uniqueName: "Average Waiting Time",
},
},
},
},
conditions: [
{
formula: "#value < 50",
measure: "Average Waiting Time",
isTotal: true,
format: {
backgroundColor: "#00A45A",
color: "#FFFFFF",
fontFamily: "Arial",
fontSize: "12px",
},
},
{
formula: "#value > 102",
measure: "Average Waiting Time",
isTotal: true,
format: {
backgroundColor: "#df3800",
color: "#FFFFFF",
fontFamily: "Arial",
fontSize: "12px",
},
},
],
options: {
configuratorButton: false,
drillThrough: false,
grid: {
showHeaders: false,
showFilter: false,
dragging: false,
},
},
formats: [
{
name: "",
thousandsSeparator: ",",
decimalSeparator: ".",
decimalPlaces: 2,
},
{
name: "currency",
currencySymbol: "$",
},
{
name: "time_format",
thousandsSeparator: ",",
decimalSeparator: ":",
decimalPlaces: 0,
nullValue: "",
currencySymbol: "min",
positiveCurrencyFormat: "1min",
textAlign: "right",
isPercent: false,
},
],
}}
customizeCell={this.customizeCellFunction}
/>
</div>
<div className="col-6">
<FlexmonsterReact.Pivot
componentFolder="https://cdn.flexmonster.com/"
height={300}
licenseFilePath="https://cdn.flexmonster.com/jsfiddle.charts.key"
report={{
dataSource: {
type: "json",
filename: "https://cdn.flexmonster.com/data/dashboad-demo-data.json",
},
slice: {
rows: [
{
uniqueName: "Division",
},
],
columns: [
{
uniqueName: "[Measures]",
},
],
measures: [
{
uniqueName: "Waiting Time",
aggregation: "average",
},
{
uniqueName: "Treatment Cost",
aggregation: "sum",
active: false,
format: "currency",
},
],
sorting: {
column: {
type: "desc",
tuple: [],
measure: {
uniqueName: "Waiting Time",
aggregation: "average",
},
},
},
},
options: {
viewType: "charts",
configuratorButton: false,
drillThrough: false,
chart: {
type: "bar_h",
showFilter: false,
showMeasures: false,
},
},
formats: [
{
name: "currency",
currencySymbol: "$",
},
{
name: "",
decimalPlaces: 2,
},
],
}}
/>
</div>
</div>
</div>
</>
);
}
customizeCellFunction = (cell, data) => {
if (
data.type === "header" &&
data.hierarchy?.caption === "Satisfaction" &&
data.member
) {
let name = data.member.caption;
let face = `<img class="flag" style="width:23px; height:23px;"
src="https://www.flexmonster.com/base/assets/img/demos/${name}Emoji.png">`;
cell.text = `<div style="display:flex; align-items:center; font-size:12px;
position:relative; bottom: 3px; left:2px;">${face}${data.member.caption}</div>`;
}
};
}
export default FlexmonsterDashboard;
/* Chart styles */
#fm-pivot-view .fm-axis > .fm-refLine {
stroke-dasharray: 4px;
}
#fm-pivot-view .fm-axis-dividers > .fm-refLine {
stroke: none;
}
#fm-pivot-view .fm-arc path {
stroke-width: 1.5px !important;
}
#fm-pivot-view .fm-barStack path {
stroke-width: 1px !important;
}
/* General colors (e.g., in pie chart) */
.fm-charts-color-1 {
fill: #00a45a !important;
}
.fm-charts-color-2 {
fill: #7e41ff !important;
}
.fm-charts-color-3 {
fill: #df3800 !important;
}
.fm-charts-color-4 {
fill: #ffb800 !important;
}
.fm-charts-color-5 {
fill: #00a45a !important;
}
.fm-charts-color-6 {
fill: #6F5674 !important;
}
.fm-charts-color-7 {
fill: #64343F !important;
}
/* Changing colors of columns in a stacked column chart */
#column-chart-container .fm-charts-color-1 {
fill: #00a45a !important;
}
#column-chart-container .fm-charts-color-2 {
fill: #df3800 !important;
}
#column-chart-container .fm-charts-color-3 {
fill: none;
}
div #fm-chart-legend div table tr td #lst1 li span#fm-icon-display.fm-ui-element {
background-color: #df3800 !important;
}
/* Header styles */
#fm-pivot-view .fm-x.fm-axis.fm-title {
font-size: 14px;
}
/* Hiding text labels from charts */
text#fm-yAxis-label {
visibility: hidden !important;
}
text#fm-xAxis-label {
visibility: hidden !important;
}
text.fm-x.fm-axis.fm-title {
visibility: hidden !important;
}
/* Other */
.demo-box {
background-color: #fafafa;
position: relative;
padding: 30px;
margin-bottom: 20px;
border: 1px solid #e9e9e9;
}
.demo-title {
font-size: 18px;
margin-bottom: 20px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.right-text {
text-align: right;
}
.description-blocks {
margin: 30px 0 30px 0;
}
.col-6 {
float: left;
width: calc(50% - 10px);
margin-right: 20px;
}
.col-6:last-child {
margin: 0;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
@media only screen and (max-width:800px) {
.col-6 {
width: 100%;
margin: 0;
margin-bottom: 20px;
}
.demo-title.right-text {
text-align: left;
}
}
Flexmonster can aggregate raw data and display it on the grid, while a special Flexmonster Connector will pass your processed data further to Highcharts, FusionCharts, Google Charts, amCharts, or all of them.