From 0d26cf72a468a92fe7314eb7adfd51e8fc908ef9 Mon Sep 17 00:00:00 2001 From: Anthony <59890724+narlock@users.noreply.github.com> Date: Mon, 3 Jun 2024 07:53:28 -0500 Subject: [PATCH] Add water widget and heatmap --- public/css/index.css | 7 +++- public/js/index.js | 7 ---- public/js/water.js | 46 +++++++++++++++++++++++++++ public/js/weight.js | 3 +- public/lib/waterWidget.js | 67 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 121 insertions(+), 9 deletions(-) diff --git a/public/css/index.css b/public/css/index.css index 178e364..12809bd 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -217,7 +217,7 @@ p { color: red; } -#profileForm, #weightEntryBox, #weightStatsBox, #weightBoxInterfaceDiv, #waterBox { +#profileForm, #weightEntryBox, #weightStatsBox, #weightBoxInterfaceDiv, #waterBox, #weightGraphBox { width: 100%; display: flex; flex-direction: column; @@ -226,6 +226,11 @@ p { font-size: medium; } +.entryWaterSpan { + padding-bottom: 20px; + margin: 20px; +} + #submitButton, #startHabit { background-color: #00a657; color: white; diff --git a/public/js/index.js b/public/js/index.js index 4a1c2e7..60fbb7b 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -71,13 +71,6 @@ async function populateWidgetData(boxElement, widgetName) { ProfileWidget.moveXpBarWithElement(xpBar, PROFILE.profile.xp, boxElement); }, 0); break; - case 'habit': - // Add header to box - const habitHeader = document.createElement('h2'); - habitHeader.textContent = 'Habit Tracker'; - boxElement.appendChild(habitHeader); - // Add widget to box and display - break; case 'weight': const WEIGHT_ENTRIES = await WeightLoader.getWeightEntriesById(1); var weightWidget = await WeightWidget.createWidgetInterface(WEIGHT_ENTRIES); diff --git a/public/js/water.js b/public/js/water.js index 9a1dd12..c33d55d 100644 --- a/public/js/water.js +++ b/public/js/water.js @@ -69,5 +69,51 @@ function displayWaterEntryToday(amount) { } async function createWaterHeatmap() { + console.log('Inside of createWaterHeatmap - water-heatmap is the div id'); + var cal = new CalHeatMap(); + var now = new Date(); + var startOfYear = new Date(now.getFullYear(), 0, 1); + var endOfYear = new Date(now.getFullYear() + 1, 0, 0); + // Prepare the given entries as a map for quick lookup + var entryMap = new Map(WATER_ENTRIES.map(entry => { + var date = new Date(entry.entryDate); + date.setDate(date.getDate() + 1); // Add one day to each entry since cal map is weird + return [date.setHours(0, 0, 0, 0), entry.entryAmount]; + })); + console.log(entryMap); + + // Generate data based on the provided entries list + var calData = {}; + for (var d = new Date(startOfYear); d <= endOfYear; d.setDate(d.getDate() + 1)) { + var timestamp = Math.floor(d.getTime() / 1000); // convert to seconds + var dayStart = new Date(d).setHours(0, 0, 0, 0); // Normalize to start of the day to match entries + var entryAmount = entryMap.has(dayStart) ? entryMap.get(dayStart) : 0; + calData[timestamp] = entryAmount; + } + + cal.init({ + itemSelector: `#water-heatmap`, + domain: "year", + subDomain: "day", + data: calData, + start: startOfYear, // Start from the beginning of the current year + cellSize: 10, + range: 1, // Set range to cover all months of the year + domainGutter: 10, + legend: [0, 10, 30, 50, 70, 90, 110, 130, 150 ], // Adjust this based on your data's max count + tooltip: true, + legendColors: { + empty: "#e3e3e3", + min: "#004461", + max: "#00b3ff" + }, + legendHorizontalPosition: "left", + subDomainTextFormat: "", // No text inside the cells + domainLabelFormat: "%Y", // %Y-%m + subDomainTitleFormat: { + empty: "No data on {date}", + filled: "{date} -- {count} water" + } + }); } \ No newline at end of file diff --git a/public/js/weight.js b/public/js/weight.js index 0860f44..32a2dcb 100644 --- a/public/js/weight.js +++ b/public/js/weight.js @@ -93,9 +93,10 @@ function displayWeightEntryToday(todaysWeightString) { } async function initializeWeightStatsBox() { + var interfaceDiv = document.getElementById('weightStatsBox'); if(ENTERED_TODAY) { - var interfaceDiv = document.getElementById('weightStatsBox'); + // Body mass index console.log(TODAY_WEIGHT_AMOUNT); diff --git a/public/lib/waterWidget.js b/public/lib/waterWidget.js index 0d57ba5..ed9a417 100644 --- a/public/lib/waterWidget.js +++ b/public/lib/waterWidget.js @@ -14,6 +14,11 @@ async function createWaterInterface() { if(TODAY_WATER_AMOUNT) { // Entry has been created for today console.log("Entry existed for today"); + var entries = await WaterLoader.getWaterEntries(1); + setTimeout(() => { + createMonthCalHeatmap(entries); + }, 0); + return displayWaterEntryToday(TODAY_WATER_AMOUNT); } else { // Entry has not been created @@ -21,8 +26,15 @@ async function createWaterInterface() { var response = await WaterLoader.createWaterEntry(1, TODAY_AS_STRING); console.log(response); TODAY_WATER_AMOUNT = response.entryAmount; + + var entries = await WaterLoader.getWaterEntries(1); + setTimeout(() => { + createMonthCalHeatmap(entries); + }, 0); return displayWaterEntryToday(TODAY_WATER_AMOUNT); } + + } function displayWaterEntryToday(amount) { @@ -36,6 +48,7 @@ function displayWaterEntryToday(amount) { // Add button interface to add var span = document.createElement('span'); + span.classList.add('entryWaterSpan'); var input = document.createElement('input') input.type = 'text'; @@ -52,4 +65,58 @@ function displayWaterEntryToday(amount) { return interfaceDiv; } +function createMonthCalHeatmap(WATER_ENTRIES) { + var parent = document.getElementById('waterBox'); + var heatmapDiv = document.createElement('div'); + heatmapDiv.id = 'water-heatmap-widget'; + parent.appendChild(heatmapDiv); + + var cal = new CalHeatMap(); + var now = new Date(); + var startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1); + var endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0); + + // Prepare the given entries as a map for quick lookup + var entryMap = new Map(WATER_ENTRIES.map(entry => { + var date = new Date(entry.entryDate); + date.setDate(date.getDate() + 1); // Add one day to each entry since cal map is weird + return [date.setHours(0, 0, 0, 0), entry.entryAmount]; + })); + console.log(entryMap); + + // Generate data based on the provided entries list + var calData = {}; + for (var d = new Date(startOfMonth); d <= endOfMonth; d.setDate(d.getDate() + 1)) { + var timestamp = Math.floor(d.getTime() / 1000); // convert to seconds + var dayStart = new Date(d).setHours(0, 0, 0, 0); // Normalize to start of the day to match entries + var entryAmount = entryMap.has(dayStart) ? entryMap.get(dayStart) : 0; + calData[timestamp] = entryAmount; + } + + cal.init({ + itemSelector: `#water-heatmap-widget`, + domain: "month", + subDomain: "day", + data: calData, + start: startOfMonth, // Start from the beginning of the current year + cellSize: 15, + range: 1, // Set range to cover all months of the year + domainGutter: 10, + legend: [0, 10, 30, 50, 70, 90, 110, 130, 150 ], // Adjust this based on your data's max count + tooltip: true, + legendColors: { + empty: "#e3e3e3", + min: "#004461", + max: "#00b3ff" + }, + legendHorizontalPosition: "right", + subDomainTextFormat: "", // No text inside the cells + domainLabelFormat: "%B", // %Y-%m + subDomainTitleFormat: { + empty: "No data on {date}", + filled: "{date} -- {count} water" + } + }); +} + export { createWaterInterface } \ No newline at end of file