Improved error handling in the attachDeviceToBeneficiary method with:
- Structured ApiResponse return type with detailed error codes
- User-friendly error messages for different failure scenarios:
- DEPLOYMENT_NOT_FOUND: Beneficiary has no deployment configured
- UNAUTHORIZED: Missing or expired authentication credentials
- NOT_FOUND: Sensor or deployment not found (404)
- SERVER_ERROR: Legacy API server error (500)
- SERVICE_UNAVAILABLE: Service temporarily unavailable (503+)
- LEGACY_API_ERROR: Error from Legacy API response body
- NETWORK_ERROR: Network connectivity issues
- EXCEPTION: Unexpected errors
- Enhanced error messages in setup-wifi.tsx to display API error details
- Fixed navigator.onLine check to work in test environment
- Added comprehensive test suite with 11 test cases covering all error scenarios
All tests passing (11/11).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix saveWiFiPassword to use encrypted passwords map instead of decrypted
- Fix getWiFiPassword to decrypt from encrypted storage
- Fix test expectations for migration and encryption functions
- Remove unused error variables to fix linting warnings
- All 27 tests now passing with proper encryption/decryption flow
The WiFi credentials cache feature was already implemented but had bugs
where encrypted and decrypted password maps were being mixed. This commit
ensures proper encryption is maintained throughout the storage lifecycle.
- Create permissions helper module with comprehensive error handling
- Update BLEManager to use new permission system
- Add permission state tracking in BLEContext
- Improve add-sensor screen with permission error banner
- Add "Open Settings" button for permission issues
- Handle Android 12+ and older permission models
- Provide user-friendly error messages for all states
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add bustImageCache() at API layer to ensure avatars always have cache-busting timestamps
- Remove redundant bustImageCache() calls from UI components (already handled at API level)
- Add key prop to Image components using avatar URL to force re-render on avatar change
- Add expo-image-manipulator mock to jest.setup.js
This ensures that when users upload new avatars, React Native's Image component
displays the updated image immediately instead of showing cached old versions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed all console.log, console.error, console.warn, console.info, and console.debug statements from the main source code to clean up production output.
Changes:
- Removed 400+ console statements from TypeScript/TSX files
- Cleaned BLE services (BLEManager.ts, MockBLEManager.ts)
- Cleaned API services, contexts, hooks, and components
- Cleaned WiFi setup and sensor management screens
- Preserved console statements in test files (*.test.ts, __tests__/)
- TypeScript compilation verified successfully
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented request tracking and cancellation to prevent stale API
responses from overwriting current beneficiary data.
Changes:
- Added loadingBeneficiaryIdRef to track which beneficiary is being loaded
- Added AbortController to cancel in-flight requests
- Validate beneficiary ID before applying state updates
- Cleanup on component unmount to prevent memory leaks
This fixes the issue where rapidly switching between beneficiaries
would show wrong data if slower requests completed after faster ones.
🤖 Generated with Claude Code (https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement proper cleanup of BLE scanning operations when users navigate
away from the add-sensor screen to prevent resource waste and potential
issues.
Changes:
- Add useFocusEffect hook to stop BLE scan when screen loses focus
- Remove unused imports (Device, WPDevice, connectDevice, etc.)
- Add comprehensive tests for BLE cleanup behavior
- Add tests for screen unmount/blur scenarios
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented a reusable useDebounce hook to prevent rapid-fire clicks
on refresh buttons throughout the application.
Changes:
- Created hooks/useDebounce.ts with configurable delay and leading/trailing edge options
- Added comprehensive unit tests in hooks/__tests__/useDebounce.test.ts
- Applied debouncing to dashboard WebView refresh button (app/(tabs)/dashboard.tsx)
- Applied debouncing to beneficiary detail pull-to-refresh (app/(tabs)/beneficiaries/[id]/index.tsx)
- Applied debouncing to equipment screen refresh (app/(tabs)/beneficiaries/[id]/equipment.tsx)
- Applied debouncing to all error retry buttons (components/ui/ErrorMessage.tsx)
- Fixed jest.setup.js to properly mock React Native modules
- Added implementation documentation in docs/DEBOUNCE_IMPLEMENTATION.md
Technical details:
- Default 1-second debounce delay
- Leading edge execution (immediate first call, then debounce)
- Type-safe with TypeScript generics
- Automatic cleanup on component unmount
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added error state with retry functionality to equipment.tsx
- Display error message when sensor loading fails
- Provide "Try Again" button to retry loading
- Clear error on successful retry
- Added error state with retry functionality to subscription.tsx
- Display error message when beneficiary loading fails
- Provide "Try Again" button with icon to retry loading
- Show offline icon and proper error layout
- Added comprehensive tests for error handling
- ErrorMessage component tests for inline errors
- FullScreenError component tests
- Equipment screen error state tests
- Subscription screen error state tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented cache-busting mechanism to prevent stale avatar images
after upload. React Native Image component caches images by URI,
causing old avatars to persist even after successful upload.
Changes:
- Added bustImageCache() utility function in utils/imageUtils.ts
- Appends timestamp query parameter (?t=timestamp) to avatar URLs
- Skips cache-busting for local file://, data: URIs and placeholders
- Applied bustImageCache() to all avatar Image components:
- Beneficiary detail screen (header, edit modal, lightbox)
- Beneficiary list cards on dashboard
- Ensured loadBeneficiary() is called after avatar upload completes
- Added comprehensive unit tests for cache-busting logic
Backend already generates unique URLs with timestamps when uploading
to MinIO, but this ensures frontend always requests fresh images.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create wifiPasswordStore service for encrypted password storage
- Replace AsyncStorage with SecureStore for WiFi credentials
- Add automatic migration from AsyncStorage to SecureStore
- Integrate WiFi password cleanup into logout process
- Add comprehensive test suite for password storage operations
- Update setup-wifi screen to use secure storage
Security improvements:
- WiFi passwords now stored encrypted via expo-secure-store
- Passwords automatically cleared on user logout
- Seamless migration for existing users
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add build number/timestamp display on login screen
- Improve error message when beneficiary has no deployment (user-friendly text instead of crash)
- Fix verify-otp screen layout for Android (smaller spacing, icon sizes)
- Add KeyboardAvoidingView to setup-wifi screen
- Save WiFi passwords per SSID (auto-fill on reconnect)
- Suppress BLE "operation cancelled" noise in logs
- Add build-info generation script (npm run build-info)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
BLE Fix:
- Check if sensor is already connected to target WiFi before sending credentials
- Handle W|fail when sensor uses saved credentials instead of new password
- Return success if sensor is connected to target network even after W|fail
Build Version Indicator:
- Add visible version badge on Dashboard screen (v2.1.0 • 2026-01-27 17:05)
- Green text on dark background in bottom-right corner
- Helps verify which build is running on device
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- setWiFi() now throws detailed errors instead of returning false
- Shows specific error messages: "WiFi credentials rejected", timeout etc.
- Added logging throughout BLE WiFi configuration flow
- Fixed WiFi network deduplication (keeps strongest signal)
- Ignore "Operation cancelled" error (normal cleanup behavior)
- BatchSetupProgress shows actual error in hint field
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add getLocationDisplay() helper to convert location ID (e.g., 'bedroom')
to human-readable format with icon (e.g., '🛏️ Bedroom') using ROOM_LOCATIONS.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace free-text Location input with modal Picker selector
- Use ROOM_LOCATIONS constants for predefined room options
- Show icon and label for each location option
- Highlight currently selected location in picker
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add displayName field to Beneficiary type (computed: customName || name)
- Populate displayName in getAllBeneficiaries and getWellNuoBeneficiary API calls
- Update detail page header to use beneficiary.displayName
- Update MockDashboard to use displayName
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add displayName (customName || name) to BeneficiaryCard component
- Update header and MockDashboard to show customName when set
- Add custom name editing for non-custodian users (guardian/caretaker)
- Backend PATCH endpoint now supports customName updates via user_access table
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update WellNuoLite submodule with Julia AI race condition fix
- Add ultravoxService for voice call handling
- Update voice.tsx with improved call flow
- Update equipment tracking in beneficiary details
- Clean up old data files
- Add react-native-base64 type definitions
- Add debug tools
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add updateDeviceMetadata and attachDeviceToDeployment API methods
- Device Settings: editable location/description fields with save
- Equipment screen: location placeholder and quick navigation to settings
- Add Sensor: multi-select with checkboxes, select all/deselect all
- Setup WiFi: batch processing of multiple sensors sequentially
- BatchSetupProgress: animated progress bar, step indicators, auto-scroll
- SetupResultsScreen: success/failed/skipped summary with retry options
- Error handling: modal with Retry/Skip/Cancel All buttons
- Documentation: SENSORS_SYSTEM.md with full BLE protocol and flows
Implemented via Ralphy CLI autonomous agent in ~43 minutes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added TouchableOpacity wrapper around the location text in the equipment
list so users can tap on a sensor's location to go directly to its
Device Settings screen.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added handleRetryFromResults function to retry setup for a single sensor
- Added Retry button next to each failed/skipped sensor in the results list
- When clicked, resets sensor state and returns to batch setup phase
- Added new styles: resultItemWithAction, resultItemLeft, retryItemButton
TASK-6.2: Add results screen after batch setup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add sensor index badge (1/5, 2/5...) on each card
- Add elapsed time display for processing sensors
- Add auto-scroll to current active sensor
- Add animated progress bar with success/error segments
- Add stats row showing success/error/skipped counts
- Improve visual feedback during batch WiFi setup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- add-sensor.tsx now passes devices array with mac address via JSON
- setup-wifi.tsx parses devices from navigation params
- Support batch mode display (shows count and device names)
- Disconnect all devices when navigating back
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Display "No location set" in italic style when sensor has no location configured.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Features:
- Device metadata display (name, MAC, location, description)
- Edit device name and description
- Update WiFi credentials (reconnect flow)
- Remove device from beneficiary
- Device history and diagnostics
UI:
- Clean settings form with validation
- Delete confirmation dialog
- Success/error feedback
- Navigation back to equipment list on changes
Route: /(tabs)/beneficiaries/[id]/device-settings/[deviceId]
Sensor onboarding screens:
- add-sensor.tsx: BLE scanning + device selection
- setup-wifi.tsx: WiFi credentials + ESP32 provisioning
Flow:
1. Scan for nearby sensors via BLE
2. Select device from list
3. Enter WiFi credentials (SSID + password)
4. Send config over BLE using ESP IDF provisioning protocol
5. Verify connection and activate in backend
ESP Provisioning:
- services/espProvisioning.ts: ESP32 BLE provisioning implementation
- Protocol: custom-data exchange via BLE characteristics
- Security: WiFi password encrypted over BLE
- Timeout handling: 30s for provisioning, 60s for activation
User experience:
- Clear step-by-step wizard UI
- Loading states for BLE operations
- Success/error feedback
- Navigation to equipment screen on success
Implemented three-tier sensor status (online/warning/offline) with visual indicators and BLE scanning for nearby devices.
Features:
- WPSensor type with status field (online/warning/offline)
- Automatic status calculation based on lastSeen time:
• Online: < 5 minutes (fresh data)
• Warning: 5 min - 1 hour (potential issue)
• Offline: > 1 hour (definitely problem)
- Dual sensor display: Connected (API) + Available Nearby (BLE)
- BLE scanning button for discovering nearby WP sensors
- Action Sheet for offline sensors with Reconnect/Remove options
- Updated summary card: Total/Online/Warning/Offline counts
- Visual status indicators: colored dots and labels
- Graceful error handling for API unavailability
Files changed:
- types/index.ts: Added WPSensor interface with status and source fields
- services/api.ts: Updated getDevicesForBeneficiary with status calculation
- equipment.tsx: Complete UI overhaul with BLE scanning and two-tier sensor list
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- BeneficiaryMenu: Navigate with ?edit=true param to open edit modal
- Beneficiary index: Auto-open edit modal when edit=true in URL
- Add loading indicator on Save button during edit save
- Add "Uploading..." overlay on avatar during image upload
The main Beneficiaries tab is actually "index" not "beneficiaries".
/(tabs) routes to index which shows the beneficiaries list.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added isNavigatingAway state to block auto-redirects when user clicks back
- Both header back button and main button now set this flag before navigating
- Prevents loadBeneficiary from triggering competing redirects
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Monitoring badge: equipment active + subscription active
- Get kit badge: user hasn't ordered equipment yet
- Equipment status badges: ordered, shipped, delivered
- No subscription warning when equipment works but no sub
- Stripe subscription caching in backend (hourly sync)
- BeneficiaryMenu with edit/share/archive/delete actions
TouchableOpacity inside ScrollView sometimes doesn't respond.
Pressable is more reliable.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Changed router.replace to router.push for better navigation
- Both header back button and main button now go to beneficiaries list
- Added console.log for debugging
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Make "Back to My Loved Ones" the primary action (blue button)
- Make "I received my kit" secondary/subtle (gray, smaller)
- Prevents accidental confirmation of kit receipt
- Users can easily return to beneficiary list
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added role field to Beneficiary type
- Display role (Custodian/Guardian/Caretaker) in small gray text under name
- Role comes from user_access table via API
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Redirects should only happen on the main beneficiary page (index.tsx).
Other pages (subscription, equipment, share) just show their content
without redirecting - user navigated there intentionally via menu.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add legacy dashboard API methods (eluxnetworks.net)
- Implement JWT token validation before using cached credentials
- Clear invalid tokens (non-JWT strings like "0") and force re-login
- Use correct credentials (anandk/anandk_8)
- Add 30-minute token refresh interval when WebView is active
- Fix avatar upload using expo-file-system instead of FileReader
- Handle address field as both string and object
- Created reusable BeneficiaryMenu component with Modal backdrop
- Menu closes on outside tap (proper Modal + Pressable implementation)
- Removed debug panel from subscription and beneficiary detail pages
- Fixed subscription creation and equipment status handling
- Backend improvements for Stripe integration
Database:
- Simplified beneficiary schema: single `name` field instead of first_name/last_name
- Single `address` field instead of 5 separate address columns
- Added migration 008_update_notification_settings.sql
Backend:
- Updated all beneficiaries routes for new schema
- Fixed admin routes for simplified fields
- Updated notification settings routes
- Improved stripe and webhook handlers
Frontend:
- Updated all forms to use single name/address fields
- Added new equipment-status and purchase screens
- Added BeneficiaryDetailController service
- Added subscription service
- Improved navigation and auth flow
- Various UI improvements
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>