From 5626408e2d9753629114499a81b33d27f32f6a2d Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Wed, 3 Dec 2025 20:18:06 +0100 Subject: [PATCH 1/3] vertically stacked recent activity boxes --- src/baby_monitor/static/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/baby_monitor/static/index.html b/src/baby_monitor/static/index.html index c3e3370..c1f974b 100644 --- a/src/baby_monitor/static/index.html +++ b/src/baby_monitor/static/index.html @@ -180,8 +180,8 @@ font-size: 1.1rem; } .activity-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + display: flex; + flex-direction: column; gap: 1rem; } .activity-card { From 93eb1dc45840b5016f01e3e47b3515db048b5a53 Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Wed, 3 Dec 2025 21:29:04 +0100 Subject: [PATCH 2/3] added feeding session calculation and displayed values --- src/baby_monitor/static/index.html | 76 ++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/src/baby_monitor/static/index.html b/src/baby_monitor/static/index.html index c1f974b..5141436 100644 --- a/src/baby_monitor/static/index.html +++ b/src/baby_monitor/static/index.html @@ -384,8 +384,8 @@ activeFeeding = await activeResponse.json(); } - // Fetch all feedings to get the last one - const feedingsResponse = await fetch("/api/feedings", { + // Fetch the 10 most recent feedings to calculate the most recent session + const feedingsResponse = await fetch("/api/feedings?limit=10", { headers: { Authorization: `Bearer ${token}`, }, @@ -394,8 +394,66 @@ if (feedingsResponse.ok) { const feedings = await feedingsResponse.json(); if (feedings.length > 0) { - // Feedings are ordered by start_time desc, so first is most recent - lastFeeding = feedings[0]; + // Calculate the most recent feeding session + let sessionStart = feedings[0].start_time; + let sessionEnd = feedings[0].end_time || feedings[0].start_time; + let sessionChildId = feedings[0].child_id; + let sessionEntries = [feedings[0]]; + + for (let i = 1; i < feedings.length; i++) { + const entry = feedings[i]; + // Only group entries for the same child (ignore feeding type) + if (entry.child_id !== sessionChildId) { + break; + } + // If the gap between this entry's end_time and current sessionStart is more than 30 min, stop + const prevEnd = entry.end_time || entry.start_time; + const sessionStartDate = new Date(sessionStart); + const prevEndDate = new Date(prevEnd); + const diffMins = Math.abs((sessionStartDate - prevEndDate) / 60000); + if (diffMins > 30) { + break; + } + // Extend session to include this entry + sessionStart = entry.start_time; + sessionEntries.push(entry); + } + + // Calculate accumulated feeding time for all events in the session + let accumulatedMinutes = 0; + sessionEntries.forEach(entry => { + if (entry.end_time && entry.start_time) { + const start = new Date(entry.start_time); + const end = new Date(entry.end_time); + const diffMs = end - start; + if (diffMs > 0) { + accumulatedMinutes += Math.floor(diffMs / 60000); + } + } + }); + + // Build a string showing all feeding types used during the session + const feedingTypesSet = new Set(); + sessionEntries.forEach(entry => { + if (entry.feeding_type) { + feedingTypesSet.add(entry.feeding_type); + } + }); + const feedingTypesString = Array.from(feedingTypesSet) + .map(formatFeedingType) + .join(', '); + + // Compose a session object + lastFeeding = { + child_id: sessionChildId, + feeding_type: feedings[0].feeding_type, + start_time: sessionStart, + end_time: sessionEnd, + entries: sessionEntries, + child_name: feedings[0].child_name, + accumulated_minutes: accumulatedMinutes, + feeding_types_string: feedingTypesString, + }; } } @@ -570,11 +628,13 @@ ? `
🍼
-
Last Feeding
+
Last Feeding Session
${formatTime(lastFeeding.start_time)}
- ${formatFeedingType(lastFeeding.feeding_type)} - ${lastFeeding.end_time ? ` • ${calculateDuration(lastFeeding.start_time, lastFeeding.end_time)}` : " (ongoing)"} + ${lastFeeding.feeding_types_string ? `${lastFeeding.feeding_types_string}` : ""} + ${lastFeeding.feeding_types_string && lastFeeding.accumulated_minutes ? " • " : ""} + ${lastFeeding.accumulated_minutes} minutes total + ${lastFeeding.end_time ? "" : " (ongoing)"}
` @@ -593,7 +653,7 @@
Last Sleep
${formatTime(lastSleep.start_time)}
- ${lastSleep.end_time ? calculateDuration(lastSleep.start_time, lastSleep.end_time) : "ongoing"} + Duration: ${lastSleep.end_time ? calculateDuration(lastSleep.start_time, lastSleep.end_time) : "ongoing"}
` From 63fc4b618cf82d290b90d1e57ff2d870d9feae58 Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Wed, 3 Dec 2025 21:29:36 +0100 Subject: [PATCH 3/3] CQ fixes --- src/baby_monitor/static/index.html | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/baby_monitor/static/index.html b/src/baby_monitor/static/index.html index 5141436..afa8410 100644 --- a/src/baby_monitor/static/index.html +++ b/src/baby_monitor/static/index.html @@ -410,7 +410,9 @@ const prevEnd = entry.end_time || entry.start_time; const sessionStartDate = new Date(sessionStart); const prevEndDate = new Date(prevEnd); - const diffMins = Math.abs((sessionStartDate - prevEndDate) / 60000); + const diffMins = Math.abs( + (sessionStartDate - prevEndDate) / 60000, + ); if (diffMins > 30) { break; } @@ -421,7 +423,7 @@ // Calculate accumulated feeding time for all events in the session let accumulatedMinutes = 0; - sessionEntries.forEach(entry => { + sessionEntries.forEach((entry) => { if (entry.end_time && entry.start_time) { const start = new Date(entry.start_time); const end = new Date(entry.end_time); @@ -434,14 +436,14 @@ // Build a string showing all feeding types used during the session const feedingTypesSet = new Set(); - sessionEntries.forEach(entry => { + sessionEntries.forEach((entry) => { if (entry.feeding_type) { feedingTypesSet.add(entry.feeding_type); } }); const feedingTypesString = Array.from(feedingTypesSet) .map(formatFeedingType) - .join(', '); + .join(", "); // Compose a session object lastFeeding = {