Move tasksResponse state and updateTaskInKanban logic from individual views
into TaskViewModel. Both AllTasksView and ResidenceDetailView now delegate
to the shared ViewModel, reducing code duplication and ensuring consistent
task state management across the app.
🤖 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>
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>
- 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>
- Create WidgetDataManager to write task data as JSON to App Group shared container
- Update widget CacheManager to read from App Group file instead of UserDefaults
- Add LargeWidgetView for .systemLarge widget family showing 5-6 tasks
- Add widget data save in AllTasksView after tasks load successfully
- Clear widget cache on logout in AuthenticationManager
- Add residenceName and isOverdue fields to widget task model
🤖 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>
Apply consistent branding colors (BlueGreen, Cerulean, BrightAmber, PrimaryScarlet,
cream backgrounds) to all screens, components, buttons, icons, and text throughout
the app. Update all Form/List views with proper list row backgrounds to ensure
visual consistency with card-based layouts.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added AccessibilityIdentifiers helper struct with identifiers for all major
UI elements across the app. Applied identifiers throughout authentication,
navigation, forms, and feature screens to enable reliable UI testing.
Changes:
- Added Helpers/AccessibilityIdentifiers.swift with centralized ID definitions
- LoginView: Added identifiers for username, password, login button fields
- RegisterView: Added identifiers for registration form fields
- MainTabView: Added identifiers for all tab bar items
- ProfileTabView: Added identifiers for logout and settings buttons
- ResidencesListView: Added identifier for add button
- Task views: Added identifiers for add, save, and form fields
- Document forms: Added identifiers for form fields and buttons
Identifiers follow naming pattern: [Feature].[Element]
Example: AccessibilityIdentifiers.Authentication.loginButton
This enables UI tests to reliably locate elements using:
app.buttons[AccessibilityIdentifiers.Authentication.loginButton]
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
iOS:
- Add archive task confirmation to TaskActionButtons.swift
- Add archive task confirmation to AllTasksView.swift
- Add cancel and archive task confirmations to ResidenceDetailView.swift
- Fix generatePropertyReport call to use new method signature
Android:
- Add cancel task confirmation to ResidenceDetailScreen.kt
- Add archive task confirmation to ResidenceDetailScreen.kt
All destructive task actions (cancel, archive/delete) now require user confirmation with clear warning messages before proceeding.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replaced individual action buttons with a single Actions menu in DynamicTaskCard
- Organized menu items into sections (primary, secondary, destructive)
- Added visual dividers between action groups
- Blue button styling for better visibility
- Added debug logging for menu interactions
- Menu properly handles all action types (mark in progress, complete, edit, cancel, restore, archive, unarchive)
- Converted AllTasksView to use horizontal grid layout (LazyHGrid)
- Changed from vertical scroll to horizontal scroll
- Added paging behavior with scroll target alignment
- Added scroll transitions for smooth animations (fade and scale)
- Fixed width columns (350pt) for consistent sizing
- Maintained pull-to-refresh functionality
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added pull-to-refresh to ResidencesListView with force refresh support
- Added pull-to-refresh to AllTasksView with rotating refresh button
- Added pull-to-refresh to ContractorsListView with force refresh
- Added pull-to-refresh to DocumentsTabContent and WarrantiesTabContent
- Improved loading state checks to prevent empty list flash during initial load
- Added refresh button to AllTasksView toolbar with clockwise rotation animation
- Improved UX by disabling refresh button while loading is in progress
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major architectural improvements:
- Created APILayer as single entry point for all network operations
- Integrated cache-first reads with automatic cache updates on mutations
- Migrated all shared Kotlin ViewModels to use APILayer instead of direct API calls
- Migrated iOS ViewModels to wrap shared Kotlin ViewModels with StateFlow observation
- Replaced LookupsManager with DataCache for centralized lookup data management
- Added password reset methods to AuthViewModel
- Added task completion and update methods to APILayer
- Added residence user management methods to APILayer
iOS specific changes:
- Updated LoginViewModel, RegisterViewModel, ProfileViewModel to use shared AuthViewModel
- Updated ContractorViewModel, DocumentViewModel to use shared ViewModels
- Updated ResidenceViewModel to use shared ViewModel and APILayer
- Updated TaskViewModel to wrap shared ViewModel with callback-based interface
- Migrated PasswordResetViewModel and VerifyEmailViewModel to shared AuthViewModel
- Migrated AllTasksView, CompleteTaskView, EditTaskView to use APILayer
- Migrated ManageUsersView, ResidenceDetailView to use APILayer
- Migrated JoinResidenceView to use async/await pattern with APILayer
- Removed LookupsManager.swift in favor of DataCache
- Fixed PushNotificationManager @MainActor issue
- Converted all direct API calls to use async/await with proper error handling
Benefits:
- Reduced code duplication between iOS and Android
- Consistent error handling across platforms
- Automatic cache management for better performance
- Centralized network layer for easier testing and maintenance
- Net reduction of ~700 lines of code through shared logic
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit fixes the issue where ScrollView content at the bottom of screens was being hidden behind the tab bar.
## Changes
- Added .safeAreaInset(edge: .bottom) to all main tab ScrollViews
- Increased bottom padding to AppSpacing.xxxl (64pt) for better spacing
- Removed .ignoresSafeArea(edges: .bottom) from AllTasksView which was causing issues
## Files Updated
- ResidencesListView.swift: Fixed residences list scrolling
- AllTasksView.swift: Fixed task columns horizontal scrolling
- ContractorsListView.swift: Fixed contractors list scrolling
- WarrantiesTabContent.swift: Fixed warranties list scrolling
- DocumentsTabContent.swift: Fixed documents list scrolling
## Technical Details
The .safeAreaInset modifier ensures ScrollViews properly account for the tab bar by:
- Automatically adjusting content insets for safe areas
- Allowing content to scroll fully above the tab bar
- Preventing content from being obscured
All tab views now provide smooth, unobstructed scrolling experience.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed duplicate Color.init(hex:) extension from AllTasksView.swift as it's now defined in DesignSystem.swift.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add camera picker interface to common ImagePicker.kt
- Implement camera capture for Android using ActivityResultContracts.TakePicture
- Implement camera capture for iOS using UIImagePickerController
- Add camera picker stubs for wasmJs, jsMain, and jvmMain platforms
- Update CompleteTaskDialog to show both "Take Photo" and "Choose from Library" buttons
- Add camera permissions to Android manifest (CAMERA permission, camera intent queries)
- Configure Android FileProvider for camera photo sharing
- Add camera and photo library usage descriptions to iOS Info.plist
- Update iOS CompleteTaskView with native camera picker support
- Fix cancel button in CompleteTaskView using @Environment(\.dismiss)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add PhotoViewerDialog (Android) and PhotoViewerSheet (iOS) for viewing completion photos
- Add CompletionCardView (iOS) to display completion details with photo button
- Update AllTasksView (iOS) to show full completion details instead of just count
- Update TaskCard (Android) to use CompletionCard component
- Add Coil 3.0.4 image loading library for Android
- Configure ImageLoader in MainActivity with network, memory, and disk caching
- Add getMediaBaseUrl() to ApiClient for loading media files without /api path
- Fix photo viewer background color to match app theme
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
iOS Logout Fix:
- Use @EnvironmentObject in MainTabView and ProfileTabView
- Pass loginViewModel from LoginView to MainTabView
- Handle logout by dismissing main tab when isAuthenticated becomes false
- Logout button now properly returns user to login screen
Share Code UX:
- Clear share code on ManageUsers screen open (iOS & Android)
- Remove auto-loading of share codes
- User must explicitly generate code each time
- Improves security with fresh codes
Loading State Improvements:
- iOS ResidenceDetailView shows loading immediately on navigation
- Android ResidenceDetailScreen enhanced with "Loading residence..." text
- Better user feedback during API calls
Multi-User Support:
- Add isPrimaryOwner and userCount to ResidenceWithTasks model
- Update iOS toResidences() extension to include new fields
- Sync with backend API changes for shared user access
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>