Remove summary from list responses, calculate client-side

- Remove summary field from MyResidencesResponse and TaskColumnsResponse
- Update HomeScreen and ResidencesScreen to observe DataManager.totalSummary
- Load tasks when residence views appear to ensure accurate summary
- Add pull-to-refresh for tasks on ResidencesScreen
- Update iOS views to use client-side calculated summary

Summary is now calculated via refreshSummaryFromKanban() from cached
kanban data. This ensures summary is always up-to-date after CRUD
operations and when residence views are shown.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-16 17:06:48 -06:00
parent 6dfc4ee57c
commit fbe45da9ff
8 changed files with 52 additions and 40 deletions

View File

@@ -93,10 +93,7 @@ final class WidgetActionProcessor {
let data = success.data {
// Update widget with fresh data
WidgetDataManager.shared.saveTasks(from: data)
// Update summary from response (no extra API call needed)
if let summary = data.summary {
DataManager.shared.setTotalSummary(summary: summary)
}
// Summary is calculated client-side by DataManager.setAllTasks() -> refreshSummaryFromKanban()
}
} catch {
print("WidgetActionProcessor: Error refreshing tasks: \(error)")

View File

@@ -3,12 +3,14 @@ import ComposeApp
struct ResidencesListView: View {
@StateObject private var viewModel = ResidenceViewModel()
@StateObject private var taskViewModel = TaskViewModel()
@State private var showingAddResidence = false
@State private var showingJoinResidence = false
@State private var showingUpgradePrompt = false
@State private var showingSettings = false
@StateObject private var authManager = AuthenticationManager.shared
@StateObject private var subscriptionCache = SubscriptionCacheWrapper.shared
@Environment(\.scenePhase) private var scenePhase
var body: some View {
ZStack {
@@ -22,7 +24,7 @@ struct ResidencesListView: View {
errorMessage: viewModel.errorMessage,
content: { residences in
ResidencesContent(
summary: viewModel.totalSummary ?? response.summary,
summary: viewModel.totalSummary ?? TotalSummary(totalResidences: Int32(residences.count), totalTasks: 0, totalOverdue: 0, totalDueSoon: 0, totalPending: 0, tasksDueNextWeek: 0, tasksDueNextMonth: 0),
residences: residences
)
},
@@ -114,19 +116,30 @@ struct ResidencesListView: View {
PostHogAnalytics.shared.screen(AnalyticsEvents.residenceScreenShown)
if authManager.isAuthenticated {
viewModel.loadMyResidences()
// Also load tasks to populate summary stats
taskViewModel.loadTasks()
}
}
.onChange(of: scenePhase) { newPhase in
// Refresh data when app comes back from background
if newPhase == .active && authManager.isAuthenticated {
viewModel.loadMyResidences(forceRefresh: true)
taskViewModel.loadTasks(forceRefresh: true)
}
}
.fullScreenCover(isPresented: $authManager.isAuthenticated.negated) {
LoginView(onLoginSuccess: {
authManager.isAuthenticated = true
viewModel.loadMyResidences()
taskViewModel.loadTasks()
})
.interactiveDismissDisabled()
}
.onChange(of: authManager.isAuthenticated) { isAuth in
if isAuth {
// User just logged in or registered - load their residences
// User just logged in or registered - load their residences and tasks
viewModel.loadMyResidences()
taskViewModel.loadTasks()
} else {
// User logged out - clear data
viewModel.myResidences = nil

View File

@@ -79,16 +79,13 @@ struct iOSApp: App {
if WidgetDataManager.shared.areTasksDirty() {
WidgetDataManager.shared.clearDirtyFlag()
Task {
// Refresh tasks - response includes summary for dashboard stats
// Refresh tasks - summary is calculated client-side from kanban data
let result = try? await APILayer.shared.getTasks(forceRefresh: true)
if let success = result as? ApiResultSuccess<TaskColumnsResponse>,
let data = success.data {
// Update widget cache
WidgetDataManager.shared.saveTasks(from: data)
// Update summary from response (no extra API call needed)
if let summary = data.summary {
DataManager.shared.setTotalSummary(summary: summary)
}
// Summary is calculated by DataManager.setAllTasks() -> refreshSummaryFromKanban()
}
}
}