Skip to content
Projects
2 min read

HR Turnover Analytics Dashboard

A single-file, offline-capable HTML dashboard for Mike Sport that visualizes employee headcount, hiring, and turnover trends across Head Office, Retail, and Warehouse divisions, with drill-down by individual store or department.

Role
Sole engineer
Year
2026
Status
live
datadashboardHRanalyticsvisualizationchartjs

Overview

This project is a self-contained HR analytics dashboard built for Mike Sport to track workforce headcount, hiring, and turnover across the organization. It covers monthly data across four divisions: Head Office, Retail, Warehouse, and Other, broken down into individual stores, concessions, and departments. The dashboard presents the data at three levels of granularity: an organization-wide trend view, a year-over-year comparison view, and a per-entity table that supports drilling into any single store or department.

Core metric types include: monthly headcount levels, new hires, exits, turnover rate (with a color-coded severity band for healthy, watch, and high), net hiring balance, and headcount delta over a selected date range. A "Period vs. Period" comparison panel lets a viewer compare two arbitrary time windows (either year over year or fully custom ranges) side by side, with an auto-generated narrative summary and "movers" cards highlighting which entities had the biggest headcount gains or the highest turnover in the selected window.

Approach

The dashboard is built as a single portable HTML file with the underlying dataset (months, per-store monthly records, and precomputed category-level aggregates) embedded directly in the page rather than fetched from a server. This makes the file fully offline-capable: it can be opened directly in a browser, emailed, or archived without any backend, database, or internet connection. Fonts and the charting library are embedded inline as well, so the file renders identically regardless of network access.

The UI is organized around a filter bar (division tabs, from/to month selectors, and a "full history" shortcut) that drives every chart and table on the page. All aggregation logic (per-store rollups, category totals, period comparisons, sorting) runs client-side in vanilla JavaScript, recomputing on every filter change. A raw data export (dashboard_raw.json) mirrors the structure embedded in the HTML, separating the dataset from the presentation layer for easier regeneration when new HR data comes in.

Tech stack

  • Vanilla HTML, CSS, and JavaScript (no framework, no build step)
  • Chart.js (bundled inline) for line, bar, and comparison charts
  • A custom Chart.js plugin for always-on data labels above bars and points
  • Embedded JSON dataset with precomputed category-level aggregates
  • Base64-embedded web fonts for a fully offline, dependency-free single-file deliverable

Engineering highlights

  • Single HTML file with zero external dependencies: fonts, charting library, and the full dataset are all inlined, so the dashboard works with no server, no install, and no network access.
  • Client-side drill-down architecture: one shared state object drives division tabs, a date-range picker, a sortable per-entity table, and every chart in sync.
  • Custom "always-on" value-label plugin for Chart.js so every bar and point on every chart is labeled without relying on hover tooltips.
  • Precomputed category-level aggregates kept consistent with the underlying per-store records so drill-down totals always reconcile with the top-level view.
  • A flexible period-comparison engine supporting both year-over-year and fully custom date ranges, with auto-generated plain-language narrative text and ranked "movers" lists.
  • Sparkline trend rendering per row in the store-level table for at-a-glance historical context alongside the current period numbers.

Want to dig deeper?

Ask my AI agent anything about how this was built, what tradeoffs I made, or how it could fit your team.

Ask my AI →