Skip to content

Commit fffa8a0

Browse files
committed
refactor: 필터링 시 각 조건에 대해 각각 필터링이 아닌, 한번의 순회 동안 각 조건을 검사해서 필터링하도록 개선
1 parent 069fb1e commit fffa8a0

1 file changed

Lines changed: 51 additions & 15 deletions

File tree

DevLog/Presentation/ViewModel/TodayViewModel.swift

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ final class TodayViewModel: Store {
2222
let items: [TodayTodoItem]
2323
}
2424

25+
struct SectionBuckets {
26+
var focused: [TodayTodoItem] = []
27+
var overdue: [TodayTodoItem] = []
28+
var dueSoon: [TodayTodoItem] = []
29+
var later: [TodayTodoItem] = []
30+
var unscheduled: [TodayTodoItem] = []
31+
}
32+
2533
struct State: Equatable {
2634
var todos: [TodayTodoItem] = []
2735
var isLoading: Bool = false
@@ -78,12 +86,13 @@ final class TodayViewModel: Store {
7886
}
7987

8088
var sections: [SectionContent] {
89+
let groupedItems = groupedSectionItems(from: displayedTodos)
8190
let allSections: [SectionContent] = [
82-
SectionContent(title: "집중할 일", items: displayedTodos.filter(\.isPinned)),
83-
SectionContent(title: "지난 마감", items: displayedTodos.filter { !$0.isPinned && isOverdue($0) }),
84-
SectionContent(title: "\(upcomingWindowDays)일 내 일정", items: displayedTodos.filter { !$0.isPinned && isDueSoon($0) }),
85-
SectionContent(title: "나중 일정", items: displayedTodos.filter { !$0.isPinned && isScheduledLater($0) }),
86-
SectionContent(title: "일정 미정", items: displayedTodos.filter { !$0.isPinned && $0.dueDate == nil })
91+
SectionContent(title: "집중할 일", items: groupedItems.focused),
92+
SectionContent(title: "지난 마감", items: groupedItems.overdue),
93+
SectionContent(title: "\(upcomingWindowDays)일 내 일정", items: groupedItems.dueSoon),
94+
SectionContent(title: "나중 일정", items: groupedItems.later),
95+
SectionContent(title: "일정 미정", items: groupedItems.unscheduled)
8796
]
8897

8998
switch state.selectedSummaryScope {
@@ -289,6 +298,43 @@ private extension TodayViewModel {
289298
}
290299
}
291300

301+
func groupedSectionItems(
302+
from items: [TodayTodoItem]
303+
) -> SectionBuckets {
304+
let startOfToday = calendar.startOfDay(for: Date())
305+
guard let windowEnd = calendar.date(byAdding: .day, value: upcomingWindowDays, to: startOfToday) else {
306+
return SectionBuckets(
307+
focused: items.filter(\.isPinned),
308+
unscheduled: items.filter { !$0.isPinned && $0.dueDate == nil }
309+
)
310+
}
311+
312+
var buckets = SectionBuckets()
313+
314+
for item in items {
315+
if item.isPinned {
316+
buckets.focused.append(item)
317+
continue
318+
}
319+
320+
guard let dueDate = item.dueDate else {
321+
buckets.unscheduled.append(item)
322+
continue
323+
}
324+
325+
let dueDay = calendar.startOfDay(for: dueDate)
326+
if dueDay < startOfToday {
327+
buckets.overdue.append(item)
328+
} else if dueDay <= windowEnd {
329+
buckets.dueSoon.append(item)
330+
} else {
331+
buckets.later.append(item)
332+
}
333+
}
334+
335+
return buckets
336+
}
337+
292338
func isOverdue(_ item: TodayTodoItem) -> Bool {
293339
guard let dueDate = item.dueDate else { return false }
294340
return calendar.startOfDay(for: dueDate) < calendar.startOfDay(for: Date())
@@ -303,14 +349,4 @@ private extension TodayViewModel {
303349
let dueDay = calendar.startOfDay(for: dueDate)
304350
return startOfToday <= dueDay && dueDay <= windowEnd
305351
}
306-
307-
func isScheduledLater(_ item: TodayTodoItem) -> Bool {
308-
guard let dueDate = item.dueDate else { return false }
309-
let startOfToday = calendar.startOfDay(for: Date())
310-
guard let windowEnd = calendar.date(byAdding: .day, value: upcomingWindowDays, to: startOfToday) else {
311-
return false
312-
}
313-
let dueDay = calendar.startOfDay(for: dueDate)
314-
return windowEnd < dueDay
315-
}
316352
}

0 commit comments

Comments
 (0)