Fitness Tracker Dashboard
This demo shows how you can include multiple grids on the same page and conditionally highlight different types of information in each of them.
Result
Full
HTML
CSS
JS
Edit
Download
Fitness Tracker Dashboard
Monitor your heart rate, calorie consumption, and activity logs in one place with a dashboard overview of your data.
Full Code
<!DOCTYPE html> <html class="zg-html"> <head> <meta charset="utf-8"> <title>ZingGrid: Blank Grid</title> <script nonce="undefined" src="https://cdn.zinggrid.com/dev/zinggrid-dev.min.js"></script> <style> .zg-body { background: #F3F3F3; padding: 30px; font-family: 'Heebo', sans-serif; } .zg-body .dashboard-container { max-width: 1000px; margin: 0 auto; } .zg-body h1 { color: #606470; margin-bottom: 10px; font-weight: 300; } .zg-body p { color: #606470; margin: 0 0 10px 0; font-weight: 300; } .zg-body hr { display: block; height: 1px; border: 0; border-top: 1px solid #dddddd; margin: 1em 0; padding: 0; margin: 0 0 30px 0; } .zg-body .columns { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 2em; margin: 2rem 0; /* min-height: 440px; */ width: 100%; } .zg-body .fas { padding-right: 5px; font-size: 15px; } .zg-body .blue { color: #2f89fc; } .zg-body .gold { color: #f4b342; } .zg-body .green { color: #4bbb8b; } .zg-body .grey { color: #ccc; } .zg-body .red { color: #ff5759; } /* Grid */ zing-grid { max-width: 1000px; margin: 0 auto; font-family: 'Heebo', sans-serif; font-size: 11px; background: #ffffff; border: none; color: #ffffff; --theme-color-primary: #606470; --zg-cell-background_sorted: #eee; --zg-head-cell-background_sorted: #ccc; --zg-icon-init-fill: #606470; --zg-head-cell-icon-color_sorted: #606470; --zg-select-arrow-color: #606470; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.05), 0 6px 20px 0 rgba(0, 0, 0, 0.09); opacity: 1; } zing-grid.loading { opacity: 0; transition: opacity .3s ease-out; } zg-caption { border-bottom: 1px solid #efefef; font-weight: 400; background: #ffffff; color: #606470; border-radius: 8px 8px 0 0; -webkit-border-radius: 8px 8px 0 0; -moz-border-radius: 8px 8px 0 0; } zg-control-bar { display: none; } zg-head, zg-head-cell { background: #ffffff; color: #606470; font-size: 9px; font-weight: bold; text-transform: none; } zg-icon { width: 15px; } zg-head, zg-body { border: none; } zg-row { border-bottom: 1px solid #efefef; background: #ffffff; color: #414141; } zg-row, zg-cell { padding: 0 15px; height: 40px; } zg-body zg-row:last-child { border-radius: 0 0 8px 8px; -moz-border-radius: 0 0 8px 8px; -webkit-border-radius: 0 0 8px 8px; } zg-pager { background: #ffffff; margin-top: 0px; color: #606470; border-radius: 0 0 8px 8px; -webkit-border-radius: 0 0 8px 8px; -moz-border-radius: 0 0 8px 8px; font-size: 10px; } .zg-body .bike { color: #2f89fc; font-weight: bold; } zg-row.outdoor-bike { color: #2f89fc; font-weight: normal; } .zg-body .run, .zg-body .peak { color: #ff5759; font-weight: bold; } zg-row.run { color: #ff5759; font-weight: normal; } zg-row.peak { color: #ff5759; font-weight: normal; } .zg-body .sport { color: #4bbb8b; font-weight: bold; } zg-row.sport { color: #4bbb8b; font-weight: normal; } .zg-body .not-peak { color: #cccccc; } .zg-body .calorie-goal { color: #f4b342; font-weight: bold; } .zg-body .bold { font-weight: bold; } @media screen and (max-width: 650px) { .columns { display: block !important; margin-bottom: 30px; } .zg-body .columns zing-grid:first-child { margin-bottom: 30px; } } zing-grid[loading] { height: 1096px; } </style> </head> <body class="zg-body"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous"> <link href="https://fonts.googleapis.com/css?family=Heebo:300,400,700" rel="stylesheet"> <div class="dashboard-container"> <h1>Fitness Tracker Dashboard</h1> <p>Monitor your heart rate, calorie consumption, and activity logs in one place with a dashboard overview of your data.</p> <hr> <div class="columns"> <zing-grid src="https://zinggrid-examples.firebaseio.com/fitness-dashboard/1/heartRateTracker" layout="row" sort pager page-size="6" page-size-options="6,12,8,24" class="loading"> <zg-caption> <i class="fas fa-heartbeat"></i> Heart Rate Tracker </zg-caption> <zg-colgroup> <zg-column index="date"></zg-column> <zg-column index="restingHeartRate"> [[index.restingHeartRate]] bpm </zg-column> <zg-column index="timeInHeartRateZones.fatBurn" header="Fat Burn"></zg-column> <zg-column index="timeInHeartRateZones.cardio" header="Cardio"></zg-column> <zg-column index="timeInHeartRateZones.peak" header="Peak" renderer="renderPeak"></zg-column> </zg-colgroup> </zing-grid> <zing-grid src="https://zinggrid-examples.firebaseio.com/fitness-dashboard/2/calorieTracker" layout="row" sort pager page-size="6" page-size-options="6,12,8,24" class="loading"> <zg-caption> <i class="fas fa-burn"></i> Calorie Tracker </zg-caption> <zg-colgroup> <zg-column type="text" index="date"></zg-column> <zg-column type="number" index="breakfast"> [[index.breakfast]] cal </zg-column> <zg-column type="number" index="lunch"> [[index.lunch]] cal </zg-column> <zg-column type="number" index="dinner"> [[index.dinner]] cal </zg-column> <zg-column type="number" index="snacks"> [[index.snacks]] cal </zg-column> <zg-column type="number" index="total" renderer="renderCalorieGoal"> </zg-column> </zg-colgroup> </zing-grid> </div> <zing-grid src="https://zinggrid-examples.firebaseio.com/fitness-dashboard/0/activityTracker" row-class="_renderClassActivity" layout="row" sort pager page-size="6" page-size-options="6,12,8,24" class="loading"> <zg-caption> <i class="fas fa-child"></i> Activity Tracker </zg-caption> <zg-colgroup> <zg-column index="date"></zg-column> <zg-column index="activityType" renderer="renderActivityType"></zg-column> <zg-column index="city"></zg-column> <zg-column index="state"></zg-column> <zg-column index="distance" header="Distance"> [[index.distance]] mi </zg-column> <zg-column index="elapsedTime"></zg-column> <zg-column index="movingTime"></zg-column> </zg-colgroup> </zing-grid> </div> <script> ZingGrid.setLicense(['26ccbfec16b8be9ee98c7d57bee6e498']); // Add Row Classes function _renderClassActivity(record, $cell) { return record.activityType.replace(' ', '-').toLowerCase(); } // Cell Renderers function renderPeak(value) { const match = value === "00:00:00"; const classes = match ? 'grey' : 'red'; const peak = match ? 'not-peak' : 'peak'; return `<i class="fas fa-heartbeat ${classes}"></i> <span class="${peak}">${value}</span>`; } function renderCalorieGoal(value, $cellRef, cell) { const match = value > "2,350"; const classes = match ? 'grey' : 'gold'; const total = match ? 'not-peak' : 'calorie-goal'; return `<i class="fas fa-star ${classes}"></i> <span class="${total}">${value}</span>`; } function renderActivityType(value) { let classes, type; switch (value) { case 'Run': classes = 'fa-shoe-prints red'; type = 'run'; break; case 'Sport': classes = 'fa-volleyball-ball green'; type = 'sport'; break; default: classes = 'fa-bicycle blue'; type = 'bike'; } return `<i class="fas ${classes}"></i> <span class="${type}">${value}</span>`; } // Custom loading class for CSS handling const zgLoaded = document.querySelectorAll('zing-grid'); zgLoaded.forEach(zg => showGrid(zg)); // --- function showGrid(grid) { grid.addEventListener('grid:ready', () => { setTimeout(() => grid.classList.remove('loading'), 250); }); } </script> </body> </html>
<!DOCTYPE html> <html class="zg-html"> <head> <meta charset="utf-8"> <title>ZingGrid: Blank Grid</title> <script src="https://cdn.zinggrid.com/dev/zinggrid-dev.min.js"></script> </head> <body class="zg-body"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous"> <link href="https://fonts.googleapis.com/css?family=Heebo:300,400,700" rel="stylesheet"> <div class="dashboard-container"> <h1>Fitness Tracker Dashboard</h1> <p>Monitor your heart rate, calorie consumption, and activity logs in one place with a dashboard overview of your data.</p> <hr> <div class="columns"> <zing-grid src="https://zinggrid-examples.firebaseio.com/fitness-dashboard/1/heartRateTracker" layout="row" sort pager page-size="6" page-size-options="6,12,8,24" class="loading" > <zg-caption> <i class="fas fa-heartbeat"></i> Heart Rate Tracker </zg-caption> <zg-colgroup> <zg-column index="date"></zg-column> <zg-column index="restingHeartRate"> [[index.restingHeartRate]] bpm </zg-column> <zg-column index="timeInHeartRateZones.fatBurn" header="Fat Burn"></zg-column> <zg-column index="timeInHeartRateZones.cardio" header="Cardio"></zg-column> <zg-column index="timeInHeartRateZones.peak" header="Peak" renderer="renderPeak"></zg-column> </zg-colgroup> </zing-grid> <zing-grid src="https://zinggrid-examples.firebaseio.com/fitness-dashboard/2/calorieTracker" layout="row" sort pager page-size="6" page-size-options="6,12,8,24" class="loading" > <zg-caption> <i class="fas fa-burn"></i> Calorie Tracker </zg-caption> <zg-colgroup> <zg-column type="text" index="date"></zg-column> <zg-column type="number" index="breakfast"> [[index.breakfast]] cal </zg-column> <zg-column type="number" index="lunch"> [[index.lunch]] cal </zg-column> <zg-column type="number" index="dinner"> [[index.dinner]] cal </zg-column> <zg-column type="number" index="snacks"> [[index.snacks]] cal </zg-column> <zg-column type="number" index="total" renderer="renderCalorieGoal"> </zg-column> </zg-colgroup> </zing-grid> </div> <zing-grid src="https://zinggrid-examples.firebaseio.com/fitness-dashboard/0/activityTracker" row-class="_renderClassActivity" layout="row" sort pager page-size="6" page-size-options="6,12,8,24" class="loading" > <zg-caption> <i class="fas fa-child"></i> Activity Tracker </zg-caption> <zg-colgroup> <zg-column index="date"></zg-column> <zg-column index="activityType" renderer="renderActivityType"></zg-column> <zg-column index="city"></zg-column> <zg-column index="state"></zg-column> <zg-column index="distance" header="Distance"> [[index.distance]] mi </zg-column> <zg-column index="elapsedTime"></zg-column> <zg-column index="movingTime"></zg-column> </zg-colgroup> </zing-grid> </div> </body> </html>
.zg-body { background: #F3F3F3; padding: 30px; font-family: 'Heebo', sans-serif; } .zg-body .dashboard-container { max-width: 1000px; margin: 0 auto; } .zg-body h1 { color: #606470; margin-bottom: 10px; font-weight: 300; } .zg-body p { color: #606470; margin: 0 0 10px 0; font-weight: 300; } .zg-body hr { display: block; height: 1px; border: 0; border-top: 1px solid #dddddd; margin: 1em 0; padding: 0; margin: 0 0 30px 0; } .zg-body .columns { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 2em; margin: 2rem 0; /* min-height: 440px; */ width: 100%; } .zg-body .fas { padding-right:5px; font-size:15px; } .zg-body .blue { color:#2f89fc; } .zg-body .gold { color: #f4b342; } .zg-body .green { color: #4bbb8b; } .zg-body .grey { color: #ccc; } .zg-body .red { color: #ff5759; } /* Grid */ zing-grid { max-width: 1000px; margin: 0 auto; font-family: 'Heebo', sans-serif; font-size: 11px; background: #ffffff; border: none; color: #ffffff; --theme-color-primary: #606470; --zg-cell-background_sorted: #eee; --zg-head-cell-background_sorted: #ccc; --zg-icon-init-fill: #606470; --zg-head-cell-icon-color_sorted: #606470; --zg-select-arrow-color: #606470; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.05), 0 6px 20px 0 rgba(0, 0, 0, 0.09); opacity: 1; } zing-grid.loading { opacity:0; transition:opacity .3s ease-out; } zg-caption { border-bottom: 1px solid #efefef; font-weight: 400; background: #ffffff; color: #606470; border-radius: 8px 8px 0 0; -webkit-border-radius: 8px 8px 0 0; -moz-border-radius: 8px 8px 0 0; } zg-control-bar { display: none; } zg-head, zg-head-cell { background: #ffffff; color: #606470; font-size: 9px; font-weight: bold; text-transform: none; } zg-icon { width: 15px; } zg-head, zg-body { border: none; } zg-row { border-bottom: 1px solid #efefef; background: #ffffff; color: #414141; } zg-row, zg-cell { padding: 0 15px; height: 40px; } zg-body zg-row:last-child { border-radius: 0 0 8px 8px; -moz-border-radius: 0 0 8px 8px; -webkit-border-radius: 0 0 8px 8px; } zg-pager { background: #ffffff; margin-top: 0px; color: #606470; border-radius: 0 0 8px 8px; -webkit-border-radius: 0 0 8px 8px; -moz-border-radius: 0 0 8px 8px; font-size: 10px; } .zg-body .bike { color: #2f89fc; font-weight: bold; } zg-row.outdoor-bike { color: #2f89fc; font-weight: normal; } .zg-body .run, .zg-body .peak { color: #ff5759; font-weight: bold; } zg-row.run { color: #ff5759; font-weight: normal; } zg-row.peak { color: #ff5759; font-weight: normal; } .zg-body .sport { color: #4bbb8b; font-weight: bold; } zg-row.sport { color: #4bbb8b; font-weight: normal; } .zg-body .not-peak { color: #cccccc; } .zg-body .calorie-goal { color: #f4b342; font-weight: bold; } .zg-body .bold { font-weight: bold; } @media screen and (max-width: 650px) { .columns { display: block !important; margin-bottom: 30px; } .zg-body .columns zing-grid:first-child { margin-bottom: 30px; } }
// Add Row Classes function _renderClassActivity(record, $cell) { return record.activityType.replace(' ', '-').toLowerCase(); } // Cell Renderers function renderPeak(value) { const match = value === "00:00:00"; const classes = match ? 'grey' : 'red'; const peak = match ? 'not-peak' : 'peak'; return `<i class="fas fa-heartbeat ${classes}"></i> <span class="${peak}">${value}</span>`; } function renderCalorieGoal(value, $cellRef, cell) { const match = value > "2,350"; const classes = match ? 'grey' : 'gold'; const total = match ? 'not-peak' : 'calorie-goal'; return `<i class="fas fa-star ${classes}"></i> <span class="${total}">${value}</span>`; } function renderActivityType(value) { let classes, type; switch (value) { case 'Run': classes = 'fa-shoe-prints red'; type = 'run'; break; case 'Sport': classes = 'fa-volleyball-ball green'; type = 'sport'; break; default: classes = 'fa-bicycle blue'; type = 'bike'; } return `<i class="fas ${classes}"></i> <span class="${type}">${value}</span>`; } // Custom loading class for CSS handling const zgLoaded = document.querySelectorAll('zing-grid'); zgLoaded.forEach(zg => showGrid(zg)); // --- function showGrid(grid) { grid.addEventListener('grid:ready', () => { setTimeout(() => grid.classList.remove('loading'), 250); }); }
Interested in this demo? Modify it to your needs in ZingSoft Studio, our testing sandbox. It's free to sign up, and you can come back and edit at any time!