changed dropdown to read-only textfield when only 1 associated child and fixed redirects after manual entries
Build and Push Docker Image / build-and-push (pull_request) Successful in 58s
Python Code Quality / python-code-quality (pull_request) Successful in 10s
Python Test / python-test (pull_request) Successful in 18s

This commit is contained in:
Brian Bjarke Jensen
2025-11-12 16:39:16 +01:00
parent 9d1ca55905
commit 28a5df4f12
7 changed files with 294 additions and 95 deletions
+22 -8
View File
@@ -280,7 +280,7 @@
let allChildren = [];
let currentDaysRange =
parseInt(localStorage.getItem("lastDiaperTimeRange")) || 7;
let selectedChildId = null; // null means "All Children"
let selectedChildId = null; // null means show first/only child
// Restore last selected child from localStorage
const lastChildId = localStorage.getItem("lastDiaperChildFilter");
@@ -321,6 +321,11 @@
if (response.ok) {
allChildren = await response.json();
// Auto-select first child if no selection exists
if (selectedChildId === null && allChildren.length > 0) {
selectedChildId = allChildren[0].id;
}
}
} catch (error) {
console.error("Error loading children:", error);
@@ -334,8 +339,7 @@
}
function onChildChange(event) {
selectedChildId =
event.target.value === "all" ? null : parseInt(event.target.value);
selectedChildId = parseInt(event.target.value);
localStorage.setItem("lastDiaperChildFilter", event.target.value);
displayDiaperChanges(allDiaperChanges);
}
@@ -367,11 +371,21 @@
content.innerHTML = `
<div class="controls">
<label for="childFilter">Child:</label>
<select id="childFilter" onchange="onChildChange(event)">
<option value="all" ${selectedChildId === null ? "selected" : ""}>All Children</option>
${childOptions}
</select>
${allChildren.length === 1 ? `
<label for="childDisplay">Child:</label>
<input
type="text"
id="childDisplay"
value="${allChildren[0].name}"
readonly
style="background-color: #f5f5f5; cursor: default; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;"
/>
` : `
<label for="childFilter">Child:</label>
<select id="childFilter" onchange="onChildChange(event)">
${childOptions}
</select>
`}
<label for="daysRange">Time Range:</label>
<select id="daysRange" onchange="onDaysRangeChange(event)">
+22 -8
View File
@@ -317,7 +317,7 @@
let allChildren = [];
let currentDaysRange =
parseInt(localStorage.getItem("lastFeedingTimeRange")) || 7;
let selectedChildId = null; // null means "All Children"
let selectedChildId = null; // null means show first/only child
let barChartInstance = null;
// Restore last selected child from localStorage
@@ -359,6 +359,11 @@
if (response.ok) {
allChildren = await response.json();
// Auto-select first child if no selection exists
if (selectedChildId === null && allChildren.length > 0) {
selectedChildId = allChildren[0].id;
}
}
} catch (error) {
console.error("Error loading children:", error);
@@ -372,8 +377,7 @@
}
function onChildChange(event) {
selectedChildId =
event.target.value === "all" ? null : parseInt(event.target.value);
selectedChildId = parseInt(event.target.value);
localStorage.setItem("lastFeedingChildFilter", event.target.value);
displayFeedings(allFeedings);
}
@@ -405,11 +409,21 @@
content.innerHTML = `
<div class="controls">
<label for="childFilter">Child:</label>
<select id="childFilter" onchange="onChildChange(event)">
<option value="all" ${selectedChildId === null ? "selected" : ""}>All Children</option>
${childOptions}
</select>
${allChildren.length === 1 ? `
<label for="childDisplay">Child:</label>
<input
type="text"
id="childDisplay"
value="${allChildren[0].name}"
readonly
style="background-color: #f5f5f5; cursor: default; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;"
/>
` : `
<label for="childFilter">Child:</label>
<select id="childFilter" onchange="onChildChange(event)">
${childOptions}
</select>
`}
<label for="daysRange">Time Range:</label>
<select id="daysRange" onchange="onDaysRangeChange(event)">
+61 -21
View File
@@ -510,18 +510,40 @@
const childSelect = document.getElementById("modalChildId");
const typeSelect = document.getElementById("modalFeedingType");
// Clear and populate child select
childSelect.innerHTML = '<option value="">Select a child</option>';
userChildren.forEach((child) => {
const option = document.createElement("option");
option.value = child.id;
option.textContent = child.name;
childSelect.appendChild(option);
});
// Clear and populate child select or show single child
if (userChildren.length === 1) {
// Single child: replace dropdown with text display
const child = userChildren[0];
const formGroup = childSelect.parentElement;
formGroup.innerHTML = `
<label for="modalChildName">Child</label>
<input
type="text"
id="modalChildName"
value="${child.name}"
readonly
style="background-color: #f5f5f5; cursor: default;"
/>
<input type="hidden" id="modalChildId" value="${child.id}" />
`;
} else {
// Multiple children: show dropdown
childSelect.innerHTML = '<option value="">Select a child</option>';
userChildren.forEach((child) => {
const option = document.createElement("option");
option.value = child.id;
option.textContent = child.name;
childSelect.appendChild(option);
});
// Set defaults based on last feeding
// Set defaults based on last feeding
if (lastFeeding) {
childSelect.value = lastFeeding.child_id;
}
}
// Set default feeding type based on last feeding
if (lastFeeding) {
childSelect.value = lastFeeding.child_id;
typeSelect.value = lastFeeding.feeding_type;
}
@@ -633,18 +655,36 @@
const modal = document.getElementById("startSleepModal");
const childSelect = document.getElementById("modalSleepChildId");
// Clear and populate child select
childSelect.innerHTML = '<option value="">Select a child</option>';
userChildren.forEach((child) => {
const option = document.createElement("option");
option.value = child.id;
option.textContent = child.name;
childSelect.appendChild(option);
});
// Clear and populate child select or show single child
if (userChildren.length === 1) {
// Single child: replace dropdown with text display
const child = userChildren[0];
const formGroup = childSelect.parentElement;
formGroup.innerHTML = `
<label for="modalSleepChildName">Child</label>
<input
type="text"
id="modalSleepChildName"
value="${child.name}"
readonly
style="background-color: #f5f5f5; cursor: default;"
/>
<input type="hidden" id="modalSleepChildId" value="${child.id}" />
`;
} else {
// Multiple children: show dropdown
childSelect.innerHTML = '<option value="">Select a child</option>';
userChildren.forEach((child) => {
const option = document.createElement("option");
option.value = child.id;
option.textContent = child.name;
childSelect.appendChild(option);
});
// Set default based on last sleep
if (lastSleep) {
childSelect.value = lastSleep.child_id;
// Set default based on last sleep
if (lastSleep) {
childSelect.value = lastSleep.child_id;
}
}
modal.classList.add("show");
+47 -15
View File
@@ -235,7 +235,7 @@
<button
type="button"
class="button secondary"
onclick="window.location.href='/diapers.html'"
onclick="window.location.href=getReturnUrl()"
>
Cancel
</button>
@@ -249,6 +249,16 @@
window.location.href = "/login.html";
}
// Determine return URL based on referrer
function getReturnUrl() {
const referrer = document.referrer;
if (referrer.includes('/diapers.html')) {
return '/diapers.html';
}
// Default to home page
return '/';
}
// Check if we're in edit mode
const urlParams = new URLSearchParams(window.location.search);
const diaperChangeId = urlParams.get("id");
@@ -277,12 +287,32 @@
children = await response.json();
const select = document.getElementById("childSelect");
children.forEach((child) => {
const option = document.createElement("option");
option.value = child.id;
option.textContent = child.name;
select.appendChild(option);
});
// Populate select dropdown or show single child
if (children.length === 1) {
// Single child: replace dropdown with text display
const child = children[0];
const formGroup = select.parentElement;
formGroup.innerHTML = `
<label for="childName">Child *</label>
<input
type="text"
id="childName"
value="${child.name}"
readonly
style="background-color: #f5f5f5; cursor: default;"
/>
<input type="hidden" id="childSelect" name="childSelect" value="${child.id}" />
`;
} else {
// Multiple children: show dropdown (clear the placeholder first)
select.innerHTML = '';
children.forEach((child) => {
const option = document.createElement("option");
option.value = child.id;
option.textContent = child.name;
select.appendChild(option);
});
}
// If editing, load the diaper change data
if (isEditMode) {
@@ -295,14 +325,16 @@
.toISOString()
.slice(0, 16);
// Load last used child from localStorage
const lastDiaperChange = JSON.parse(
localStorage.getItem("lastDiaperChange") || "{}",
);
// Load last used child from localStorage (only for multiple children)
if (children.length > 1) {
const lastDiaperChange = JSON.parse(
localStorage.getItem("lastDiaperChange") || "{}",
);
if (lastDiaperChange.child_id) {
document.getElementById("childSelect").value =
lastDiaperChange.child_id;
if (lastDiaperChange.child_id) {
document.getElementById("childSelect").value =
lastDiaperChange.child_id;
}
}
}
} else {
@@ -431,7 +463,7 @@
"success",
);
setTimeout(() => {
window.location.href = "/diapers.html";
window.location.href = getReturnUrl();
}, 1000);
} else {
const errorData = await response.json();
+39 -10
View File
@@ -206,6 +206,16 @@
window.location.href = "/login.html";
}
// Determine return URL based on referrer
function getReturnUrl() {
const referrer = document.referrer;
if (referrer.includes('/feedings.html')) {
return '/feedings.html';
}
// Default to home page
return '/';
}
const form = document.getElementById("logFeedingForm");
const messageDiv = document.getElementById("message");
const submitBtn = document.getElementById("submitBtn");
@@ -259,13 +269,32 @@
return;
}
// Populate select dropdown
children.forEach((child) => {
const option = document.createElement("option");
option.value = child.id;
option.textContent = child.name;
childSelect.appendChild(option);
});
// Populate select dropdown or show single child
if (children.length === 1) {
// Single child: replace dropdown with text display
const child = children[0];
const formGroup = childSelect.parentElement;
formGroup.innerHTML = `
<label for="childName">Child</label>
<input
type="text"
id="childName"
value="${child.name}"
readonly
style="background-color: #f5f5f5; cursor: default;"
/>
<input type="hidden" id="childId" name="childId" value="${child.id}" />
`;
} else {
// Multiple children: show dropdown (clear placeholder first)
childSelect.innerHTML = '';
children.forEach((child) => {
const option = document.createElement("option");
option.value = child.id;
option.textContent = child.name;
childSelect.appendChild(option);
});
}
// Show form, hide loading
loadingDiv.style.display = "none";
@@ -369,9 +398,9 @@
: "Feeding logged successfully!",
"success",
);
// Redirect to feedings page after 1 second
// Redirect to appropriate page after 1 second
setTimeout(() => {
window.location.href = "/feedings.html";
window.location.href = getReturnUrl();
}, 1000);
} else {
showMessage(
@@ -394,7 +423,7 @@
}
function goBack() {
window.location.href = "/feedings.html";
window.location.href = getReturnUrl();
}
</script>
</body>
+39 -10
View File
@@ -196,6 +196,16 @@
window.location.href = "/login.html";
}
// Determine return URL based on referrer
function getReturnUrl() {
const referrer = document.referrer;
if (referrer.includes('/sleep.html')) {
return '/sleep.html';
}
// Default to home page
return '/';
}
const form = document.getElementById("logSleepForm");
const messageDiv = document.getElementById("message");
const submitBtn = document.getElementById("submitBtn");
@@ -249,13 +259,32 @@
return;
}
// Populate select dropdown
children.forEach((child) => {
const option = document.createElement("option");
option.value = child.id;
option.textContent = child.name;
childSelect.appendChild(option);
});
// Populate select dropdown or show single child
if (children.length === 1) {
// Single child: replace dropdown with text display
const child = children[0];
const formGroup = childSelect.parentElement;
formGroup.innerHTML = `
<label for="childName">Child</label>
<input
type="text"
id="childName"
value="${child.name}"
readonly
style="background-color: #f5f5f5; cursor: default;"
/>
<input type="hidden" id="childId" name="childId" value="${child.id}" />
`;
} else {
// Multiple children: show dropdown (clear placeholder first)
childSelect.innerHTML = '';
children.forEach((child) => {
const option = document.createElement("option");
option.value = child.id;
option.textContent = child.name;
childSelect.appendChild(option);
});
}
// Show form, hide loading
loadingDiv.style.display = "none";
@@ -353,9 +382,9 @@
: "Sleep logged successfully!",
"success",
);
// Redirect to sleep page after 1 second
// Redirect to appropriate page after 1 second
setTimeout(() => {
window.location.href = "/sleep.html";
window.location.href = getReturnUrl();
}, 1000);
} else {
showMessage(
@@ -378,7 +407,7 @@
}
function goBack() {
window.location.href = "/sleep.html";
window.location.href = getReturnUrl();
}
</script>
</body>
+64 -23
View File
@@ -328,19 +328,22 @@
let allChildren = [];
let selectedChildId = "";
// Filter change handlers
document
.getElementById("childFilter")
.addEventListener("change", function () {
selectedChildId = this.value;
// Save selection to localStorage
if (selectedChildId) {
localStorage.setItem("lastSleepChildFilter", selectedChildId);
} else {
localStorage.removeItem("lastSleepChildFilter");
}
renderCharts();
});
// Filter change handlers (will be attached after children are loaded)
function attachChildFilterListener() {
const childFilter = document.getElementById("childFilter");
if (childFilter) {
childFilter.addEventListener("change", function () {
selectedChildId = this.value;
// Save selection to localStorage
if (selectedChildId) {
localStorage.setItem("lastSleepChildFilter", selectedChildId);
} else {
localStorage.removeItem("lastSleepChildFilter");
}
renderCharts();
});
}
}
document
.getElementById("timeRangeFilter")
@@ -365,19 +368,52 @@
allChildren = await childrenResponse.json();
// Populate child filter
const childFilter = document.getElementById("childFilter");
childFilter.innerHTML = '<option value="">All Children</option>';
allChildren.forEach((child) => {
const option = document.createElement("option");
option.value = child.id;
option.textContent = child.name;
childFilter.appendChild(option);
});
// Auto-select first child if available
if (allChildren.length > 0 && !selectedChildId) {
selectedChildId = allChildren[0].id;
}
// Populate child filter or show single child
const childFilterContainer = document.querySelector('.controls');
if (allChildren.length === 1) {
// Single child: show as read-only text
const child = allChildren[0];
childFilterContainer.innerHTML = `
<label for="childDisplay">Child:</label>
<input
type="text"
id="childDisplay"
value="${child.name}"
readonly
style="background-color: #f5f5f5; cursor: default; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;"
/>
<label for="timeRangeFilter">Time Range:</label>
<select id="timeRangeFilter">
<option value="1">Last 24 hours</option>
<option value="3">Last 3 days</option>
<option value="7" selected>Last 7 days</option>
<option value="14">Last 14 days</option>
<option value="30">Last 30 days</option>
<option value="90">Last 90 days</option>
</select>
`;
} else {
// Multiple children: show dropdown
const childFilter = document.getElementById("childFilter");
childFilter.innerHTML = '';
allChildren.forEach((child) => {
const option = document.createElement("option");
option.value = child.id;
option.textContent = child.name;
childFilter.appendChild(option);
});
}
// Restore last selected child from localStorage
const lastChildId = localStorage.getItem("lastSleepChildFilter");
if (lastChildId) {
if (lastChildId && allChildren.length > 1) {
const childFilter = document.getElementById("childFilter");
childFilter.value = lastChildId;
selectedChildId = lastChildId;
}
@@ -402,6 +438,11 @@
allSleeps = await sleepResponse.json();
// Attach event listener for child filter if multiple children
if (allChildren.length > 1) {
attachChildFilterListener();
}
renderCharts();
} catch (error) {
console.error("Error loading data:", error);