Skip to content

Commit 6f41e1b

Browse files
committed
Feat: 루틴 완료에 따른 별 표시 (#T3-178(
1 parent b07e0f2 commit 6f41e1b

3 files changed

Lines changed: 55 additions & 5 deletions

File tree

Projects/Presentation/Sources/Home/View/Component/WeekView.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ final class WeekView: UIView {
2424
private var dateViews: [Date: DateView] = [:]
2525
private let calendar = Calendar.current
2626
private var selectedDate: Date
27+
private var allCompletedDates: [Date] = []
2728
weak var delegate: WeekViewDelegate?
2829

2930
init(date: Date = Date()) {
@@ -88,6 +89,10 @@ final class WeekView: UIView {
8889
isSelected: isSelected,
8990
isToday: isToday)
9091

92+
let isAllCompleted = allCompletedDates.contains(date)
93+
if isAllCompleted {
94+
dateView.updateAllCompleted()
95+
}
9196
dateView.didTapDateButton = { [weak self] date in
9297
self?.selectDate(date: date)
9398
}
@@ -100,6 +105,15 @@ final class WeekView: UIView {
100105
}
101106
}
102107

108+
func updateAllCompletedState(allCompletedDates: [Date]) {
109+
self.allCompletedDates = allCompletedDates
110+
for dateView in dateViews {
111+
if allCompletedDates.contains(dateView.key) {
112+
dateView.value.updateAllCompleted()
113+
}
114+
}
115+
}
116+
103117
// 날짜를 선택합니다.
104118
private func selectDate(date: Date) {
105119
selectedDate = date

Projects/Presentation/Sources/Home/View/HomeViewController.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,13 @@ final class HomeViewController: BaseViewController<HomeViewModel> {
454454
self.navigationController?.pushViewController(routineListViewController, animated: true)
455455
}
456456
.store(in: &cancellables)
457+
458+
viewModel.output.allCompletedRoutineDatePublisher
459+
.receive(on: DispatchQueue.main)
460+
.sink { [weak self] allCompletedDates in
461+
self?.weekView.updateAllCompletedState(allCompletedDates: allCompletedDates)
462+
}
463+
.store(in: &cancellables)
457464
}
458465

459466
// 해당 날짜의 Routine View를 설정합니다. (없다면 EmptyView)

Projects/Presentation/Sources/Home/ViewModel/HomeViewModel.swift

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ final class HomeViewModel: ViewModel {
3030
let fetchRoutineResultPublisher: AnyPublisher<Bool, Never>
3131
let routinesPublisher: AnyPublisher<[Routine], Never>
3232
let updateRoutineCompletionResultPublisher: AnyPublisher<Bool, Never>
33+
let allCompletedRoutineDatePublisher: AnyPublisher<[Date], Never>
3334
}
3435

3536
private(set) var output: Output
3637
private var routines: [String: [Routine]] = [:]
37-
private var routineCompleted: [String: Bool] = [:]
38+
private var routinesCompleted: [String: Bool] = [:]
3839
private let nicknameSubject = CurrentValueSubject<String, Never>("")
3940
private let emotionSubject = CurrentValueSubject<Emotion?, Never>(nil)
4041
private let selectedDateSubject = CurrentValueSubject<Date, Never>(.now)
@@ -43,6 +44,7 @@ final class HomeViewModel: ViewModel {
4344
private let routinesSubject = CurrentValueSubject<[Routine], Never>([])
4445
private let selectedRoutineSubject = CurrentValueSubject<Routine?, Never>(nil)
4546
private let updateRoutineCompletionResultSubject = PassthroughSubject<Bool, Never>()
47+
private let allCompletedRoutineDateSubject = CurrentValueSubject<[Date], Never>([])
4648

4749
private let calendar = Calendar.current
4850
private let today = Date()
@@ -67,8 +69,8 @@ final class HomeViewModel: ViewModel {
6769
routineListDatePublisher: routineListDateSubject.eraseToAnyPublisher(),
6870
fetchRoutineResultPublisher: fetchRoutineResultSubject.eraseToAnyPublisher(),
6971
routinesPublisher: routinesSubject.eraseToAnyPublisher(),
70-
updateRoutineCompletionResultPublisher: updateRoutineCompletionResultSubject.eraseToAnyPublisher()
71-
)
72+
updateRoutineCompletionResultPublisher: updateRoutineCompletionResultSubject.eraseToAnyPublisher(),
73+
allCompletedRoutineDatePublisher: allCompletedRoutineDateSubject.eraseToAnyPublisher())
7274
}
7375

7476
func action(input: Input) {
@@ -132,10 +134,19 @@ final class HomeViewModel: ViewModel {
132134
// MARK: - 날짜
133135
private func moveWeek(by week: Int) {
134136
let currentDate = selectedDateSubject.value
135-
guard let weekStartDate = calendar.date(byAdding: .weekOfYear, value: week, to: currentDate)
137+
guard let nextWeekDate = calendar.date(byAdding: .weekOfYear, value: week, to: currentDate)
136138
else { return }
139+
let weekStartDate = calculateWeekStartDate(for: nextWeekDate)
137140
selectedDateSubject.send(weekStartDate)
138141
fetchDailyRoutine(for: weekStartDate)
142+
fetchAllCompletedRoutine()
143+
}
144+
145+
// 현재 주의 첫째 날(월요일)을 계산해줍니다.
146+
private func calculateWeekStartDate(for date: Date) -> Date {
147+
let weekday = calendar.component(.weekday, from: date)
148+
let daysFromMonday = (weekday == 1) ? 6 : weekday - 2
149+
return calendar.date(byAdding: .day, value: -daysFromMonday, to: date) ?? date
139150
}
140151

141152
// 날짜를 선택하고 그 날에 해당하는 루틴을 불러옵니다.
@@ -144,6 +155,22 @@ final class HomeViewModel: ViewModel {
144155
fetchDailyRoutine(for: date)
145156
}
146157

158+
private func fetchAllCompletedRoutine() {
159+
let selectedDate = selectedDateSubject.value
160+
let weekStartDate = calculateWeekStartDate(for: selectedDate)
161+
var allCompletedDates: [Date] = []
162+
for i in 0..<7 {
163+
guard let date = calendar.date(byAdding: .day, value: i, to: weekStartDate)
164+
else { continue }
165+
guard
166+
let isAllCompleted = routinesCompleted[date.convertToString(dateType: .yearMonthDate)],
167+
isAllCompleted
168+
else { continue }
169+
allCompletedDates.append(date)
170+
}
171+
allCompletedRoutineDateSubject.send(allCompletedDates)
172+
}
173+
147174
// MARK: - 루틴
148175
// 루틴들을 불러옵니다. (처음에는 +-1 주, 그 이후에는 1주씩)
149176
private func fetchRoutines() {
@@ -163,8 +190,9 @@ final class HomeViewModel: ViewModel {
163190
let routineEntities = values.routines
164191
let allCompleted = values.allCompleted
165192
routines[date] = routineEntities.map({ $0.toRoutine() })
166-
routineCompleted[date] = allCompleted
193+
routinesCompleted[date] = allCompleted
167194
}
195+
fetchAllCompletedRoutine()
168196
fetchRoutineResultSubject.send(true)
169197
} catch {
170198
fetchRoutineResultSubject.send(false)
@@ -218,6 +246,7 @@ final class HomeViewModel: ViewModel {
218246
Task {
219247
fetchRoutines(startDate: selectedDate, endDate: selectedDate)
220248
fetchDailyRoutine(for: selectedDate)
249+
fetchAllCompletedRoutine()
221250
}
222251
}
223252

0 commit comments

Comments
 (0)