JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.css">
<div id="table-container">
<script id="table-template" type="text/x-handlebars-template">
<table class="u-full-width">
<thead>
<tr>
<th>Project location</th>
<th>Total</th>
<th>Timestamp</th>
</tr>
</thead>
<tbody>
{{#each this}}
<tr class="name-row">
<th class="name" colspan="3">{{key}}</th>
</tr>
{{#each values}}
<tr>
<th class="group-name" colspan="4">{{key}}</th>
</tr>
{{#each values}}
<tr>
<td>{{site}}</td>
<td>{{total}}</td>
<td>
<span>{{timestamp}}</span>
</td>
</tr>
{{/each}}
{{/each}}
{{/each}}
</tbody>
</table>
</script>
CSS
.name-row {
background: #ddd;
border-top: 1px solid black;
}
.group-name {
background: #eee;
}
JavaScript
var data = [
{
key: "Region 1",
values: [
{
key: "Sub region 1",
values: [
{
site: "Site A",
timestamp: 1507246300935,
total: 3,
},
{
site: "Site B",
timestamp: 1507246300818,
total: 0,
},
{
site: "Site C",
timestamp: 1507246300936,
total: 0,
}
],
},
{
key: "Sub region 2",
values: [
{
site: "Site A",
timestamp: 1507246301442,
total: 20,
},
{
site: "Site B",
timestamp: 1507246301788,
total: 5,
}
]
},
{
key: "Sub region 3",
values: [
{
site: "Site A",
timestamp: 1507246302503,
total: 66,
},
{
site: "Site B",
timestamp: 1507246302783,
total: 2
}
]
}
]
},
{
key: "Region 2",
values: [
{
key: "Sub region 1",
values: [
{
site: "Site A",
timestamp: 1507246306789,
total: 0,
},
{
site: "Site B",
timestamp: 1507246307439,
total: 6,
}
]
},
{
key: "Sub region 2",
values: [
{
site: "Site A",
timestamp: 1507246308269,
total: 10,
},
{
site: "Site B",
timestamp: 1507246308683,
total: 30,
}
]
}
]
}
];
var source = document.getElementById('table-template').innerHTML;
var template = Handlebars.compile(source);
document.getElementById('table-container').innerHTML = template(data);