From 44c6f0168f2fd5fdfb9d72f35a3eba6eeb4d269e Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Sun, 9 Nov 2025 21:23:09 +0100 Subject: [PATCH] added feedings page with graphs and list of entries with option to edit and manually add new --- src/baby_monitor/main.py | 6 + src/baby_monitor/static/feedings.html | 1058 ++++++++++++++++++++++ src/baby_monitor/static/index.html | 5 + src/baby_monitor/static/log-feeding.html | 95 +- 4 files changed, 1148 insertions(+), 16 deletions(-) create mode 100644 src/baby_monitor/static/feedings.html diff --git a/src/baby_monitor/main.py b/src/baby_monitor/main.py index aeeef30..0d45a8b 100644 --- a/src/baby_monitor/main.py +++ b/src/baby_monitor/main.py @@ -91,6 +91,12 @@ def serve_log_feeding() -> FileResponse: return FileResponse(static_path / "log-feeding.html") +@app.get("/feedings.html", include_in_schema=False) +def serve_feedings() -> FileResponse: + """Serve the feedings overview page.""" + return FileResponse(static_path / "feedings.html") + + @app.get("/api/") def read_root(token: Annotated[str, Depends(verify_token)]) -> dict: """API root endpoint (requires authentication).""" diff --git a/src/baby_monitor/static/feedings.html b/src/baby_monitor/static/feedings.html new file mode 100644 index 0000000..68dc416 --- /dev/null +++ b/src/baby_monitor/static/feedings.html @@ -0,0 +1,1058 @@ + + + + + + Feedings - Baby Monitor + + + +
+
+
+
+
+ + + + + +
+

🍼 Feedings

+

Overview of all feeding sessions

+ +
+

Loading...

+
+
+ + + + + diff --git a/src/baby_monitor/static/index.html b/src/baby_monitor/static/index.html index 28f6ddf..00d7fca 100644 --- a/src/baby_monitor/static/index.html +++ b/src/baby_monitor/static/index.html @@ -216,6 +216,7 @@ @@ -285,6 +286,10 @@ window.location.href = "/add-child.html"; }); + document.getElementById("menuFeedings").addEventListener("click", () => { + window.location.href = "/feedings.html"; + }); + document.getElementById("menuLogout").addEventListener("click", () => { closeMenu(); logout(); diff --git a/src/baby_monitor/static/log-feeding.html b/src/baby_monitor/static/log-feeding.html index ba0750b..97ee15a 100644 --- a/src/baby_monitor/static/log-feeding.html +++ b/src/baby_monitor/static/log-feeding.html @@ -212,14 +212,28 @@ const loadingDiv = document.getElementById("loadingChildren"); const childSelect = document.getElementById("childId"); - // Set default start time to now - const now = new Date(); - const localDateTime = new Date( - now.getTime() - now.getTimezoneOffset() * 60000, - ) - .toISOString() - .slice(0, 16); - document.getElementById("startTime").value = localDateTime; + // Check if we're editing an existing feeding + const urlParams = new URLSearchParams(window.location.search); + const feedingId = urlParams.get("id"); + const isEditMode = !!feedingId; + + // Set default start time to now (only for new feedings) + if (!isEditMode) { + const now = new Date(); + const localDateTime = new Date( + now.getTime() - now.getTimezoneOffset() * 60000, + ) + .toISOString() + .slice(0, 16); + document.getElementById("startTime").value = localDateTime; + } + + // Update title and button text if editing + if (isEditMode) { + document.querySelector("h1").textContent = "🍼 Edit Feeding"; + document.querySelector(".subtitle").textContent = "Update feeding session details"; + submitBtn.textContent = "Update Feeding"; + } // Load user's children async function loadChildren() { @@ -255,6 +269,11 @@ // Show form, hide loading loadingDiv.style.display = "none"; form.style.display = "block"; + + // If editing, load the feeding data + if (isEditMode) { + loadFeedingData(); + } } else { showMessage("Failed to load children", "error"); } @@ -263,6 +282,44 @@ } } + async function loadFeedingData() { + try { + const response = await fetch(`/api/feedings/${feedingId}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + + if (response.ok) { + const feeding = await response.json(); + + // Populate form with existing data + document.getElementById("childId").value = feeding.child_id; + + // Format datetime for datetime-local input + const startTime = new Date(feeding.start_time); + const startLocalDateTime = new Date( + startTime.getTime() - startTime.getTimezoneOffset() * 60000 + ).toISOString().slice(0, 16); + document.getElementById("startTime").value = startLocalDateTime; + + if (feeding.end_time) { + const endTime = new Date(feeding.end_time); + const endLocalDateTime = new Date( + endTime.getTime() - endTime.getTimezoneOffset() * 60000 + ).toISOString().slice(0, 16); + document.getElementById("endTime").value = endLocalDateTime; + } + + document.getElementById("feedingType").value = feeding.feeding_type; + } else { + showMessage("Failed to load feeding data", "error"); + } + } catch (error) { + showMessage("Network error loading feeding", "error"); + } + } + loadChildren(); form.addEventListener("submit", async (e) => { @@ -275,12 +332,15 @@ // Disable button during request submitBtn.disabled = true; - submitBtn.textContent = "Logging..."; + submitBtn.textContent = isEditMode ? "Updating..." : "Logging..."; messageDiv.classList.remove("show"); try { - const response = await fetch("/api/feedings", { - method: "POST", + const url = isEditMode ? `/api/feedings/${feedingId}` : "/api/feedings"; + const method = isEditMode ? "PUT" : "POST"; + + const response = await fetch(url, { + method: method, headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, @@ -296,14 +356,17 @@ const data = await response.json(); if (response.ok) { - showMessage("Feeding logged successfully!", "success"); - // Redirect to home page after 1 second + showMessage( + isEditMode ? "Feeding updated successfully!" : "Feeding logged successfully!", + "success" + ); + // Redirect to feedings page after 1 second setTimeout(() => { - window.location.href = "/"; + window.location.href = "/feedings.html"; }, 1000); } else { showMessage( - data.detail || "Failed to log feeding. Please try again.", + data.detail || `Failed to ${isEditMode ? 'update' : 'log'} feeding. Please try again.`, "error", ); } @@ -311,7 +374,7 @@ showMessage("Network error. Please try again.", "error"); } finally { submitBtn.disabled = false; - submitBtn.textContent = "Log Feeding"; + submitBtn.textContent = isEditMode ? "Update Feeding" : "Log Feeding"; } });