- Add overdueCount field to ResidenceResponse model
- ResidenceCard shows PulsingIconView when residence has overdue tasks
- SummaryCard uses static CaseraIconView (never pulses)
- APILayer refreshes residence data after task completion to update
overdue counts and animation state
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Allow users to customize when they receive notification reminders:
- Add hour fields to NotificationPreference model
- Add timezone conversion utilities (localHourToUtc, utcHourToLocal)
- Add time picker UI for iOS (wheel picker in sheet)
- Add time picker UI for Android (hour chip selector dialog)
- Times stored in UTC, displayed in user's local timezone
- Add localized strings for time picker UI
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add SharedResidence model and package type detection for .casera files
- Add generateSharePackage API endpoint integration
- Create ResidenceSharingManager for iOS and Android
- Add share button to residence detail screens (owner only)
- Add residence import handling with confirmation dialogs
- Update Quick Look extensions to show house icon for residence packages
- Route .casera imports by type (contractor vs residence)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- DataManager now persists lookup data (residence types, task categories,
priorities, statuses, specialties, templates) to disk
- Loads cached lookups on app startup for faster launch
- iOS: Refresh lookups when app becomes active, refresh widget on background
- Android: Initialize DataManager in onCreate, already had onResume refresh
- Only send ETag if lookup data is actually in memory to avoid 304 with no data
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add LOGGING_IN step to PasswordResetStep enum on both platforms
- Auto-login with new credentials after successful password reset
- Navigate directly to main app (or verification screen if unverified)
- Show "Logging in..." state during auto-login process
- Hide back button during auto-login to prevent interruption
- Fall back to "Return to Login" if auto-login fails
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Contractor Sharing:
- Add .casera file format for sharing contractors between users
- Create SharedContractor model with JSON serialization
- Implement ContractorSharingManager for iOS (Swift) and Android (Kotlin)
- Register .casera file type in iOS Info.plist and Android manifest
- Add share button to ContractorDetailView (iOS) and ContractorDetailScreen (Android)
- Add import confirmation, success, and error dialogs
- Create expect/actual platform implementations for sharing and import handling
Navigation Changes:
- Remove Profile tab from bottom tab bar (iOS and Android)
- Add settings gear icon to left side of "My Properties" title
- Settings gear opens Profile/Settings screen as sheet (iOS) or navigates (Android)
- Add property button to top right action bar
Bug Fixes:
- Fix ResidenceUsersResponse to match API's flat array response format
- Fix GenerateShareCodeResponse handling to access nested shareCode property
- Update ManageUsersDialog to accept residenceOwnerId parameter
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
iOS:
- Add notification categories with action buttons (complete, view, cancel, etc.)
- Handle notification actions in AppDelegate with API calls
- Add navigation to specific task from notification tap
- Register UNNotificationCategory for each task state
Android:
- Add NotificationActionReceiver BroadcastReceiver for handling actions
- Update MyFirebaseMessagingService to show action buttons
- Add deep link handling in MainActivity for task navigation
- Register receiver in AndroidManifest.xml
Shared:
- Add navigateToTaskId parameter to App for cross-platform navigation
- Add notification observers in MainTabView/AllTasksView for refresh
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add TaskTemplate model with category grouping support
- Add TaskTemplateApi for fetching templates from backend
- Add TaskSuggestionDropdown component for Android task form
- Add TaskTemplatesBrowserSheet for browsing all templates
- Add TaskSuggestionsView and TaskTemplatesBrowserView for iOS
- Update DataManager to cache task templates
- Update APILayer with template fetch and search methods
- Update TaskFormView (iOS) with template suggestions
- Update AddTaskDialog (Android) with template suggestions
- Update onboarding task view to use templates
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add emailTaskCompleted field to NotificationPreference model
- Add email preference toggle to notification settings UI (iOS & Android)
- Add localized strings for email notifications section
- Update ViewModel to support email preference updates
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Suite0_OnboardingTests with fresh install and login test flows
- Add accessibility identifiers to onboarding views for UI testing
- Remove deprecated DataCache in favor of unified DataManager
- Update API layer to support public upgrade-triggers endpoint
- Improve onboarding first task view with better date handling
- Update various views with accessibility identifiers for testing
- Fix subscription feature comparison view layout
- Update document detail view improvements
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement complete onboarding experience for Android with the following screens:
- Welcome screen with "Start Fresh" and "Join Existing Home" options
- Value props carousel showcasing app features (Tasks, Documents, Contractors, Family)
- Residence naming screen for new property setup
- Account creation with email registration (no Apple Sign In on Android)
- Email verification with 6-digit code
- Join residence screen for share code entry
- First task selection with 6 category templates
- Subscription upsell with monthly/yearly plans
Key implementation details:
- OnboardingViewModel manages all state and API integration
- AnimatedContent provides smooth screen transitions
- HorizontalPager for feature carousel
- Onboarding completion persisted in DataManager
- New users start at onboarding, returning users go to login
Files added:
- OnboardingViewModel.kt
- OnboardingScreen.kt (coordinator)
- OnboardingWelcomeContent.kt
- OnboardingValuePropsContent.kt
- OnboardingNameResidenceContent.kt
- OnboardingCreateAccountContent.kt
- OnboardingVerifyEmailContent.kt
- OnboardingJoinResidenceContent.kt
- OnboardingFirstTaskContent.kt
- OnboardingSubscriptionContent.kt
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add configurable cache timeout (CACHE_TIMEOUT_MS) to DataManager
- Fix cache to work with empty results (contractors, documents, residences)
- Change Documents/Warranties view to use client-side filtering for cache efficiency
- Add pull-to-refresh support for empty state views in ListAsyncContentView
- Fix ContractorsListView to pass forceRefresh parameter correctly
- Fix TaskViewModel loading spinner not stopping after refresh completes
- Remove duplicate cache checks in iOS ViewModels, delegate to Kotlin APILayer
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create DataManager.kt with StateFlows for all cached data:
- Authentication (token, user)
- Residences, tasks, documents, contractors
- Subscription status and upgrade triggers
- All lookup data (residence types, task categories, etc.)
- Theme preferences and state metadata
- Add PersistenceManager with platform-specific implementations:
- Android: SharedPreferences
- iOS: NSUserDefaults
- JVM: Properties file
- WasmJS: localStorage
- Migrate APILayer to update DataManager on every API response
- Update Kotlin ViewModels to use DataManager for token access
- Deprecate LookupsRepository (delegates to DataManager)
- Create iOS DataManagerObservable Swift wrapper for SwiftUI
- Update iOS auth flow to use DataManager.isAuthenticated()
Data flow: User Action → API Call → DataManager Updated → All Screens React
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add updatedTask field to TaskCompletionResponse model from API
- Modify CompleteTaskView callback to pass back the updated task
- Add updateTaskInKanban() function to AllTasksView and ResidenceDetailView
- Move completed tasks to correct kanban column without additional API call
- Remove debug print statements from ResidenceDetailView
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
iOS:
- Add AuthenticatedImage.swift component with auth header support
- Update PhotoViewerSheet, ImageViewerSheet, DocumentDetailView, DocumentFormView
- Use TokenStorage for auth and ApiClient.getMediaBaseUrl() for URLs
- In-memory image caching for performance
Android/KMM:
- Add AuthenticatedImage.kt Compose component using Coil3 httpHeaders
- Add mediaUrl field to TaskCompletionImage and DocumentImage models
- Update PhotoViewerDialog, DocumentDetailScreen, DocumentFormScreen
- Use authenticated media URLs instead of public image URLs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
KMM (Android/Shared):
- Add strings.xml with 200+ localized strings
- Add translation files for es, fr, de, pt languages
- Update all screens to use stringResource() for i18n
- Add Accept-Language header to API client for all platforms
iOS:
- Add L10n.swift helper with type-safe string accessors
- Add Localizable.xcstrings with translations for all 5 languages
- Update all SwiftUI views to use L10n.* for localized strings
- Localize Auth, Residence, Task, Contractor, Document, and Profile views
Supported languages: English, Spanish, French, German, Portuguese
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add centralized formatWidgetDate() helper that handles both yyyy-MM-dd and ISO8601 formats
- Update widget date display to show "Today", "in X days", or "X days ago"
- Fix isTaskOverdue() to parse ISO8601 dates from Go API
- Remove duplicate date formatting functions from widget views
- Switch API environment back to DEV
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add DateUtils.kt for shared Kotlin date formatting with formatDate,
formatDateMedium, formatDateTime, formatRelativeDate, and isOverdue
- Add DateUtils.swift for iOS with matching date formatting functions
- Enhance ContractorDetailScreen (Android) with quick action buttons
(call, email, website, directions), clickable contact rows, residence
association, statistics section, and metadata
- Enhance ContractorDetailView (iOS) with same features, refactored into
smaller @ViewBuilder functions to fix Swift compiler type-check timeout
- Fix empty string handling in iOS - check !isEmpty in addition to != nil
for optional fields like phone, email, website, address
- Update various task and document views to use centralized DateUtils
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Kotlin/KMM:
- Update Contractor model with optional residenceId and specialties array
- Rename averageRating to rating, update address field names
- Add ContractorMinimal model for task references
- Add residence picker and multi-select specialty chips to AddContractorDialog
- Fix ContractorsScreen and ContractorDetailScreen field references
iOS:
- Rewrite ContractorFormSheet with residence and specialty pickers
- Update ContractorDetailView with FlowLayout for specialties
- Add FlowLayout component for wrapping badge layouts
- Fix ContractorCard and CompleteTaskView field references
- Update ContractorFormState with residence/specialty selection
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add NotificationPreferencesScreen (Android) and NotificationPreferencesView (iOS)
- Add NotificationPreferencesViewModel for shared business logic
- Wire up notification preferences from ProfileScreen on both platforms
- Add subscription verification on app launch for iOS (StoreKit) and Android (Google Play Billing)
- Update SubscriptionApi to match Go backend endpoints (/subscription/purchase/)
- Update StoreKit Configuration with correct product IDs and pricing ($2.99/month, $27.99/year)
- Update Android placeholder prices to match App Store pricing
- Fix NotificationPreference model to match Go backend schema
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Kotlin Shared Layer:
- Add AppleSignInRequest and AppleSignInResponse models
- Add appleSignIn method to AuthApi and APILayer
- Add appleSignInState and appleSignIn() to AuthViewModel
iOS App:
- Create AppleSignInManager for AuthenticationServices integration
- Create AppleSignInViewModel to coordinate Apple auth flow
- Update LoginView with "Sign in with Apple" button
- Add Sign in with Apple entitlement
- Add accessibility identifier for UI testing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Rename Kotlin package from com.example.mycrib to com.example.casera
- Update Android app name, namespace, and application ID
- Update iOS bundle identifiers and project settings
- Rename iOS directories (MyCribTests -> CaseraTests, etc.)
- Update deep link schemes from mycrib:// to casera://
- Update app group identifiers
- Update subscription product IDs
- Update all UI strings and branding
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Change residence to residence_id with @SerialName annotation
- Change contractor to contractor_id with @SerialName annotation
- Update DocumentApi.kt to use correct field names in form data and JSON requests
- Fixes iOS document creation failing with "missing residence_id" error
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add CompletionHistorySheet for viewing task completion history (Android & iOS)
- Update TaskCard and DynamicTaskCard with completion history access
- Add getTaskCompletions API endpoint to TaskApi and APILayer
- Update models (CustomTask, Document, TaskCompletion, User) for Go API alignment
- Improve TaskKanbanView with completion history integration
- Update iOS TaskViewModel with completion history loading
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update all Kotlin API models to match Go API response structures
- Fix Swift type aliases (TaskDetail→TaskResponse, Residence→ResidenceResponse, etc.)
- Update TaskCompletionCreateRequest to simplified Go API format (taskId, notes, actualCost, photoUrl)
- Fix optional handling for frequency, priority, category, status in task models
- Replace isPrimaryOwner with ownerId comparison against current user
- Update ResidenceUsersResponse to use owner.id instead of ownerId
- Fix non-optional String fields to use isEmpty checks instead of optional binding
- Add type aliases for backwards compatibility in Kotlin models
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Load subscription status and upgrade triggers during Android app
initialization in LookupsRepository.initialize(). Previously, only
iOS was loading this data via APILayer.initializeLookups().
Without subscription data, SubscriptionHelper couldn't enforce limits
because SubscriptionCache.currentSubscription was always null.
Changes:
- Add SubscriptionApi calls to load subscription status and upgrade
triggers in parallel with other lookup data
- Clear SubscriptionCache on logout in clear() method
- Add debug logging for subscription loading
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- Make currentTier a computed property from StoreKit instead of stored value
- Initialize StoreKit at app launch and refresh on foreground for ready subscription status
- Fix empty state logic: show empty state when limit > 0, upgrade prompt when limit = 0
- Add subscription status display in Profile screen (iOS/Android)
- Add upgrade prompts to Residences and Tasks screens for free tier users
- Improve SubscriptionHelper with better tier checking logic
iOS:
- SubscriptionCache: currentTier now computed from StoreKit.purchasedProductIDs
- StoreKitManager: add refreshSubscriptionStatus() method
- AppDelegate: initialize StoreKit at launch and refresh on app active
- ContractorsListView: use shouldShowUpgradePrompt(currentCount:limitKey:)
- WarrantiesTabContent/DocumentsTabContent: same empty state fix
- ProfileTabView: display current tier and limitations status
- ResidencesListView/ResidenceDetailView: add upgrade prompts for free users
- AllTasksView: add upgrade prompt for free users
Android:
- ContractorsScreen/DocumentsScreen: fix empty state logic
- ProfileScreen: display subscription status and limits
- ResidencesScreen/ResidenceDetailScreen: add upgrade prompts
- UpgradeFeatureScreen: improve UI layout
Shared:
- APILayer: add getSubscriptionStatus() method
- SubscriptionHelper: add hasAccessToFeature() utility
- Remove duplicate subscription checking logic
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed unresolved references by matching the standard API client pattern:
- Changed from apiCall helper to try-catch pattern
- Use ApiClient.httpClient instead of direct httpClient reference
- Use ApiClient.getBaseUrl() instead of ApiConfig.baseUrl
- Added proper HttpClient parameter with default value
- Added proper error handling with response status checks
- Fixed verifyIOSReceipt to include transactionId parameter
- Fixed Android verification request format (use map instead of data class)
Now matches the pattern used by other API classes (ResidenceApi, TaskApi, etc.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented Android subscription UI components:
- UpgradeFeatureScreen: Full-screen view for restricted features (contractors, documents)
* Shows feature icon, name, and description
* Displays "This feature is available with Pro" badge
* Opens UpgradePromptDialog on button click
- UpgradePromptDialog: Modal dialog with upgrade options
* Trigger-specific title and message from backend
* Feature preview list with Material icons
* "Upgrade to Pro" button with loading state
* "Compare Free vs Pro" button
* "Maybe Later" cancel option
- FeatureComparisonDialog: Full-screen comparison table
* Free vs Pro feature comparison
* Displays data from SubscriptionCache.featureBenefits
* Default features if no data loaded
* Upgrade button
- BillingManager: Google Play Billing Library placeholder
* Singleton manager for in-app purchases
* Product query placeholder
* Purchase flow placeholder
* Backend receipt verification placeholder
* Restore purchases placeholder
All components follow Material3 design system with theme-aware colors and spacing constants.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Client-Side Changes:
- Add WarrantyStatus data class to Document model for backend-calculated status
- Update WarrantyCard to display backend status (statusText, statusColor) with client fallback
- Fix document list refresh: call loadDocuments() after create/update operations
Testing:
- Add ComprehensiveDocumentWarrantyTests with 25+ XCUITest cases
- Test document creation, update, delete, image upload
- Test warranty-specific fields and property selection
- Test both general documents and warranties
- Includes helper methods for form interaction and cleanup
Other:
- Update ApiConfig and PushNotificationManager
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit adds persistent theme storage and comprehensive documentation for Android development.
Theme Persistence:
- Created ThemeStorage with platform-specific implementations (SharedPreferences/UserDefaults)
- Updated ThemeManager.initialize() to load saved theme on app start
- Integrated ThemeStorage initialization in MainActivity and MainViewController
- Theme selection now persists across app restarts
Documentation (CLAUDE.md):
- Added comprehensive Android Design System section
- Documented all 11 themes and theme management
- Provided color system guidelines (use MaterialTheme.colorScheme)
- Documented spacing system (AppSpacing/AppRadius constants)
- Added standard component usage examples (StandardCard, FormTextField, etc.)
- Included screen patterns (Scaffold, pull-to-refresh, lists)
- Provided button and dialog patterns
- Listed key design principles for Android development
Build Status:
- ✅ Android builds successfully
- ✅ iOS builds successfully
- ✅ Theme persistence works on both platforms
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit adds a comprehensive theming system to Android matching iOS, and fixes package declarations throughout the codebase to match directory structure.
Theme System Additions:
- Added 11 themes matching iOS: Default, Teal, Ocean, Forest, Sunset, Monochrome, Lavender, Crimson, Midnight, Desert, Mint
- Created ThemeColors.kt with exact iOS color values for light/dark modes
- Added ThemeManager.kt for dynamic theme switching
- Created Spacing.kt with standardized spacing constants (xs/sm/md/lg/xl)
- Added ThemePickerDialog.kt for theme selection UI
- Integrated theme switching in ProfileScreen.kt
- Updated App.kt to observe ThemeManager for reactive theming
Component Library:
- Added StandardCard.kt and CompactCard.kt for consistent card styling
- Added FormTextField.kt with error/helper text support
- Added FormSection.kt for grouping related form fields
- Added StandardEmptyState.kt for empty state UI
Package Migration:
- Fixed all package declarations to match directory structure (com.example.mycrib.*)
- Updated package declarations in commonMain, androidMain, and iosMain
- Fixed all import statements across entire codebase
- Ensures compilation on both Android and iOS platforms
iOS Theme Rename:
- Renamed "Default" theme to "Teal" in iOS
- Renamed "Bright" theme to "Default" in iOS to make vibrant colors the default
Build Status:
- ✅ Android builds successfully
- ✅ iOS builds successfully
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove pagination from all Django REST Framework endpoints
- Update Kotlin API clients to return direct lists instead of paginated responses
- Update iOS ViewModels to handle direct list responses
- Remove ContractorListResponse, DocumentListResponse, and PaginatedResponse models
- Fix contractor form specialty selector loading with improved DataCache access
- Fix contractor sheet presentation to use full screen (.presentationDetents([.large]))
- Improve UI test scrolling to handle lists of any size with smart end detection
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated contractor models and forms to make phone field optional. Added
accessibility identifiers for add buttons to enable UI testing.
Contractor changes:
- Kotlin: Made phone nullable in Contractor, ContractorCreateRequest,
ContractorSummary models
- Android: Updated AddContractorDialog validation to only require name
- Android: Removed asterisk from phone field label
- Android: Updated ContractorDetailScreen to handle nullable phone
- iOS: Updated ContractorFormSheet validation to only check name field
- iOS: Updated form footer text to show only name as required
- iOS: Updated ContractorDetailView to use optional binding for phone display
Accessibility improvements:
- iOS: Added accessibility identifier to contractor add button in
ContractorsListView
- iOS: Added accessibility identifier to task add button in
ResidenceDetailView
These identifiers enable reliable UI testing by allowing tests to access
buttons by their accessibility identifiers instead of searching by label.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated Kotlin models, Android UI, and iOS UI to make all address fields
optional for residences. Only the residence name is now required.
Changes:
- Kotlin: Made propertyType, streetAddress, city, stateProvince, postalCode,
country nullable in Residence, ResidenceSummary, ResidenceWithTasks models
- Kotlin: Updated navigation routes to handle nullable address fields
- Android: Updated ResidenceFormScreen and ResidenceDetailScreen to handle nulls
- iOS: Updated ResidenceFormView validation to only check name field
- iOS: Updated PropertyHeaderCard and ResidenceCard to use optional binding
for address field displays
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed issue where adding or editing a residence didn't update the residence
list, requiring manual refresh to see changes.
iOS Changes:
- ResidencesListView: Added onResidenceCreated callback to AddResidenceView
sheet that triggers loadMyResidences(forceRefresh: true)
- AddResidenceView: Added onResidenceCreated callback parameter
- ResidenceFormView: Added onSuccess callback that fires before dismissing
in both create and update modes
Android Changes:
- ResidencesScreen: Added shouldRefresh parameter with LaunchedEffect that
watches for changes and reloads residences when flag is true
- App.kt (ResidencesRoute): Read "refresh" flag from saved state handle
- App.kt (AddResidenceRoute): Set "refresh" flag in previous back stack
entry before navigating back on residence created
- App.kt (EditResidenceRoute): Set "refresh" flag before navigating back
on residence updated
Both platforms now properly refresh the residence list when:
- A new residence is added
- An existing residence is edited
- User joins a residence with code (already working)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Model type updates:
- Change decimal cost fields from String to Double for better type safety
- actualCost: String? → Double? (TaskCompletion, TaskCompletionCreateRequest)
- estimatedCost: String? → Double? (CustomTask, TaskCreateRequest, TaskDetail)
- purchasePrice: String? → Double? (Residence, ResidenceCreateRequest)
TaskDetail model fixes:
- Add missing residenceName, createdBy, createdByUsername fields
- Add missing intervalDays field to match backend response
- Remove actualCost and notes fields (not in backend TaskDetailSerializer)
- Ensure 100% compatibility with Django API TaskDetailSerializer
UI input/output conversions:
- EditTaskScreen: Convert Double to String for display, String to Double for API
- AddTaskDialog: Convert String input to Double for API requests
- CompleteTaskDialog: Convert String input to Double for API requests
- App.kt: Handle type conversions in navigation route parameters
Display improvements:
- TaskCard: Update preview data to use numeric literals (150.00 vs "150.00")
- Cost display already handles Double correctly with string interpolation
Benefits:
- Type-safe numeric handling throughout the app
- Smaller JSON payloads (numbers vs quoted strings)
- Better performance with direct numeric deserialization
- Aligns with REST API best practices
- 100% backend compatibility verified
Testing:
- All models now match backend serializer field types exactly
- Build successful with no errors
- Ready for integration with optimized Django API
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added comprehensive usage documentation for dynamic task summary components
and updated TaskApi to rely on backend's default threshold value.
**Changes:**
**New: TASK_SUMMARY_USAGE.md**
- Complete Android usage guide for TaskSummaryCard component
- Examples of basic usage, filtering categories, and customization
- Documents all available categories and their metadata
- Shows how to use dynamic task summary in different screens
**New: iosApp/TASK_SUMMARY_USAGE_IOS.md**
- Complete iOS usage guide for TaskSummaryCard SwiftUI component
- Examples for ResidenceDetailView, ResidenceCard, and HomeScreen
- Documents SF Symbol icon usage and color parsing
- Integration examples and troubleshooting tips
**New: TaskConstants.kt**
- Created client-side constants file (currently unused)
- Contains TASK_CURRENT_THRESHOLD_DAYS = 29
- Available for future use if client needs local threshold
**Updated: TaskApi.kt**
- Changed days parameter from `days: Int = 30` to `days: Int? = null`
- Now only sends days parameter to backend if explicitly provided
- Allows backend's default threshold (29 days) to be used
- Applied to both getTasks() and getTasksByResidence()
**Updated: ApiConfig.kt**
- Minor configuration update
**Benefits:**
✅ Comprehensive documentation for both platforms
✅ Apps now use backend's default threshold value
✅ Cleaner API calls without unnecessary parameters
✅ Client can still override threshold if needed
✅ Documentation includes troubleshooting and best practices
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated both iOS and Android to build residence task summary UI entirely
from API response data, with no hardcoded categories, icons, colors, or labels.
**Changes:**
**Backend Integration:**
- Updated TaskSummary model to use dynamic categories list instead of static fields
- Added TaskColumnCategory and TaskColumnIcon models for metadata
- Categories now include: name, displayName, icons (ios/android/web), color, count
**Android (ResidencesScreen.kt):**
- Removed hardcoded category extraction (overdue_tasks, current_tasks, in_progress_tasks)
- Now dynamically iterates over first 3 categories from API
- Added getIconForCategory() helper to map icon names to Material Icons
- Added parseHexColor() helper that works in commonMain (no Android-specific code)
- Uses category.displayName, category.icons.android, category.color from API
**iOS (ResidenceCard.swift):**
- Removed hardcoded category extraction and SF Symbol names
- Now dynamically iterates over first 3 categories using ForEach
- Uses category.displayName, category.icons.ios, category.color from API
- Leverages existing Color(hex:) extension for color parsing
**Component Organization:**
- Moved TaskSummaryCard.kt from commonMain to androidMain (uses Android-specific APIs)
- Created TaskSummaryCard.swift for iOS with dynamic category rendering
**Benefits:**
✅ Backend controls all category metadata (icons, colors, display names)
✅ Apps automatically reflect backend changes without redeployment
✅ No platform-specific hardcoded values
✅ Single source of truth in task/constants.py TASK_COLUMNS
**Files Changed:**
- Residence.kt: Added TaskColumnCategory, TaskColumnIcon models
- ResidencesScreen.kt: Dynamic category rendering with helpers
- ResidenceCard.swift: Dynamic category rendering with ForEach
- TaskSummaryCard.kt: Moved to androidMain
- TaskSummaryCard.swift: New iOS dynamic component
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Created ErrorMessageParser utility for both iOS (Swift) and Android (Kotlin)
- Parser detects JSON-formatted error messages and extracts user-friendly text
- Identifies when data objects (not errors) are returned and provides generic messages
- Updated all API error handling to pass raw error bodies instead of concatenating
- Applied ErrorMessageParser across all ViewModels and screens on both platforms
- Fixed ContractorApi and DocumentApi to not concatenate error bodies with messages
- Updated ApiResultHandler to automatically parse all error messages
- Error messages now show "Request failed. Please check your input and try again." instead of raw JSON
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Applied the new error handling utilities to ResidencesScreen and
ResidenceDetailScreen, replacing inline error displays with popup dialogs.
Changes:
- ResidencesScreen: Replaced inline error UI with ApiResultHandler
- Shows error dialog popup instead of error message in center of screen
- Maintains all functionality while improving UX
- ResidenceDetailScreen: Comprehensive error handling implementation
- Main residence loading uses ApiResultHandler with custom loading content
- Generate report operation uses HandleErrors() extension
- Delete residence operation uses HandleErrors() extension
- All operations now show retry/cancel dialogs on error
Benefits:
- Consistent error handling UX across screens
- Users can retry failed operations without navigating away
- Cleaner code with less boilerplate error handling
- Error dialogs are non-blocking and dismissible
These screens now demonstrate the pattern for implementing error handling
across the rest of the app using the error handling utilities.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Created reusable error handling components that can be used across all
screens in both Android and iOS apps to show retry/cancel dialogs when
network calls fail.
Android Components:
- ApiResultHandler: Composable that automatically handles ApiResult states
with loading indicators and error dialogs
- HandleErrors(): Extension function for ApiResult to show error dialogs
for operations that don't return display data
- Updated ResidencesScreen to import ApiResultHandler
iOS Components:
- ViewStateHandler: SwiftUI view that handles loading/error/success states
with automatic error alerts
- handleErrors(): View modifier for automatic error monitoring
- Both use the existing ErrorAlertModifier for consistent alerts
Documentation:
- Created ERROR_HANDLING.md with comprehensive usage guide
- Includes examples for data loading and create/update/delete operations
- Migration guide for updating existing screens
- Best practices and testing guidelines
These utilities make it easy to add consistent error handling with retry
functionality to any screen that makes network calls, improving the user
experience across the entire app.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented user-friendly error handling for network call failures:
Android (Compose):
- Created reusable ErrorDialog component with retry and cancel buttons
- Updated TasksScreen to show error dialog popup instead of inline error
- Error dialog appears when network calls fail with option to retry
iOS (SwiftUI):
- Created ErrorAlertModifier and ErrorAlertInfo helpers
- Added .errorAlert() view modifier for consistent error handling
- Updated TaskFormView to show error alerts with retry/cancel options
- Error alerts appear when task creation or other network calls fail
Both platforms now provide a consistent user experience when network
errors occur, giving users the choice to retry the operation or cancel.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>