added feedings page with graphs and list of entries with option to edit and manually add new
This commit is contained in:
@@ -91,6 +91,12 @@ def serve_log_feeding() -> FileResponse:
|
|||||||
return FileResponse(static_path / "log-feeding.html")
|
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/")
|
@app.get("/api/")
|
||||||
def read_root(token: Annotated[str, Depends(verify_token)]) -> dict:
|
def read_root(token: Annotated[str, Depends(verify_token)]) -> dict:
|
||||||
"""API root endpoint (requires authentication)."""
|
"""API root endpoint (requires authentication)."""
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -216,6 +216,7 @@
|
|||||||
|
|
||||||
<div class="menu-overlay" id="menuOverlay">
|
<div class="menu-overlay" id="menuOverlay">
|
||||||
<div class="menu-item" id="menuAddChild">👶 Add Child</div>
|
<div class="menu-item" id="menuAddChild">👶 Add Child</div>
|
||||||
|
<div class="menu-item" id="menuFeedings">🍼 Feedings</div>
|
||||||
<div class="menu-item logout" id="menuLogout">🚪 Logout</div>
|
<div class="menu-item logout" id="menuLogout">🚪 Logout</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -285,6 +286,10 @@
|
|||||||
window.location.href = "/add-child.html";
|
window.location.href = "/add-child.html";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById("menuFeedings").addEventListener("click", () => {
|
||||||
|
window.location.href = "/feedings.html";
|
||||||
|
});
|
||||||
|
|
||||||
document.getElementById("menuLogout").addEventListener("click", () => {
|
document.getElementById("menuLogout").addEventListener("click", () => {
|
||||||
closeMenu();
|
closeMenu();
|
||||||
logout();
|
logout();
|
||||||
|
|||||||
@@ -212,7 +212,13 @@
|
|||||||
const loadingDiv = document.getElementById("loadingChildren");
|
const loadingDiv = document.getElementById("loadingChildren");
|
||||||
const childSelect = document.getElementById("childId");
|
const childSelect = document.getElementById("childId");
|
||||||
|
|
||||||
// Set default start time to now
|
// 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 now = new Date();
|
||||||
const localDateTime = new Date(
|
const localDateTime = new Date(
|
||||||
now.getTime() - now.getTimezoneOffset() * 60000,
|
now.getTime() - now.getTimezoneOffset() * 60000,
|
||||||
@@ -220,6 +226,14 @@
|
|||||||
.toISOString()
|
.toISOString()
|
||||||
.slice(0, 16);
|
.slice(0, 16);
|
||||||
document.getElementById("startTime").value = localDateTime;
|
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
|
// Load user's children
|
||||||
async function loadChildren() {
|
async function loadChildren() {
|
||||||
@@ -255,6 +269,11 @@
|
|||||||
// Show form, hide loading
|
// Show form, hide loading
|
||||||
loadingDiv.style.display = "none";
|
loadingDiv.style.display = "none";
|
||||||
form.style.display = "block";
|
form.style.display = "block";
|
||||||
|
|
||||||
|
// If editing, load the feeding data
|
||||||
|
if (isEditMode) {
|
||||||
|
loadFeedingData();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
showMessage("Failed to load children", "error");
|
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();
|
loadChildren();
|
||||||
|
|
||||||
form.addEventListener("submit", async (e) => {
|
form.addEventListener("submit", async (e) => {
|
||||||
@@ -275,12 +332,15 @@
|
|||||||
|
|
||||||
// Disable button during request
|
// Disable button during request
|
||||||
submitBtn.disabled = true;
|
submitBtn.disabled = true;
|
||||||
submitBtn.textContent = "Logging...";
|
submitBtn.textContent = isEditMode ? "Updating..." : "Logging...";
|
||||||
messageDiv.classList.remove("show");
|
messageDiv.classList.remove("show");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch("/api/feedings", {
|
const url = isEditMode ? `/api/feedings/${feedingId}` : "/api/feedings";
|
||||||
method: "POST",
|
const method = isEditMode ? "PUT" : "POST";
|
||||||
|
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: method,
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
@@ -296,14 +356,17 @@
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
showMessage("Feeding logged successfully!", "success");
|
showMessage(
|
||||||
// Redirect to home page after 1 second
|
isEditMode ? "Feeding updated successfully!" : "Feeding logged successfully!",
|
||||||
|
"success"
|
||||||
|
);
|
||||||
|
// Redirect to feedings page after 1 second
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.href = "/";
|
window.location.href = "/feedings.html";
|
||||||
}, 1000);
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
showMessage(
|
showMessage(
|
||||||
data.detail || "Failed to log feeding. Please try again.",
|
data.detail || `Failed to ${isEditMode ? 'update' : 'log'} feeding. Please try again.`,
|
||||||
"error",
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -311,7 +374,7 @@
|
|||||||
showMessage("Network error. Please try again.", "error");
|
showMessage("Network error. Please try again.", "error");
|
||||||
} finally {
|
} finally {
|
||||||
submitBtn.disabled = false;
|
submitBtn.disabled = false;
|
||||||
submitBtn.textContent = "Log Feeding";
|
submitBtn.textContent = isEditMode ? "Update Feeding" : "Log Feeding";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user