@@ -14,8 +14,8 @@ final class ProfileViewModel: Store {
1414 var statusMessage : String = " "
1515 var avatarURL : URL ?
1616 var selectedQuarterStart : Date ?
17- var completionQuarterCache : [ Date : ProfileCompletionQuarter ] = [ : ]
18- var quarterTodosCache : [ Date : [ Todo ] ] = [ : ]
17+ var completionQuarter : ProfileCompletionQuarter ?
18+ var dayActivitiesByDate : [ Date : [ ProfileSelectedDayActivity ] ] = [ : ]
1919 var selectedActivityTypes : Set < ProfileActivityType > = [ . created, . completed]
2020 var selectedDay : ProfileCompletionDay ?
2121 var selectedActivityForSheet : ProfileSelectedDayActivity ?
@@ -31,7 +31,11 @@ final class ProfileViewModel: Store {
3131 case tapResetStatusMessageButton
3232 case willUpdateStatusMessage
3333 case fetchUserData( UserProfile )
34- case setCompletionQuarter( ProfileCompletionQuarter , [ Todo ] )
34+ case setCompletionQuarter(
35+ quarterStart: Date ,
36+ quarter: ProfileCompletionQuarter ,
37+ dayActivitiesByDate: [ Date : [ ProfileSelectedDayActivity ] ]
38+ )
3539 case moveQuarter( Int )
3640 case toggleActivityType( ProfileActivityType )
3741 case selectDay( ProfileCompletionDay ? )
@@ -68,28 +72,17 @@ final class ProfileViewModel: Store {
6872 }
6973
7074 var selectedQuarter : ProfileCompletionQuarter ? {
71- guard let selectedQuarterStart = state. selectedQuarterStart else { return nil }
72- return state. completionQuarterCache [ selectedQuarterStart]
75+ state. completionQuarter
7376 }
7477
7578 var selectedDayActivities : [ ProfileSelectedDayActivity ] {
76- guard let selectedDay = state. selectedDay,
77- let selectedQuarterStart = state. selectedQuarterStart,
78- let todos = state. quarterTodosCache [ selectedQuarterStart] else { return [ ] }
79+ guard let selectedDay = state. selectedDay else { return [ ] }
7980 let dayStart = calendar. startOfDay ( for: selectedDay. date)
81+ let activities = state. dayActivitiesByDate [ dayStart] ?? [ ]
8082
81- return todos. compactMap { todo in
82- let isCreated = state. selectedActivityTypes. contains ( . created)
83- && calendar. startOfDay ( for: todo. createdAt) == dayStart
84- let isCompleted = state. selectedActivityTypes. contains ( . completed)
85- && todo. isCompleted
86- && calendar. startOfDay ( for: todo. updatedAt) == dayStart
87- guard isCreated || isCompleted else { return nil }
88- return ProfileSelectedDayActivity (
89- todo: todo,
90- showsCreated: isCreated,
91- showsCompleted: isCompleted
92- )
83+ return activities. filter { activity in
84+ ( state. selectedActivityTypes. contains ( . created) && activity. showsCreated)
85+ || ( state. selectedActivityTypes. contains ( . completed) && activity. showsCompleted)
9386 }
9487 }
9588
@@ -130,8 +123,7 @@ final class ProfileViewModel: Store {
130123 state. selectedActivityTypes = settings
131124 }
132125 effects = [ . fetchUserData]
133- if let selectedQuarterStart = state. selectedQuarterStart,
134- state. completionQuarterCache [ selectedQuarterStart] == nil {
126+ if let selectedQuarterStart = state. selectedQuarterStart {
135127 effects. append ( . fetchCompletionQuarter( selectedQuarterStart) )
136128 }
137129 case . setAlert( let isPresented) :
@@ -143,9 +135,10 @@ final class ProfileViewModel: Store {
143135 state. email = profile. email
144136 state. statusMessage = profile. statusMessage
145137 state. avatarURL = profile. avatarURL
146- case . setCompletionQuarter( let quarter, let todos) :
147- state. completionQuarterCache [ quarter. quarterStart] = quarter
148- state. quarterTodosCache [ quarter. quarterStart] = todos
138+ case . setCompletionQuarter( let quarterStart, let quarter, let dayActivitiesByDate) :
139+ guard state. selectedQuarterStart == quarterStart else { break }
140+ state. completionQuarter = quarter
141+ state. dayActivitiesByDate = dayActivitiesByDate
149142 case . selectDay( let day) :
150143 if let day, state. selectedDay? . date == day. date {
151144 state. selectedDay = nil
@@ -166,11 +159,11 @@ final class ProfileViewModel: Store {
166159 guard canMove ( to: nextQuarterStart, calendar: calendar, today: today) else { break }
167160
168161 state. selectedQuarterStart = nextQuarterStart
162+ state. completionQuarter = nil
163+ state. dayActivitiesByDate = [ : ]
169164 state. selectedDay = nil
170165 state. selectedActivityForSheet = nil
171- if state. completionQuarterCache [ nextQuarterStart] == nil {
172- effects = [ . fetchCompletionQuarter( nextQuarterStart) ]
173- }
166+ effects = [ . fetchCompletionQuarter( nextQuarterStart) ]
174167 case . toggleActivityType( let activityType) :
175168 if state. selectedActivityTypes. contains ( activityType) , state. selectedActivityTypes. count == 1 {
176169 break
@@ -212,7 +205,14 @@ final class ProfileViewModel: Store {
212205 let todos = try await fetchQuarterTodos ( from: quarterStart)
213206 let months = makeCompletionMonths ( from: todos, quarterStart: quarterStart)
214207 let quarter = ProfileCompletionQuarter ( quarterStart: quarterStart, months: months)
215- send ( . setCompletionQuarter( quarter, todos) )
208+ let dayActivitiesByDate = makeDayActivitiesByDate ( from: todos)
209+ send (
210+ . setCompletionQuarter(
211+ quarterStart: quarterStart,
212+ quarter: quarter,
213+ dayActivitiesByDate: dayActivitiesByDate
214+ )
215+ )
216216 } catch {
217217 send ( . setAlert( true ) )
218218 }
@@ -235,6 +235,35 @@ final class ProfileViewModel: Store {
235235}
236236
237237private extension ProfileViewModel {
238+ func makeDayActivitiesByDate( from todos: [ Todo ] ) -> [ Date : [ ProfileSelectedDayActivity ] ] {
239+ var activitiesByDate : [ Date : [ ProfileSelectedDayActivity ] ] = [ : ]
240+
241+ for todo in todos {
242+ let createdDay = calendar. startOfDay ( for: todo. createdAt)
243+ let completedDay = todo. isCompleted ? calendar. startOfDay ( for: todo. updatedAt) : nil
244+
245+ activitiesByDate [ createdDay, default: [ ] ] . append (
246+ ProfileSelectedDayActivity (
247+ todo: todo,
248+ showsCreated: true ,
249+ showsCompleted: completedDay == createdDay
250+ )
251+ )
252+
253+ if let completedDay, completedDay != createdDay {
254+ activitiesByDate [ completedDay, default: [ ] ] . append (
255+ ProfileSelectedDayActivity (
256+ todo: todo,
257+ showsCreated: false ,
258+ showsCompleted: true
259+ )
260+ )
261+ }
262+ }
263+
264+ return activitiesByDate
265+ }
266+
238267 func setAlert(
239268 _ state: inout State ,
240269 isPresented: Bool
0 commit comments