From b763aa1e9de1b6b7619db7de8983a54a30dd3b0c Mon Sep 17 00:00:00 2001 From: Jacob Hagstedt Date: Thu, 4 Jun 2026 09:18:22 +0200 Subject: [PATCH] Small cleanup --- test_asgi.py => backend/scripts/test_asgi.py | 0 test_db.py => backend/scripts/test_db.py | 0 backend_log.txt | 14 ----- build-docker.sh | 16 ------ push-docker.sh | 5 -- test-results/.last-run.json | 4 -- test_timezone.js | 33 ----------- todo.md | 10 ++-- verify_final_fix.py | 58 -------------------- verify_timezone.py | 57 ------------------- wakeup_times_plan.md | 31 ----------- 11 files changed, 6 insertions(+), 222 deletions(-) rename test_asgi.py => backend/scripts/test_asgi.py (100%) rename test_db.py => backend/scripts/test_db.py (100%) delete mode 100644 backend_log.txt delete mode 100644 build-docker.sh delete mode 100644 push-docker.sh delete mode 100644 test-results/.last-run.json delete mode 100644 test_timezone.js delete mode 100644 verify_final_fix.py delete mode 100644 verify_timezone.py delete mode 100644 wakeup_times_plan.md diff --git a/test_asgi.py b/backend/scripts/test_asgi.py similarity index 100% rename from test_asgi.py rename to backend/scripts/test_asgi.py diff --git a/test_db.py b/backend/scripts/test_db.py similarity index 100% rename from test_db.py rename to backend/scripts/test_db.py diff --git a/backend_log.txt b/backend_log.txt deleted file mode 100644 index 2c744b1..0000000 --- a/backend_log.txt +++ /dev/null @@ -1,14 +0,0 @@ -INFO: Will watch for changes in these directories: ['/Users/jhag/projects/babymonitor/backend'] -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [63655] using StatReload -INFO: Started server process [63657] -INFO: Waiting for application startup. -INFO: Application startup complete. -WARNING: StatReload detected changes in 'app/main.py'. Reloading... -INFO: Shutting down -INFO: Waiting for application shutdown. -INFO: Application shutdown complete. -INFO: Finished server process [63657] -INFO: Started server process [71064] -INFO: Waiting for application startup. -INFO: Application startup complete. diff --git a/build-docker.sh b/build-docker.sh deleted file mode 100644 index fdf404e..0000000 --- a/build-docker.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -docker buildx build \ - --platform linux/arm64 \ - -t babymonitor-frontend:latest \ - -f frontend/Dockerfile \ - --load \ - frontend - -docker buildx build \ - --platform linux/arm64 \ - -t babymonitor-backend:latest \ - -f backend/Dockerfile \ - --load \ - backend - \ No newline at end of file diff --git a/push-docker.sh b/push-docker.sh deleted file mode 100644 index 58e5d7b..0000000 --- a/push-docker.sh +++ /dev/null @@ -1,5 +0,0 @@ -podman save babymonitor-frontend:latest -o frontend.tar - -podman save babymonitor-backend:latest -o backend.tar - -scp frontend.tar backend.tar jacobhagstedt@raspberrypi.local:~/ diff --git a/test-results/.last-run.json b/test-results/.last-run.json deleted file mode 100644 index 5fca3f8..0000000 --- a/test-results/.last-run.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "status": "failed", - "failedTests": [] -} \ No newline at end of file diff --git a/test_timezone.js b/test_timezone.js deleted file mode 100644 index 1e9ea2d..0000000 --- a/test_timezone.js +++ /dev/null @@ -1,33 +0,0 @@ -const adjustForTimezone = (utcMinutes) => { - const offsetInMinutes = -120; // Simulate UTC+2 - return utcMinutes - offsetInMinutes; -}; - -const formatMinutesAfter = (minutes, reference = "04:00") => { - const [refHours, refMinutes] = reference.split(":").map(Number); - const totalRefMinutes = refHours * 60 + refMinutes; - const targetMinutes = totalRefMinutes + minutes; - const normalizedMinutes = ((targetMinutes % 1440) + 1440) % 1440; - const hours = Math.floor(normalizedMinutes / 60); - const mins = normalizedMinutes % 60; - return `${String(hours).padStart(2, "0")}:${String(mins).padStart(2, "0")}`; -}; - -// Case 1: Backend sends offset from 04:00 UTC (-5 minutes) -const backendOffset = -5; -const adjusted = adjustForTimezone(backendOffset); -console.log("Adjusted offset:", adjusted); // Should be 115 -console.log("Formatted time:", formatMinutesAfter(adjusted, "04:00")); // Should be 05:55 - -// Case 2: Backend sends minutes from UTC midnight (235 minutes) -const backendMidnightMins = 235; -const adjusted2 = adjustForTimezone(backendMidnightMins); -console.log("Adjusted midnight mins:", adjusted2); // Should be 355 -// If we use it as an offset from reference: -console.log("Formatted time (as offset):", formatMinutesAfter(adjusted2, "04:00")); // Should be 09:55 (WRONG if it was supposed to be 05:55) - -// If we want the offset from reference for Case 2: -const refMins = 4 * 60; -const correctOffset = adjusted2 - refMins; // 355 - 240 = 115 -console.log("Corrected offset (from midnight):", correctOffset); // 115 -console.log("Formatted time (corrected):", formatMinutesAfter(correctOffset, "04:00")); // 05:55 diff --git a/todo.md b/todo.md index f0e08a7..bbce8fb 100644 --- a/todo.md +++ b/todo.md @@ -20,9 +20,9 @@ exitcode '1': failure - [ ] Editing a sleep session in "sleep sessions", when I click the edit button the times show up as UTC but should show as my local timezone - [ ] We should drop the "notes" column from the sleep_session table -- [ ] Switch over to oh-my-opencode and try it out -- [ ] Adda footer at the bottom of the app that shows the version (aka git tag) of the app -- [ ] Fix race condition of gitea workflows +- [x] Switch over to oh-my-opencode and try it out +- [/] Adda footer at the bottom of the app that shows the version (aka git tag) of the app +- [-] Fix race condition of gitea workflows If both workflows run at the same time, a race condition occurs: 1. Collision: Both workflows will query the latest tag (e.g., v1.0.5) and calculate the same next version (v1.0.6). @@ -30,4 +30,6 @@ If both workflows run at the same time, a race condition occurs: 3. The Loser: The second workflow will attempt to push v1.0.6, but the remote will reject it because that tag already exists, causing the workflow to fail. This happens because both workflows share the same global tag namespace (v1.0.x). To fix this, you should differentiate them by using unique prefixes, such as backend-v1.0.x and frontend-v1.0.x. -- [ ] remove the lint form the gitea workflows added by the agent. makes no sense there +--> Invalid. the containers are named differently. + +- [x] remove the lint form the gitea workflows added by the agent. makes no sense there diff --git a/verify_final_fix.py b/verify_final_fix.py deleted file mode 100644 index 452cdec..0000000 --- a/verify_final_fix.py +++ /dev/null @@ -1,58 +0,0 @@ -import datetime - -def verify_real_wakeup_with_mock_api(): - # --- DATA FROM DATABASE (REAL) --- - # session id 1 wakeup: 2026-05-27 03:17:00 UTC - wakeup_utc = datetime.datetime(2026, 5, 27, 3, 17) - wakeup_utc_mins = wakeup_utc.hour * 60 + wakeup_utc.minute - - # --- SETUP PARAMETERS (CLIENT SIDE) --- - # User is in Stockholm (+2) - offset_in_minutes = -120 - local_ref_str = "04:00" - local_ref_mins = 4 * 60 - - print(f"1. Database Wakeup (UTC): {wakeup_utc} ({wakeup_utc_mins}m)") - print(f"2. Client Local Reference: {local_ref_str} ({local_ref_mins}m)") - print(f"3. Client Timezone Offset: {offset_in_minutes}m") - - # --- STEP 1: SIMULATE API CALL (CLIENT SIDE) --- - def localHHMMToUTCHHMM(hhmm, offset): - [h, m] = map(int, hhmm.split(":")) - total_mins_utc = (h * 60 + m) + offset - norm = ((total_mins_utc % 1440) + 1440) % 1440 - return f"{norm // 60:02d}:{norm % 60:02d}" - - utc_ref = localHHMMToUTCHHMM(local_ref_str, offset_in_minutes) - print(f"4. Simulated API call with wakeup_ref (converted to UTC): {utc_ref}") - - # --- STEP 2: SIMULATE BACKEND (SERVER SIDE) --- - # Backend receives utc_ref and calculates delta: wakeup_utc - utc_ref - utc_ref_mins = (int(utc_ref.split(":")[0]) * 60 + int(utc_ref.split(":")[1])) - backend_delta = wakeup_utc_mins - utc_ref_mins - print(f"5. Backend returns delta: {backend_delta}") - - # --- STEP 3: SIMULATE COMPONENT RENDERING (CLIENT SIDE) --- - # Component receives delta and uses it directly as offsetFromRef. - offset_from_ref = backend_delta - - def formatMinutesAfter(minutes, ref): - [rh, rm] = map(int, ref.split(":")) - target = (rh * 60 + rm) + minutes - norm = ((target % 1440) + 1440) % 1440 - return f"{norm // 60:02d}:{norm % 60:02d}" - - displayed_time = formatMinutesAfter(offset_from_ref, local_ref_str) - print(f"6. Component renders time: {displayed_time}") - - # --- ASSERTION --- - expected_local_time = "05:17" - print(f"\nASSERTION: Expected {expected_local_time}, Actual {displayed_time}") - if displayed_time == expected_local_time: - print("VERIFICATION SUCCESSFUL!") - else: - print("VERIFICATION FAILED!") - exit(1) - -if __name__ == "__main__": - verify_real_wakeup_with_mock_api() diff --git a/verify_timezone.py b/verify_timezone.py deleted file mode 100644 index 770d912..0000000 --- a/verify_timezone.py +++ /dev/null @@ -1,57 +0,0 @@ -import datetime - -def solve(): - # Scenario: User in Stockholm (UTC+2) - # Local Wakeup Reference: 04:00 - # Actual Wakeup Time (UTC): 03:17 - - offset_minutes = -120 # Stockholm UTC+2 -> getTimezoneOffset() is -120 - - wakeup_ref_local = "04:00" - wakeup_ref_mins_local = 4 * 60 - - # Let's assume the backend calculates: wakeup_minutes = (UTC_wakeup - UTC_ref) - # where it treats the provided ref as if it were in UTC. - - # Case 1: BUGGY (Frontend sends Local ref "04:00" to backend) - # Backend treats 04:00 as UTC. - utc_wakeup = 3 * 60 + 17 # 03:17 UTC - wakeup_minutes_from_backend = utc_wakeup - wakeup_ref_mins_local # 197 - 240 = -43 - print(f"BUGGY: Backend returns wakeup_minutes (assuming ref 04:00 is UTC): {wakeup_minutes_from_backend}") - - # Frontend (current) tries to fix it with adjustForTimezone: - received_wakeup_minutes = wakeup_minutes_from_backend - # offsetFromRef = getLocalOffsetFromReference(received, "04:00") - # localMins = adjustForTimezone(received) = received - offset_minutes - # offsetFromRef = localMins - ref_mins_local - - def adjustForTimezone(utc_min): - return utc_min - offset_minutes - - def getLocalOffsetFromReference(utc_min, ref_mins): - local_m = adjustForTimezone(utc_min) - return local_m - ref_mins - - offset_from_ref = getLocalOffsetFromReference(received_wakeup_minutes, wakeup_ref_mins_local) - print(f"BUGGY: Frontend calculates offsetFromRef: {offset_from_ref}") - # formatMinutesAfter(offset, ref) -> ref + offset - print(f"BUGGY: Displayed time (ref + offset): {wakeup_ref_mins_local + offset_from_ref}") - - # Case 2: CORRECT (Frontend sends UTC ref "02:00" to backend) - # Stockholm +2 means 04:00 Local is 02:00 UTC. - utc_wakeup_ref = wakeup_ref_mins_local + offset_minutes # 240 - 120 = 120 - wakeup_minutes_from_backend_correct = utc_wakeup - utc_wakeup_ref # 197 - 120 = 77 - print(f"\nCORRECT: Backend returns wakeup_minutes (assuming ref 02:00 is UTC): {wakeup_minutes_from_backend_correct}") - - # Frontend receives 77. - # If it's a delta, the component should use it directly as offsetFromRef. - # Or if we want to keep existing logic, we have to realize 77 is ALREADY the delta. - # But the component thinks it's "minutes from midnight". - # This is a mismatch. - - print("---") - print(f"Target Local Wakeup: 05:17 ({3 * 60 + 17 + abs(offset_minutes)})") - print(f"Target Local Ref: 04:00 ({wakeup_ref_mins_local})") - print(f"Target Local Delta: {317 - 240} = 77") - -solve() diff --git a/wakeup_times_plan.md b/wakeup_times_plan.md deleted file mode 100644 index 7c7de2c..0000000 --- a/wakeup_times_plan.md +++ /dev/null @@ -1,31 +0,0 @@ -# Plan: Fix Timezone Handling in Wakeup Times Module - -## Problem Description -The "Wakeup Times" chart (in `frontend/src/components/stats/WakeupPlot.tsx`) displays wakeup times incorrectly due to a timezone mismatch. -- **Observation**: If a baby wakes up at `05:55` local time (e.g., in UTC+2), the chart shows `03:55`. -- **Cause**: The backend stores times in UTC. The frontend currently receives minutes relative to UTC midnight and renders them directly using `formatMinutesAfter` without applying the client's local timezone offset. - -## Investigation Steps -1. **Backend Verification**: - - Examine `backend/app/routers/stats.py` (or equivalent) and the CRUD logic to confirm that `wakeup_minutes` is calculated based on UTC midnight. - - Verify how the backend handles the `wakeup_ref` and `bedtime_ref` parameters. -2. **Frontend Logic Audit**: - - Trace the data flow from `fetchWakeSleepTimes` -> `useStats` -> `WakeupPlot.tsx`. - - Confirm that `wakeup_minutes` is indeed a raw offset from UTC midnight. - -## Implementation Plan -1. **Calculate Local Offset**: Use `new Date().getTimezoneOffset()` in the frontend to determine the difference between UTC and local time. -2. **Adjust Minutes**: - - In `WakeupPlot.tsx`, modify the mapping logic to adjust `day.wakeup_minutes` by the local timezone offset before it is passed to `formatMinutesAfter`. - - Formula: `local_minutes = utc_minutes - (timezone_offset_in_minutes)`. - *(Note: `getTimezoneOffset()` returns minutes positive for west of UTC, negative for east, so subtraction is correct to add offset to UTC).* -3. **Refactor Utilities (if needed)**: If the logic is used elsewhere, consider moving timezone-aware formatting to `frontend/src/utils/time.ts`. - -## Verification Plan -1. **Manual Verification**: - - Mock a response from the backend with a known UTC time. - - Check if the rendered string matches the expected local time. -2. **Automated Testing**: - - Add/update a test case in `frontend/tests/e2e/stats.spec.ts` (or a unit test in `frontend/tests/`) that simulates different timezone offsets to ensure the display is correct. -3. **Regression Check**: - - Ensure `BedtimePlot.tsx` and other time-related components are not negatively impacted by changes to shared utilities.