diff --git a/requirements.txt b/requirements.txt index e69de29..3ac74ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -0,0 +1,3 @@ +Install These Packages To Run The Code: +python -m install flask +python -m install paho-mqtt \ No newline at end of file diff --git a/src/dashboard/js/dashboard.js b/src/dashboard/js/dashboard.js index e69de29..24beb3a 100644 --- a/src/dashboard/js/dashboard.js +++ b/src/dashboard/js/dashboard.js @@ -0,0 +1,61 @@ +// ── Smart Campus Environmental Monitor ────────────────────── +// dashboard.js +// Author: Favour Ezeh +// Role: Project Manager | Dashboard Lead +// 4005CMD Integrative Project — Coventry University +// ──────────────────────────────────────────────────────────── + +// ── AUTO REFRESH ───────────────────────────────────────────── +// TODO Sprint 4: Replace with live MQTT data using Flask endpoint +// Currently page refreshes every 30 seconds to simulate updates + +const REFRESH_INTERVAL = 30000; // 30 seconds + +setTimeout(function() { + location.reload(); +}, REFRESH_INTERVAL); + + +// ── ALERT COUNTER ──────────────────────────────────────────── +// Updates the page title to show alert count so it's visible +// even when the browser tab is in the background + +document.addEventListener("DOMContentLoaded", function() { + const alertBadges = document.querySelectorAll(".badge.bg-danger"); + const alertCount = alertBadges.length; + + if (alertCount > 0) { + document.title = `(${alertCount} Alerts) Environmental Campus Monitor`; + } else { + document.title = "Environmental Campus Monitor"; + } +}); + + +// ── TIMESTAMP ──────────────────────────────────────────────── +// Shows the last time the page was refreshed so users know +// how current the data is + +document.addEventListener("DOMContentLoaded", function() { + const now = new Date(); + const timeString = now.toLocaleTimeString("en-GB", { + hour: "2-digit", + minute: "2-digit", + second: "2-digit" + }); + + const navbar = document.querySelector(".navbar-text"); + if (navbar) { + navbar.textContent = `Last updated: ${timeString} | 4005CMD — Coventry University`; + } +}); + + +// ── HISTORICAL CHARTS ──────────────────────────────────────── +// TODO Sprint 3: Build out Chart.js graphs here using data +// fetched from Flask /api/history endpoint +// This will include: +// - Temperature trend line chart +// - CO2 trend line chart +// - Occupancy bar chart +// - Noise level chart \ No newline at end of file diff --git a/src/dashboard/static/css/style.css b/src/dashboard/static/css/style.css index e69de29..4334329 100644 --- a/src/dashboard/static/css/style.css +++ b/src/dashboard/static/css/style.css @@ -0,0 +1,151 @@ +/* ── GLOBAL ────────────────────────────────────────────────── */ +body { + background-color: #f0f4f8; + font-family: Arial, sans-serif; + color: #333333; +} + +/* ── NAVBAR ────────────────────────────────────────────────── */ +.navbar { + background-color: #1F4E79; + padding: 12px 24px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); +} + +.navbar-brand { + font-size: 1.2rem; + font-weight: bold; + color: #ffffff !important; + letter-spacing: 0.5px; +} + +.navbar-text { + color: #BDD7EE !important; + font-size: 0.85rem; +} + +/* ── PAGE TITLE ─────────────────────────────────────────────── */ +.page-title { + color: #1F4E79; + font-weight: bold; + font-size: 1.6rem; +} + +/* ── STAT CARDS ─────────────────────────────────────────────── */ +.stat-card { + background-color: #ffffff; + border-radius: 10px; + padding: 20px; + text-align: center; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08); + border-left: 5px solid #2E75B6; +} + +.stat-card.alert-stat { + border-left: 5px solid #dc3545; +} + +.stat-number { + font-size: 2rem; + font-weight: bold; + color: #1F4E79; +} + +.alert-stat .stat-number { + color: #dc3545; +} + +.stat-label { + font-size: 0.85rem; + color: #666666; + margin-top: 4px; +} + +/* ── DASHBOARD CARDS ────────────────────────────────────────── */ +.dashboard-card { + background-color: #ffffff; + border-radius: 10px; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08); + overflow: hidden; + height: 100%; +} + +.card-header-custom { + background-color: #1F4E79; + color: #ffffff; + font-weight: bold; + font-size: 1rem; + padding: 12px 20px; + letter-spacing: 0.3px; +} + +.alert-header { + background-color: #c0392b; +} + +.card-body { + padding: 16px; +} + +/* ── TABLE ──────────────────────────────────────────────────── */ +.table thead th { + background-color: #D6E4F0; + color: #1F4E79; + font-weight: bold; + font-size: 0.85rem; + border: none; +} + +.table tbody tr:hover { + background-color: #f0f7ff; +} + +.table td { + font-size: 0.9rem; + vertical-align: middle; +} + +/* ── ALERT ITEMS ────────────────────────────────────────────── */ +.alert-item { + background-color: #fff5f5; + border-left: 4px solid #dc3545; + border-radius: 6px; + padding: 10px 14px; + margin-bottom: 10px; +} + +.alert-room { + font-weight: bold; + color: #c0392b; + font-size: 0.85rem; +} + +.alert-message { + font-size: 0.85rem; + color: #333333; + margin-top: 2px; +} + +.alert-value { + font-size: 0.8rem; + color: #666666; + margin-top: 4px; +} + +/* ── BADGES ─────────────────────────────────────────────────── */ +.badge { + font-size: 0.78rem; + padding: 5px 10px; + border-radius: 20px; +} + +/* ── RESPONSIVE ─────────────────────────────────────────────── */ +@media (max-width: 768px) { + .stat-card { + margin-bottom: 16px; + } + + .navbar-text { + display: none; + } +} diff --git a/src/dashboard/templates/index.html b/src/dashboard/templates/index.html index e69de29..9e03cd8 100644 --- a/src/dashboard/templates/index.html +++ b/src/dashboard/templates/index.html @@ -0,0 +1,123 @@ +{% extends "base.html" %} + +{% block content %} + + +
+
+

Dashboard Overview

+

Live environmental monitoring across campus rooms

+
+
+ ● System Online +
+
+ + +
+
+
+
3
+
Rooms Monitored
+
+
+
+
+
12
+
Active Sensors
+
+
+
+
+
{{ alerts|length }}
+
Active Alerts
+
+
+
+
+
Live
+
Data Status
+
+
+
+ + +
+ + +
+
+
+ Live Sensor Readings +
+
+ + + + + + + + + + + {% for reading in readings %} + + + + + + + {% endfor %} + +
RoomSensorValueStatus
{{ reading.room }}{{ reading.sensor }}{{ reading.value }} + {% if reading.status == "Alert" %} + ⚠ Alert + {% else %} + ✓ Normal + {% endif %} +
+
+
+
+ + +
+
+
+ Active Alerts +
+
+ {% if alerts %} + {% for alert in alerts %} +
+
{{ alert.room }}
+
{{ alert.message }}
+
Reading: {{ alert.value }}
+
+ {% endfor %} + {% else %} +

No active alerts

+ {% endif %} +
+
+
+ +
+ + +
+
+
+
+ Historical Data +
+
+

Historical Charts — Coming Sprint 3

+

Will display temperature, CO2, noise and occupancy trends over time

+
+
+
+
+ +{% endblock %} \ No newline at end of file