formatting fixes
This commit is contained in:
@@ -35,9 +35,7 @@ def create_sleep(
|
||||
raise HTTPException(status_code=404, detail="Child not found")
|
||||
|
||||
if child["user_id"] != user_id:
|
||||
raise HTTPException(
|
||||
status_code=403, detail="Access denied to this child"
|
||||
)
|
||||
raise HTTPException(status_code=403, detail="Access denied to this child")
|
||||
|
||||
sleep = sleep_repo.create(
|
||||
child_id=request.child_id,
|
||||
@@ -125,9 +123,7 @@ def update_sleep(
|
||||
)
|
||||
|
||||
if not updated:
|
||||
raise HTTPException(
|
||||
status_code=500, detail="Failed to update sleep log"
|
||||
)
|
||||
raise HTTPException(status_code=500, detail="Failed to update sleep log")
|
||||
|
||||
return SleepResponse(**updated)
|
||||
|
||||
|
||||
@@ -433,7 +433,8 @@
|
||||
}
|
||||
|
||||
function onChildChange(event) {
|
||||
selectedChildId = event.target.value === "all" ? null : parseInt(event.target.value);
|
||||
selectedChildId =
|
||||
event.target.value === "all" ? null : parseInt(event.target.value);
|
||||
displayDiaperChanges(allDiaperChanges);
|
||||
}
|
||||
|
||||
@@ -455,31 +456,34 @@
|
||||
const peePieData = preparePeePieChartData(diaperChanges);
|
||||
|
||||
// Build child dropdown options
|
||||
const childOptions = allChildren.map(child =>
|
||||
`<option value="${child.id}" ${selectedChildId === child.id ? 'selected' : ''}>${child.name}</option>`
|
||||
).join('');
|
||||
const childOptions = allChildren
|
||||
.map(
|
||||
(child) =>
|
||||
`<option value="${child.id}" ${selectedChildId === child.id ? "selected" : ""}>${child.name}</option>`,
|
||||
)
|
||||
.join("");
|
||||
|
||||
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>
|
||||
<option value="all" ${selectedChildId === null ? "selected" : ""}>All Children</option>
|
||||
${childOptions}
|
||||
</select>
|
||||
|
||||
<label for="daysRange">Time Range:</label>
|
||||
<select id="daysRange" onchange="onDaysRangeChange(event)">
|
||||
<option value="1" ${currentDaysRange === 1 ? 'selected' : ''}>Last 24 Hours</option>
|
||||
<option value="3" ${currentDaysRange === 3 ? 'selected' : ''}>Last 3 Days</option>
|
||||
<option value="7" ${currentDaysRange === 7 ? 'selected' : ''}>Last 7 Days</option>
|
||||
<option value="14" ${currentDaysRange === 14 ? 'selected' : ''}>Last 14 Days</option>
|
||||
<option value="30" ${currentDaysRange === 30 ? 'selected' : ''}>Last 30 Days</option>
|
||||
<option value="90" ${currentDaysRange === 90 ? 'selected' : ''}>Last 90 Days</option>
|
||||
<option value="1" ${currentDaysRange === 1 ? "selected" : ""}>Last 24 Hours</option>
|
||||
<option value="3" ${currentDaysRange === 3 ? "selected" : ""}>Last 3 Days</option>
|
||||
<option value="7" ${currentDaysRange === 7 ? "selected" : ""}>Last 7 Days</option>
|
||||
<option value="14" ${currentDaysRange === 14 ? "selected" : ""}>Last 14 Days</option>
|
||||
<option value="30" ${currentDaysRange === 30 ? "selected" : ""}>Last 30 Days</option>
|
||||
<option value="90" ${currentDaysRange === 90 ? "selected" : ""}>Last 90 Days</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<h2>Diaper Changes Per Day (Last ${currentDaysRange} Day${currentDaysRange !== 1 ? 's' : ''})</h2>
|
||||
<h2>Diaper Changes Per Day (Last ${currentDaysRange} Day${currentDaysRange !== 1 ? "s" : ""})</h2>
|
||||
<div class="chart-wrapper">
|
||||
<canvas id="diaperChart"></canvas>
|
||||
</div>
|
||||
@@ -526,7 +530,9 @@
|
||||
|
||||
// Filter by selected child if applicable
|
||||
if (selectedChildId !== null) {
|
||||
filteredChanges = filteredChanges.filter((dc) => dc.child_id === selectedChildId);
|
||||
filteredChanges = filteredChanges.filter(
|
||||
(dc) => dc.child_id === selectedChildId,
|
||||
);
|
||||
}
|
||||
|
||||
// Sort by most recent first
|
||||
@@ -534,7 +540,8 @@
|
||||
return new Date(b.change_time) - new Date(a.change_time);
|
||||
});
|
||||
|
||||
const listHtml = filteredChanges.map((dc) => {
|
||||
const listHtml = filteredChanges
|
||||
.map((dc) => {
|
||||
const changeTime = new Date(dc.change_time);
|
||||
|
||||
const dateStr = changeTime.toLocaleDateString("en-US", {
|
||||
@@ -551,33 +558,44 @@
|
||||
// Build badges for poop and pee
|
||||
let badges = [];
|
||||
if (dc.poop_amount || dc.poop_color) {
|
||||
const poopInfo = [dc.poop_amount, dc.poop_color].filter(Boolean).join(", ");
|
||||
badges.push(`<span class="diaper-badge poop">💩 ${poopInfo}</span>`);
|
||||
const poopInfo = [dc.poop_amount, dc.poop_color]
|
||||
.filter(Boolean)
|
||||
.join(", ");
|
||||
badges.push(
|
||||
`<span class="diaper-badge poop">💩 ${poopInfo}</span>`,
|
||||
);
|
||||
}
|
||||
if (dc.pee_amount || dc.pee_color) {
|
||||
const peeInfo = [dc.pee_amount, dc.pee_color].filter(Boolean).join(", ");
|
||||
badges.push(`<span class="diaper-badge pee">💧 ${peeInfo}</span>`);
|
||||
const peeInfo = [dc.pee_amount, dc.pee_color]
|
||||
.filter(Boolean)
|
||||
.join(", ");
|
||||
badges.push(
|
||||
`<span class="diaper-badge pee">💧 ${peeInfo}</span>`,
|
||||
);
|
||||
}
|
||||
if (badges.length === 0) {
|
||||
badges.push('<span class="diaper-badge" style="background: #f0f0f0; color: #666;">Clean diaper</span>');
|
||||
badges.push(
|
||||
'<span class="diaper-badge" style="background: #f0f0f0; color: #666;">Clean diaper</span>',
|
||||
);
|
||||
}
|
||||
|
||||
// Get child name
|
||||
const child = allChildren.find(c => c.id === dc.child_id);
|
||||
const child = allChildren.find((c) => c.id === dc.child_id);
|
||||
const childName = child ? child.name : "Unknown";
|
||||
|
||||
return `
|
||||
<div class="diaper-item">
|
||||
<div class="diaper-info-left">
|
||||
<div class="diaper-time">${dateStr} at ${timeStr}${selectedChildId === null ? ` - ${childName}` : ''}</div>
|
||||
<div class="diaper-time">${dateStr} at ${timeStr}${selectedChildId === null ? ` - ${childName}` : ""}</div>
|
||||
<div class="diaper-details">
|
||||
${badges.join('')}
|
||||
${badges.join("")}
|
||||
</div>
|
||||
</div>
|
||||
<button class="edit-button" onclick="editDiaperChange(${dc.id})">Edit</button>
|
||||
</div>
|
||||
`;
|
||||
}).join("");
|
||||
})
|
||||
.join("");
|
||||
|
||||
const listContainer = `
|
||||
<div class="diapers-list">
|
||||
@@ -592,7 +610,7 @@
|
||||
`;
|
||||
|
||||
const content = document.getElementById("content");
|
||||
content.insertAdjacentHTML('beforeend', listContainer);
|
||||
content.insertAdjacentHTML("beforeend", listContainer);
|
||||
}
|
||||
|
||||
function editDiaperChange(diaperChangeId) {
|
||||
@@ -617,7 +635,9 @@
|
||||
|
||||
// Filter by selected child if applicable
|
||||
if (selectedChildId !== null) {
|
||||
recentChanges = recentChanges.filter((dc) => dc.child_id === selectedChildId);
|
||||
recentChanges = recentChanges.filter(
|
||||
(dc) => dc.child_id === selectedChildId,
|
||||
);
|
||||
}
|
||||
|
||||
// Count poop amounts
|
||||
@@ -670,7 +690,9 @@
|
||||
|
||||
// Filter by selected child if applicable
|
||||
if (selectedChildId !== null) {
|
||||
recentChanges = recentChanges.filter((dc) => dc.child_id === selectedChildId);
|
||||
recentChanges = recentChanges.filter(
|
||||
(dc) => dc.child_id === selectedChildId,
|
||||
);
|
||||
}
|
||||
|
||||
// Count pee amounts
|
||||
@@ -718,7 +740,9 @@
|
||||
// Filter by selected child if applicable
|
||||
let filteredChanges = diaperChanges;
|
||||
if (selectedChildId !== null) {
|
||||
filteredChanges = diaperChanges.filter((dc) => dc.child_id === selectedChildId);
|
||||
filteredChanges = diaperChanges.filter(
|
||||
(dc) => dc.child_id === selectedChildId,
|
||||
);
|
||||
}
|
||||
|
||||
// Create days based on currentDaysRange (including today)
|
||||
@@ -742,8 +766,12 @@
|
||||
return changeDate >= date && changeDate < nextDay;
|
||||
});
|
||||
|
||||
const poopCount = dayChanges.filter(dc => dc.poop_amount !== null).length;
|
||||
const peeCount = dayChanges.filter(dc => dc.pee_amount !== null).length;
|
||||
const poopCount = dayChanges.filter(
|
||||
(dc) => dc.poop_amount !== null,
|
||||
).length;
|
||||
const peeCount = dayChanges.filter(
|
||||
(dc) => dc.pee_amount !== null,
|
||||
).length;
|
||||
|
||||
poopData.push(poopCount);
|
||||
peeData.push(peeCount);
|
||||
@@ -849,17 +877,29 @@
|
||||
const ctx = document.getElementById("poopPieChart").getContext("2d");
|
||||
|
||||
const colors = {
|
||||
"Light": { bg: "rgba(139, 69, 19, 0.5)", border: "rgba(139, 69, 19, 1)" },
|
||||
"Medium": { bg: "rgba(139, 69, 19, 0.7)", border: "rgba(139, 69, 19, 1)" },
|
||||
"Heavy": { bg: "rgba(139, 69, 19, 0.9)", border: "rgba(139, 69, 19, 1)" },
|
||||
"No Poop": { bg: "rgba(200, 200, 200, 0.5)", border: "rgba(200, 200, 200, 1)" },
|
||||
Light: {
|
||||
bg: "rgba(139, 69, 19, 0.5)",
|
||||
border: "rgba(139, 69, 19, 1)",
|
||||
},
|
||||
Medium: {
|
||||
bg: "rgba(139, 69, 19, 0.7)",
|
||||
border: "rgba(139, 69, 19, 1)",
|
||||
},
|
||||
Heavy: {
|
||||
bg: "rgba(139, 69, 19, 0.9)",
|
||||
border: "rgba(139, 69, 19, 1)",
|
||||
},
|
||||
"No Poop": {
|
||||
bg: "rgba(200, 200, 200, 0.5)",
|
||||
border: "rgba(200, 200, 200, 1)",
|
||||
},
|
||||
};
|
||||
|
||||
const backgroundColors = chartData.labels.map(
|
||||
(label) => colors[label]?.bg || "rgba(200, 200, 200, 0.5)"
|
||||
(label) => colors[label]?.bg || "rgba(200, 200, 200, 0.5)",
|
||||
);
|
||||
const borderColors = chartData.labels.map(
|
||||
(label) => colors[label]?.border || "rgba(200, 200, 200, 1)"
|
||||
(label) => colors[label]?.border || "rgba(200, 200, 200, 1)",
|
||||
);
|
||||
|
||||
new Chart(ctx, {
|
||||
@@ -900,8 +940,12 @@
|
||||
callbacks: {
|
||||
label: function (context) {
|
||||
const count = context.parsed;
|
||||
const total = context.dataset.data.reduce((a, b) => a + b, 0);
|
||||
const percentage = total > 0 ? ((count / total) * 100).toFixed(1) : 0;
|
||||
const total = context.dataset.data.reduce(
|
||||
(a, b) => a + b,
|
||||
0,
|
||||
);
|
||||
const percentage =
|
||||
total > 0 ? ((count / total) * 100).toFixed(1) : 0;
|
||||
return `${context.label}: ${count} (${percentage}%)`;
|
||||
},
|
||||
},
|
||||
@@ -915,17 +959,29 @@
|
||||
const ctx = document.getElementById("peePieChart").getContext("2d");
|
||||
|
||||
const colors = {
|
||||
"Light": { bg: "rgba(255, 215, 0, 0.5)", border: "rgba(255, 215, 0, 1)" },
|
||||
"Medium": { bg: "rgba(255, 215, 0, 0.7)", border: "rgba(255, 215, 0, 1)" },
|
||||
"Heavy": { bg: "rgba(255, 215, 0, 0.9)", border: "rgba(255, 215, 0, 1)" },
|
||||
"No Pee": { bg: "rgba(200, 200, 200, 0.5)", border: "rgba(200, 200, 200, 1)" },
|
||||
Light: {
|
||||
bg: "rgba(255, 215, 0, 0.5)",
|
||||
border: "rgba(255, 215, 0, 1)",
|
||||
},
|
||||
Medium: {
|
||||
bg: "rgba(255, 215, 0, 0.7)",
|
||||
border: "rgba(255, 215, 0, 1)",
|
||||
},
|
||||
Heavy: {
|
||||
bg: "rgba(255, 215, 0, 0.9)",
|
||||
border: "rgba(255, 215, 0, 1)",
|
||||
},
|
||||
"No Pee": {
|
||||
bg: "rgba(200, 200, 200, 0.5)",
|
||||
border: "rgba(200, 200, 200, 1)",
|
||||
},
|
||||
};
|
||||
|
||||
const backgroundColors = chartData.labels.map(
|
||||
(label) => colors[label]?.bg || "rgba(200, 200, 200, 0.5)"
|
||||
(label) => colors[label]?.bg || "rgba(200, 200, 200, 0.5)",
|
||||
);
|
||||
const borderColors = chartData.labels.map(
|
||||
(label) => colors[label]?.border || "rgba(200, 200, 200, 1)"
|
||||
(label) => colors[label]?.border || "rgba(200, 200, 200, 1)",
|
||||
);
|
||||
|
||||
new Chart(ctx, {
|
||||
@@ -966,8 +1022,12 @@
|
||||
callbacks: {
|
||||
label: function (context) {
|
||||
const count = context.parsed;
|
||||
const total = context.dataset.data.reduce((a, b) => a + b, 0);
|
||||
const percentage = total > 0 ? ((count / total) * 100).toFixed(1) : 0;
|
||||
const total = context.dataset.data.reduce(
|
||||
(a, b) => a + b,
|
||||
0,
|
||||
);
|
||||
const percentage =
|
||||
total > 0 ? ((count / total) * 100).toFixed(1) : 0;
|
||||
return `${context.label}: ${count} (${percentage}%)`;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -470,7 +470,8 @@
|
||||
}
|
||||
|
||||
function onChildChange(event) {
|
||||
selectedChildId = event.target.value === "all" ? null : parseInt(event.target.value);
|
||||
selectedChildId =
|
||||
event.target.value === "all" ? null : parseInt(event.target.value);
|
||||
displayFeedings(allFeedings);
|
||||
}
|
||||
|
||||
@@ -492,31 +493,34 @@
|
||||
const durationChartData = prepareDurationChartData(feedings);
|
||||
|
||||
// Build child dropdown options
|
||||
const childOptions = allChildren.map(child =>
|
||||
`<option value="${child.id}" ${selectedChildId === child.id ? 'selected' : ''}>${child.name}</option>`
|
||||
).join('');
|
||||
const childOptions = allChildren
|
||||
.map(
|
||||
(child) =>
|
||||
`<option value="${child.id}" ${selectedChildId === child.id ? "selected" : ""}>${child.name}</option>`,
|
||||
)
|
||||
.join("");
|
||||
|
||||
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>
|
||||
<option value="all" ${selectedChildId === null ? "selected" : ""}>All Children</option>
|
||||
${childOptions}
|
||||
</select>
|
||||
|
||||
<label for="daysRange">Time Range:</label>
|
||||
<select id="daysRange" onchange="onDaysRangeChange(event)">
|
||||
<option value="1" ${currentDaysRange === 1 ? 'selected' : ''}>Last 24 Hours</option>
|
||||
<option value="3" ${currentDaysRange === 3 ? 'selected' : ''}>Last 3 Days</option>
|
||||
<option value="7" ${currentDaysRange === 7 ? 'selected' : ''}>Last 7 Days</option>
|
||||
<option value="14" ${currentDaysRange === 14 ? 'selected' : ''}>Last 14 Days</option>
|
||||
<option value="30" ${currentDaysRange === 30 ? 'selected' : ''}>Last 30 Days</option>
|
||||
<option value="90" ${currentDaysRange === 90 ? 'selected' : ''}>Last 90 Days</option>
|
||||
<option value="1" ${currentDaysRange === 1 ? "selected" : ""}>Last 24 Hours</option>
|
||||
<option value="3" ${currentDaysRange === 3 ? "selected" : ""}>Last 3 Days</option>
|
||||
<option value="7" ${currentDaysRange === 7 ? "selected" : ""}>Last 7 Days</option>
|
||||
<option value="14" ${currentDaysRange === 14 ? "selected" : ""}>Last 14 Days</option>
|
||||
<option value="30" ${currentDaysRange === 30 ? "selected" : ""}>Last 30 Days</option>
|
||||
<option value="90" ${currentDaysRange === 90 ? "selected" : ""}>Last 90 Days</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<h2>Feedings Per Day (Last ${currentDaysRange} Day${currentDaysRange !== 1 ? 's' : ''})</h2>
|
||||
<h2>Feedings Per Day (Last ${currentDaysRange} Day${currentDaysRange !== 1 ? "s" : ""})</h2>
|
||||
<div class="chart-wrapper">
|
||||
<canvas id="feedingsChart"></canvas>
|
||||
</div>
|
||||
@@ -563,7 +567,9 @@
|
||||
|
||||
// Filter by selected child if applicable
|
||||
if (selectedChildId !== null) {
|
||||
filteredFeedings = filteredFeedings.filter((f) => f.child_id === selectedChildId);
|
||||
filteredFeedings = filteredFeedings.filter(
|
||||
(f) => f.child_id === selectedChildId,
|
||||
);
|
||||
}
|
||||
|
||||
// Sort by most recent first
|
||||
@@ -571,9 +577,12 @@
|
||||
return new Date(b.start_time) - new Date(a.start_time);
|
||||
});
|
||||
|
||||
const listHtml = filteredFeedings.map((feeding) => {
|
||||
const listHtml = filteredFeedings
|
||||
.map((feeding) => {
|
||||
const startTime = new Date(feeding.start_time);
|
||||
const endTime = feeding.end_time ? new Date(feeding.end_time) : null;
|
||||
const endTime = feeding.end_time
|
||||
? new Date(feeding.end_time)
|
||||
: null;
|
||||
|
||||
const dateStr = startTime.toLocaleDateString("en-US", {
|
||||
month: "short",
|
||||
@@ -594,22 +603,23 @@
|
||||
const typeLabel = formatFeedingType(feeding.feeding_type);
|
||||
|
||||
// Get child name
|
||||
const child = allChildren.find(c => c.id === feeding.child_id);
|
||||
const child = allChildren.find((c) => c.id === feeding.child_id);
|
||||
const childName = child ? child.name : "Unknown";
|
||||
|
||||
return `
|
||||
<div class="feeding-item">
|
||||
<div class="feeding-info-left">
|
||||
<div class="feeding-time">${dateStr} at ${timeStr}${selectedChildId === null ? ` - ${childName}` : ''}</div>
|
||||
<div class="feeding-time">${dateStr} at ${timeStr}${selectedChildId === null ? ` - ${childName}` : ""}</div>
|
||||
<div class="feeding-details">
|
||||
<span class="feeding-type-badge ${typeClass}">${typeLabel}</span>
|
||||
${duration !== null ? `${duration} minutes` : 'Ongoing'}
|
||||
${duration !== null ? `${duration} minutes` : "Ongoing"}
|
||||
</div>
|
||||
</div>
|
||||
<button class="edit-button" onclick="editFeeding(${feeding.id})">Edit</button>
|
||||
</div>
|
||||
`;
|
||||
}).join("");
|
||||
})
|
||||
.join("");
|
||||
|
||||
const listContainer = `
|
||||
<div class="feedings-list">
|
||||
@@ -624,7 +634,7 @@
|
||||
`;
|
||||
|
||||
const content = document.getElementById("content");
|
||||
content.insertAdjacentHTML('beforeend', listContainer);
|
||||
content.insertAdjacentHTML("beforeend", listContainer);
|
||||
}
|
||||
|
||||
function formatFeedingType(type) {
|
||||
@@ -660,7 +670,9 @@
|
||||
|
||||
// Filter by selected child if applicable
|
||||
if (selectedChildId !== null) {
|
||||
recentFeedings = recentFeedings.filter((f) => f.child_id === selectedChildId);
|
||||
recentFeedings = recentFeedings.filter(
|
||||
(f) => f.child_id === selectedChildId,
|
||||
);
|
||||
}
|
||||
|
||||
const typeCounts = {
|
||||
@@ -708,7 +720,9 @@
|
||||
|
||||
// Filter by selected child if applicable
|
||||
if (selectedChildId !== null) {
|
||||
completedFeedings = completedFeedings.filter((f) => f.child_id === selectedChildId);
|
||||
completedFeedings = completedFeedings.filter(
|
||||
(f) => f.child_id === selectedChildId,
|
||||
);
|
||||
}
|
||||
|
||||
// Calculate durations in minutes
|
||||
@@ -760,7 +774,9 @@
|
||||
// Filter by selected child if applicable
|
||||
let filteredFeedings = feedings;
|
||||
if (selectedChildId !== null) {
|
||||
filteredFeedings = feedings.filter((f) => f.child_id === selectedChildId);
|
||||
filteredFeedings = feedings.filter(
|
||||
(f) => f.child_id === selectedChildId,
|
||||
);
|
||||
}
|
||||
|
||||
// Create days based on currentDaysRange (including today)
|
||||
@@ -881,7 +897,7 @@
|
||||
background: "rgba(118, 75, 162, 0.8)",
|
||||
border: "rgba(118, 75, 162, 1)",
|
||||
},
|
||||
"Bottle": {
|
||||
Bottle: {
|
||||
background: "rgba(255, 159, 64, 0.8)",
|
||||
border: "rgba(255, 159, 64, 1)",
|
||||
},
|
||||
@@ -889,10 +905,10 @@
|
||||
|
||||
// Generate colors based on labels present
|
||||
const backgroundColors = chartData.labels.map(
|
||||
(label) => colorMap[label]?.background || "rgba(200, 200, 200, 0.8)"
|
||||
(label) => colorMap[label]?.background || "rgba(200, 200, 200, 0.8)",
|
||||
);
|
||||
const borderColors = chartData.labels.map(
|
||||
(label) => colorMap[label]?.border || "rgba(200, 200, 200, 1)"
|
||||
(label) => colorMap[label]?.border || "rgba(200, 200, 200, 1)",
|
||||
);
|
||||
|
||||
new Chart(ctx, {
|
||||
@@ -933,8 +949,12 @@
|
||||
callbacks: {
|
||||
label: function (context) {
|
||||
const count = context.parsed;
|
||||
const total = context.dataset.data.reduce((a, b) => a + b, 0);
|
||||
const percentage = total > 0 ? ((count / total) * 100).toFixed(1) : 0;
|
||||
const total = context.dataset.data.reduce(
|
||||
(a, b) => a + b,
|
||||
0,
|
||||
);
|
||||
const percentage =
|
||||
total > 0 ? ((count / total) * 100).toFixed(1) : 0;
|
||||
return `${context.label}: ${count} (${percentage}%)`;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -232,7 +232,11 @@
|
||||
<button type="submit" class="button" id="submitBtn">
|
||||
Log Diaper Change
|
||||
</button>
|
||||
<button type="button" class="button secondary" onclick="window.location.href='/'">
|
||||
<button
|
||||
type="button"
|
||||
class="button secondary"
|
||||
onclick="window.location.href='/'"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</form>
|
||||
@@ -252,8 +256,10 @@
|
||||
|
||||
// Update UI for edit mode
|
||||
if (isEditMode) {
|
||||
document.getElementById("pageTitle").textContent = "🧷 Edit Diaper Change";
|
||||
document.getElementById("submitBtn").textContent = "Update Diaper Change";
|
||||
document.getElementById("pageTitle").textContent =
|
||||
"🧷 Edit Diaper Change";
|
||||
document.getElementById("submitBtn").textContent =
|
||||
"Update Diaper Change";
|
||||
}
|
||||
|
||||
let children = [];
|
||||
@@ -291,7 +297,7 @@
|
||||
|
||||
// Load last used child from localStorage
|
||||
const lastDiaperChange = JSON.parse(
|
||||
localStorage.getItem("lastDiaperChange") || "{}"
|
||||
localStorage.getItem("lastDiaperChange") || "{}",
|
||||
);
|
||||
|
||||
if (lastDiaperChange.child_id) {
|
||||
@@ -311,22 +317,26 @@
|
||||
// Load diaper change data for editing
|
||||
async function loadDiaperChangeData() {
|
||||
try {
|
||||
const response = await fetch(`/api/diaper-changes/${diaperChangeId}`, {
|
||||
const response = await fetch(
|
||||
`/api/diaper-changes/${diaperChangeId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
if (response.ok) {
|
||||
const diaperChange = await response.json();
|
||||
|
||||
// Populate form fields
|
||||
document.getElementById("childSelect").value = diaperChange.child_id;
|
||||
document.getElementById("childSelect").value =
|
||||
diaperChange.child_id;
|
||||
|
||||
// Convert UTC time to local datetime-local format
|
||||
const changeTime = new Date(diaperChange.change_time);
|
||||
changeTime.setMinutes(
|
||||
changeTime.getMinutes() - changeTime.getTimezoneOffset()
|
||||
changeTime.getMinutes() - changeTime.getTimezoneOffset(),
|
||||
);
|
||||
document.getElementById("changeTime").value = changeTime
|
||||
.toISOString()
|
||||
@@ -355,11 +365,14 @@
|
||||
.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const childId = parseInt(document.getElementById("childSelect").value);
|
||||
const childId = parseInt(
|
||||
document.getElementById("childSelect").value,
|
||||
);
|
||||
const changeTime = new Date(
|
||||
document.getElementById("changeTime").value
|
||||
document.getElementById("changeTime").value,
|
||||
).toISOString();
|
||||
const poopAmount = document.getElementById("poopAmount").value || null;
|
||||
const poopAmount =
|
||||
document.getElementById("poopAmount").value || null;
|
||||
const poopColor = document.getElementById("poopColor").value || null;
|
||||
const peeAmount = document.getElementById("peeAmount").value || null;
|
||||
const peeColor = document.getElementById("peeColor").value || null;
|
||||
@@ -407,7 +420,7 @@
|
||||
"lastDiaperChange",
|
||||
JSON.stringify({
|
||||
child_id: childId,
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -415,7 +428,7 @@
|
||||
isEditMode
|
||||
? "Diaper change updated successfully!"
|
||||
: "Diaper change logged successfully!",
|
||||
"success"
|
||||
"success",
|
||||
);
|
||||
setTimeout(() => {
|
||||
window.location.href = "/";
|
||||
@@ -424,7 +437,7 @@
|
||||
const errorData = await response.json();
|
||||
showMessage(
|
||||
errorData.detail || "Failed to log diaper change",
|
||||
"error"
|
||||
"error",
|
||||
);
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = isEditMode
|
||||
|
||||
@@ -231,7 +231,8 @@
|
||||
// Update title and button text if editing
|
||||
if (isEditMode) {
|
||||
document.querySelector("h1").textContent = "🍼 Edit Feeding";
|
||||
document.querySelector(".subtitle").textContent = "Update feeding session details";
|
||||
document.querySelector(".subtitle").textContent =
|
||||
"Update feeding session details";
|
||||
submitBtn.textContent = "Update Feeding";
|
||||
}
|
||||
|
||||
@@ -299,15 +300,19 @@
|
||||
// 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);
|
||||
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);
|
||||
endTime.getTime() - endTime.getTimezoneOffset() * 60000,
|
||||
)
|
||||
.toISOString()
|
||||
.slice(0, 16);
|
||||
document.getElementById("endTime").value = endLocalDateTime;
|
||||
}
|
||||
|
||||
@@ -336,7 +341,9 @@
|
||||
messageDiv.classList.remove("show");
|
||||
|
||||
try {
|
||||
const url = isEditMode ? `/api/feedings/${feedingId}` : "/api/feedings";
|
||||
const url = isEditMode
|
||||
? `/api/feedings/${feedingId}`
|
||||
: "/api/feedings";
|
||||
const method = isEditMode ? "PUT" : "POST";
|
||||
|
||||
const response = await fetch(url, {
|
||||
@@ -357,8 +364,10 @@
|
||||
|
||||
if (response.ok) {
|
||||
showMessage(
|
||||
isEditMode ? "Feeding updated successfully!" : "Feeding logged successfully!",
|
||||
"success"
|
||||
isEditMode
|
||||
? "Feeding updated successfully!"
|
||||
: "Feeding logged successfully!",
|
||||
"success",
|
||||
);
|
||||
// Redirect to feedings page after 1 second
|
||||
setTimeout(() => {
|
||||
@@ -366,7 +375,8 @@
|
||||
}, 1000);
|
||||
} else {
|
||||
showMessage(
|
||||
data.detail || `Failed to ${isEditMode ? 'update' : 'log'} feeding. Please try again.`,
|
||||
data.detail ||
|
||||
`Failed to ${isEditMode ? "update" : "log"} feeding. Please try again.`,
|
||||
"error",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -528,8 +528,7 @@
|
||||
const sleepDate = new Date(sleep.start_time);
|
||||
const matchesTimeRange = sleepDate >= cutoffDate;
|
||||
const matchesChild =
|
||||
!selectedChildId ||
|
||||
sleep.child_id === parseInt(selectedChildId);
|
||||
!selectedChildId || sleep.child_id === parseInt(selectedChildId);
|
||||
return matchesTimeRange && matchesChild;
|
||||
});
|
||||
|
||||
@@ -576,7 +575,8 @@
|
||||
|
||||
// Prepare data for charts
|
||||
const barChartData = prepareBarChartData(filteredSleeps, timeRange);
|
||||
const durationDistData = prepareDurationDistributionData(completedSleeps);
|
||||
const durationDistData =
|
||||
prepareDurationDistributionData(completedSleeps);
|
||||
|
||||
let html = `
|
||||
<div class="stats-grid">
|
||||
|
||||
Reference in New Issue
Block a user