Commit Graph

186 Commits

Author SHA1 Message Date
Daniel Volz 56d244aa61 fix: stabilize frontend e2e selectors and auth/session reliability (#373) 2026-03-02 23:21:57 +01:00
Daniel Volz cd8263e607 fix: align desktop intake labels and form field pairing (#368)
* fix: align desktop intake labels and form field pairing

* chore: align frontend lockfile version and include remaining local changes
2026-03-02 01:33:28 +01:00
Daniel Volz da004b5c3e fix: align frontend tube/liquid container semantics (#364)
* fix: align frontend tube/liquid container semantics

* test(frontend): fix PR #364 CI regressions
2026-03-02 00:23:32 +01:00
Daniel Volz 9e8a6315e7 fix: keep topical stock non-depleting in planner flows (#359)
* fix: keep topical stock non-depleting in planner and reports

* test: stabilize e2e selectors for updated medication semantics

* fix(backend): add missing planner translation keys
2026-02-28 23:36:52 +01:00
Daniel Volz 8aaeca6b26 feat: simplify tube stock editing UI (#357)
* feat: add package amount persistence and backend route support

* test: align backend test schemas with medication metadata fields

* fix(backend): restore intake usage normalizer for planner endpoint

* fix(backend): keep export typing compatible before liquid-unit stack step

* feat: simplify tube stock editing in desktop and mobile forms
2026-02-28 23:24:48 +01:00
Daniel Volz b009d9e158 fix: frontend nginx restart loop from invalid log_format scope (#350)
* fix: place nginx log_format in valid context

* fix: unblock required checks for nginx hotfix

* fix: restore mandatory doku files in nginx hotfix pr
2026-02-27 01:47:59 +01:00
Daniel Volz ba0ab672b9 docs: update memory and report for multi-pr delivery (#347) 2026-02-27 01:15:40 +01:00
Daniel Volz 57c998ba09 chore: update dependabot automation and agent governance (#341)
* chore: update dependabot automation and agent governance

* chore: trigger required CI checks for governance PR
2026-02-27 01:11:05 +01:00
Daniel Volz cc22f80209 fix: align frontend types and tests for react 19 (#339) 2026-02-27 01:01:48 +01:00
Daniel Volz 19ba4bb7d2 feat: add FORM_LOGIN_ENABLED auth toggle (#334) 2026-02-27 00:48:58 +01:00
Daniel Volz f36d56c523 test: update modal tests to reflect global ESC handler
Remove ESC-keydown tests from ProfileModal.test.tsx since the
useEscapeKey hook was removed from individual modals. Escape key
handling is now centralized in App.tsx's global handler, making
per-component ESC tests invalid (the component no longer responds
to ESC in isolation).
2026-02-25 23:54:21 +01:00
Daniel Volz f0496e8ca5 fix: remove duplicate ESC handlers causing double history.back()
AboutModal, ProfileModal, and ShareDialog each had their own
useEscapeKey hook AND were handled by the global ESC handler in
App.tsx. When ESC was pressed, both fired synchronously, calling
history.back() twice — navigating past the current page instead
of just closing the modal.

Removed the per-modal useEscapeKey calls since the global handler
in App.tsx already manages ESC priority for all modals.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-25 23:50:07 +01:00
Daniel Volz d02f16af3a fix: stabilize e2e CI and local playwright workers (#321)
* fix: stabilize e2e CI and local playwright workers

* fix(ci): apply biome formatting and import order for frontend build
2026-02-25 22:15:38 +01:00
Copilot 2a9ca39c24 Allow medications with only a generic name (no commercial name required) (#311)
* Initial plan

* feat: allow generic name only for medications (frontend changes)

- Add getMedDisplayName() helper for consistent name display
- Update validation to require either commercial or generic name
- Update all display locations to use display name fallback
- Add i18n keys for nameOrGenericRequired in en.json and de.json
- Remove required attribute from commercial name field
- Update FIELD_LIMITS.name.min from 1 to 0

Co-authored-by: DanielVolz <3275994+DanielVolz@users.noreply.github.com>

* feat: allow generic name only for medications (backend changes)

- Update Zod schema to allow empty name with cross-field refinement
- Update reminder scheduler to use name || genericName for display
- Update planner routes to match medications by display name
- Update existing tests to match new validation behavior

Co-authored-by: DanielVolz <3275994+DanielVolz@users.noreply.github.com>

* fix: update placeholder text and fix FIELD_LIMITS test

- Remove "(optional)" from generic name placeholder in en/de
- Update types.test.ts to expect FIELD_LIMITS.name.min = 0

Co-authored-by: DanielVolz <3275994+DanielVolz@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: DanielVolz <3275994+DanielVolz@users.noreply.github.com>
2026-02-25 21:29:25 +01:00
Daniel Volz 6161c14a7b fix: logo optimization, deprecated meta tag, and clipboard copy fallback (#306)
- Replace 2 MB favicon.svg (base64-PNG-in-SVG) with optimized 43 KB app-logo.png (256x256)
- Update AppHeader and AboutModal references to use new logo
- Remove SVG favicon link from index.html (PNG/ICO favicons remain)
- Fix deprecated apple-mobile-web-app-capable → mobile-web-app-capable meta tag
- Add clipboard copy fallback for non-secure contexts (LAN IP over HTTP)

Closes #303
2026-02-25 00:04:35 +01:00
Daniel Volz 96b2a0c96f feat: image upload optimization with sharp, thumbnails, and structured error codes (#304)
- Add sharp for server-side image processing (WebP conversion + thumbnails)
- New shared backend utility for image upload, optimization, and cleanup
- Return structured error codes from upload endpoints (IMAGE_TOO_LARGE, INVALID_TYPE, etc.)
- Frontend error code mapping with i18n support (EN + DE)
- MedicationAvatar tries thumbnail first, falls back to full image
- Error display in MedicationsPage, MobileEditModal, and Auth avatar upload

Closes #302
2026-02-24 23:52:59 +01:00
Daniel Volz 26475fd3d0 feat: add correlation ids and tighten frontend security headers (#299)
* feat: add correlation ids and tighten frontend security headers

* docs: remove obsolete project setup guide

* fix: restore health config flags for compatibility

* test(frontend): align auth fetch assertions with correlation headers
2026-02-24 21:21:30 +01:00
Daniel Volz 63cd9ef19b fix: harden share link dose operations and token reuse (#298)
* fix: harden share link dose operations and token reuse

* fix: restore share dose compatibility and add correlation helper
2026-02-24 21:12:43 +01:00
Daniel Volz b0c5d48095 chore: update bug template guidance and include app test changes (#293) 2026-02-23 19:54:18 +01:00
Daniel Volz ba36f67371 fix: smooth mobile edit transition and align modal validation behavior (#286)
* fix: reliable Escape key close for all modals via useEscapeKey hook

- Add useEscapeKey hook (document-level keydown listener)
- Retrofit all 12 modal/overlay components to use it
- Remove redundant overlay onKeyDown Escape handlers
- Simplify modal-content onKeyDown to plain stopPropagation
- Replace MedDetailModal's capture-phase useEffect with 3 useEscapeKey calls
- Replace SharedSchedule's inline useEffect with useEscapeKey
- Add mandatory modal rules to UI Consistency skill
- All 777 frontend + 569 backend tests pass

* fix: smooth mobile edit transition and align modal validation behavior

* fix: keep overlay keydown non-closing for Enter key

* fix: show mobile name error when validation already exists

* fix: restore app-level escape priority handling

* fix: prioritize schedule lightbox on Escape
2026-02-23 06:42:06 +01:00
Daniel Volz 2aa6b1f406 fix: prevent background scroll when any modal is open (#284)
Replace CSS-only modal-open class toggle with a shared useScrollLock
hook that uses position:fixed + scroll position save/restore. This
reliably prevents background scrolling on all browsers including
iOS Safari.

The hook supports nesting (lock counter) so stacked modals (e.g.
MedDetail → RefillModal) work correctly.

Also adds missing modal states to the scroll lock: showRefillModal,
showEditStockModal, showImageLightbox, scheduleLightboxImage.

Replaces the inline 40-line scroll lock in MobileEditModal with the
shared hook.
2026-02-22 18:40:39 +01:00
Daniel Volz 259f00e7a0 fix: unify number stepper layout and detail modal padding (#279)
Reorder stepper DOM elements (input first) and apply refill-number-stepper
class to both steppers for consistent CSS order-based layout.
Fix missing bottom padding on .med-detail-body.
2026-02-22 17:57:36 +01:00
Daniel Volz 33c1095e77 feat: add FormNumberStepper to medication edit forms (#274)
Replace plain numeric inputs with a reusable +/− stepper component in
both desktop (MedicationsPage) and mobile (MobileEditModal) edit forms.

Applied to Stock, Schedule, and Prescription tab fields. Reorder tabs
so Schedule appears before Prescription. Add responsive grid overrides
for narrow sidebar and compact schedule rows.

Fix label-hover ghost activation by placing <input> first in DOM
(CSS order restores visual [−] [value] [+] layout).

Closes #273
2026-02-22 16:49:51 +01:00
Daniel Volz 9a2d42b8b9 fix: stabilize dashboard modal and image click behavior (#267)
* feat: make medication names clickable in Dashboard dose schedule

Add click handlers to med-name-stack divs in all three dose schedule
sections (past, current/overdue, future) on DashboardPage, opening the
MedDetail modal on click.

Add early-return guards to all four modal openers in AppContext
(openMedDetail, openImageLightbox, openScheduleLightbox, openUserFilter)
to prevent duplicate pushState entries on double-click, which caused
unexpected navigation to the Medications page.

Closes #266

* fix: stabilize dashboard modal and image click handling

* fix: close medication detail on first backdrop click
2026-02-22 10:50:58 +01:00
Daniel Volz 088a6c1a05 chore: fix all Biome lint warnings and MedDetail intake bell icons (#265)
- Backend: refactor nested ternaries, remove unused imports/any types
- Frontend: fix exhaustive deps, a11y label associations, array index keys,
  empty CSS blocks, unused vars, type annotations
- MedDetail modal: fix intake schedule bell icons not rendering (use unified
  intake source with fallback), place bell inline after person name
- MedDetail modal: revert schedule rows from grid to flexbox layout

Closes #264
2026-02-22 08:52:03 +01:00
Daniel Volz afb8e5028c fix: auto-mark intakes at due time and show robot marker (#261)
* fix: auto-mark intakes at due time and show robot marker

* test: add taken_source to integration schema

* test: align e2e route schema with taken_source
2026-02-21 20:45:05 +01:00
Daniel Volz 976d7356ec feat: improve medication detail modal layout and display (#258)
Widen detail modal on desktop (711px, up from 500px) with max-width
override to beat modals-base.css specificity. Limit fullscreen mode
to actual phones (<=500px) instead of all screens <=900px. Move intake
schedule section before prescription details. Show per-intake takenBy
person and bell icon with proper warning color. Right-align time in
schedule rows. Move notes icon after label text. Replace emoji bell
icons with Lucide Bell component in SchedulePage and MobileEditModal.
Add common.on/common.off i18n keys.

Closes #254
2026-02-21 18:00:23 +01:00
Daniel Volz 943148fb49 feat: close modals with browser back button on mobile (#257)
* feat: close modals with browser back button on mobile

Create reusable useModalHistory hook that pushes history state when a
modal opens and listens for popstate to close it. Apply to ReportModal,
ClearMissedConfirm, ExportModal, ImportConfirm, and all modals using
ConfirmModal/ShareDialog/Auth/ExportModal base components. Escape key
handling was already in place for desktop.

Closes #253

* fix: update tests for renamed button labels and missing useModalHistory mock
2026-02-21 18:00:12 +01:00
Daniel Volz 94bd8bd6e8 feat: improve mobile edit modal swipe gestures and tab navigation (#256)
* feat: improve mobile edit modal swipe gestures and tab navigation

Replace React passive touch handlers with native non-passive
addEventListener via useEffect for reliable horizontal swipe blocking.
Reduce axis-lock threshold from 18-26px to 6px for more responsive
gesture detection. Remove isInteractive() guard so swipe works on
input fields. Add tab strip auto-scroll via scrollIntoView when
active tab changes. Fix vertical scrolling by changing readonly
fieldset from display:block to display:flex.

Closes #252

* fix: guard scrollIntoView for jsdom test compatibility
2026-02-21 18:00:02 +01:00
Daniel Volz 0cf1c5353e fix: notification channel toggles snap back after being enabled (#255)
* fix: notification channel toggles snap back after being enabled

The checked props for email/push notification toggles had redundant
conditions (smtpHost/shoutrrrUrl checks) that forced them to false,
causing immediate visual snap-back. Additionally, performSave()
overwrote emailEnabled/shoutrrrEnabled in local state with effective
values, disabling toggles when no SMTP host or Shoutrrr URL was set.

Remove redundant checked prop conditions (disabled attr already handles
interaction gating) and stop overwriting enabled flags in local state
after save.

Closes #250

* fix: remove leaked useModalHistory import from SettingsPage

* fix: update useSettings tests to match new toggle behavior
2026-02-21 17:59:50 +01:00
Daniel Volz 75c201cab5 fix: keep med detail stock and package values consistent (#249) 2026-02-21 15:47:44 +01:00
Daniel Volz fd3b770a81 fix: improve mobile edit modal scrolling behavior (#247) 2026-02-21 15:24:57 +01:00
Daniel Volz 612aa007aa fix: unify stock semantics across planner and scheduler (#245)
* fix: unify stock semantics across planner and scheduler

* fix: stabilize dashboard hmr and align stock helper tests
2026-02-21 15:24:53 +01:00
Daniel Volz b489e1e117 fix: keep mobile med detail actions visible while scrolling (#240) 2026-02-20 19:31:59 +01:00
Daniel Volz 052751b2ba feat: reports, timeline toggles, and stock correction improvements (#236)
* refactor(frontend): modularize styles and polish modal/ui interactions

* feat: add report workflow and timeline/settings improvements

* fix: resolve CI failures for backend typing, lint, and playwright config
2026-02-20 18:52:59 +01:00
Daniel Volz 89d565bc9d chore: fix lint errors and reduce warnings across codebase (#234)
* chore: fix lint errors and reduce warnings across codebase

- Fix noExplicitAny catches in backend routes and plugins
- Fix noNestedTernary issues in backend services
- Add keyboard event handlers for useKeyWithClickEvents in frontend
- Disable noImportantStyles rule in biome.json
- Fix formatting errors across all changed files
- Fix test file lint issues

Closes #233

* fix: restore any types in test files for TS compatibility

* fix: revert Auth.tsx dependency array changes that caused infinite re-render

* fix: null-safe user.username access in AppContext dependency array
2026-02-17 05:21:47 +01:00
Daniel Volz 08a18fc14a fix: improve export filename and import confirmation UX (#232)
Export filename:
- Include username for multi-user/instance distinction
- Include timestamp with time (YYYYMMDD-HHMM) instead of date only
- Example: medassist-export-daniel-20260216-2108.json

Import confirmation:
- Show friendly 'Import Data?' dialog on empty instances instead of
  scary 'Replace All Data?' warning with danger button
- Only show destructive warning when there is existing data to replace
- Use primary button style for empty-state import

Closes #231
2026-02-16 22:20:20 +01:00
Daniel Volz 779870960c fix: frontend UI polish — tooltips, planner checkbox, settings layout (#228)
- Fix mobile tooltip positioning (above icon instead of centered)
- Place planner checkbox and send-now button on same row
- Move settings tooltips beside input fields instead of overlapping
- Fix input-with-tooltip layout for narrow screens
- Add daily/everyNDays i18n keys for dose frequency display
- Fix lint formatting in page components

Closes #225
2026-02-16 21:51:51 +01:00
Daniel Volz 871e6066ec fix: export/import missing refill history, prescription, and bottle fields (#227)
- Add refill history export/import with medication reference mapping
- Include totalPills (bottle type capacity) in inventory export
- Include dismissedUntil field for past dose dismissal state
- Add expiryWarningDays and shareStockStatus to settings export
- Bump export version to 1.1
- Add refill count to import result reporting
- Update i18n import success details to include refill count

Closes #224
2026-02-16 21:51:39 +01:00
Daniel Volz 4b697374f6 feat: obsolete medication archiving, start date, and UI improvements (#215)
* feat: obsolete medication archiving, start date, and UI improvements

- Add soft-archive (obsolete) for medications with dedicated section and toggle
- Add medication start date field with date picker and validation
- Add obsolete/reactivate API endpoints with proper auth
- Filter obsolete meds from schedule, coverage, planner, and notifications
- Improve UserFilterModal with intake schedules, stock badges, and click-to-open
- Improve dashboard taken-by badges with per-intake bell icons
- Add Escape key support to ConfirmModal and MobileEditModal
- Fix Lightbox close button positioning near image
- Add read-only mode support for MobileEditModal
- DB migrations: 0008 (is_obsolete, obsolete_at), 0009 (medication_start_date)
- All user-facing text uses i18n keys (en + de)

* test: fix tests for obsolete medications and UI changes

- Backend: add is_obsolete, obsolete_at, medication_start_date columns to test schemas
- Backend: add test medication inserts in planner tests for active-med filtering
- Frontend: update useMedications URL to include includeObsolete param
- Frontend: fix MobileEditModal selectors and validation assertions
- Frontend: add onClearUser prop to UserFilterModal test renders
- Frontend: fix MedicationsPage and DashboardPage test assertions
2026-02-15 23:23:38 +01:00
Daniel Volz a016e45ef2 feat: frontend LOG_LEVEL support via logger utility (#209)
- Inject LOG_LEVEL at build time via Vite define (__LOG_LEVEL__, default: warn)
- Create frontend logger utility (frontend/src/utils/logger.ts) mirroring backend API
- Replace all console.error calls with log.error in MedicationsPage, AppContext, Auth
- Supports levels: silent > error > warn > info > debug

Closes #205
2026-02-14 20:28:06 +01:00
Daniel Volz 150be1e114 feat: add prescription refills column to planner table and email (#207)
- Add 6th column 'Prescription refills' to frontend Planner table
- Add matching column to backend planner email (HTML + plaintext)
- Show remaining refills for meds with prescription tracking, '–' otherwise
- Add backend translations for new column header (EN + DE)
- Add frontend i18n keys for prescription refills column
- Update planner tests with medications table schema

Closes #203
2026-02-14 20:21:09 +01:00
Daniel Volz 6ff0ad2745 fix: mobile modal UX improvements (delete confirm, browser-back, z-index) (#206)
- Replace browser confirm() with ConfirmModal for delete confirmation
- Add dedicated history entry for delete dialog so browser back dismisses it
- Track unsaved-changes warning source to restore correct context on cancel
- Add overlayClassName prop to ConfirmModal for nested z-index layering
- Add .nested-confirm CSS class for proper modal stacking
- Add i18n keys for delete confirmation dialog (EN + DE)

Closes #202
2026-02-14 20:17:01 +01:00
Daniel Volz 0ffab23b6d feat: add back button in medication edit header (#201) 2026-02-14 19:22:37 +01:00
Daniel Volz 8273b07231 feat: track number of prescription repeats (#193)
* feat: track prescription repeats and refill reminders

* test: align backend and frontend suites with current prescription and UI behavior

* test: update frontend and backend expectations for latest reminders and refill flow
2026-02-14 19:07:36 +01:00
Daniel Volz edf42bb068 fix: show reminder icon per intake dose in schedule (#198)
* fix: show reminder icon per intake dose in schedule

* test: align schedule reminder icon test with intake-level flag
2026-02-14 18:53:52 +01:00
Daniel Volz 5c09f97cb3 test: improve frontend test coverage (#163)
- Export DashboardPage helper functions for testability
- Add new test files: App, SharedSchedule, AppContext, UnsavedChangesContext, useUnsavedChangesWarning
- Expand existing test coverage for Auth, MedDetailModal, MobileEditModal, DashboardPage, MedicationsPage, PlannerPage, and more
- Add edge case and error handling tests across components, hooks, and pages
2026-02-13 18:34:19 +01:00
Daniel Volz 4275dca838 fix: improve modal scroll lock and e2e script workflow (#156) 2026-02-12 21:43:28 +01:00
Daniel Volz 1c50e9395f fix: past days UX improvements and clear missed logic (#152)
- Render past days above 'Show past days' toggle when expanded
- Auto-scroll to today when expanding past days
- Remove blue hover color from past day dividers (use opacity instead)
- Fix 'All taken' logic: green only for manually taken doses
- Yellow styling stays for days with non-taken doses (even after dismissal)
- Warning icon disappears after 'Clear missed' (dismissed doses not counted)
2026-02-10 16:42:23 +01:00
Daniel Volz 749e92b135 fix: bottle total capacity backward compatibility (#149)
* fix: bottle total capacity shows dash for old medications

Old medications created before the totalPills column was added had
totalPills=null. This caused two issues:

1. MedDetailModal showed '—' instead of the actual capacity in the
   Package Details section (while the Stock section showed correct values)
2. Edit form showed an empty Total Capacity field on mobile

Fix: Fall back to packageSize (looseTablets for bottles) when totalPills
is null, matching the behavior already used in MedicationsPage and the
stock display section.

Added test for backward compatibility scenario.

* chore: retrigger CI
2026-02-09 20:59:30 +01:00