Skip to content

Commit df31c9f

Browse files
authored
Feature/record past date/main (#47)
* feat: GetHistoryFromDateUsecase * feat: ContextMenu * feat: DateToSelectHistory * feat: datetoselecthistory * feat: navigation binding * feat: HistoryListViewModel * feat: DateToSelectHistoryView * fix * fix
1 parent 0c21b81 commit df31c9f

13 files changed

+162
-3
lines changed

dg-muscle-ios/sources/App/Delegate/SceneDelegate.swift

+3
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ class SceneDelegate: NSObject, UIWindowSceneDelegate {
9090
case "setrunduration":
9191
let duration = URLManager.shared.getParameter(url: url, name: "duration") ?? ""
9292
coordinator?.setDuration(duration: Int(duration) ?? 0)
93+
case "datetoselecthistory":
94+
coordinator?.dateToSelectHistory()
95+
9396
default: break
9497
}
9598
}

dg-muscle-ios/sources/DataLayer/History/Repository/HistoryRepositoryImpl.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public final class HistoryRepositoryImpl: Domain.HistoryRepository {
1515

1616
public var runDistanceSubject: PassthroughSubject<Double, Never> = .init()
1717
public var runDurationSubject: PassthroughSubject<Int, Never> = .init()
18+
public var dateToSelectHistory: PassthroughSubject<Date, Never> = .init()
1819

1920
public var histories: AnyPublisher<[Domain.History], Never> { $_histories.eraseToAnyPublisher() }
2021
private var cancellables = Set<AnyCancellable>()
@@ -41,7 +42,10 @@ public final class HistoryRepositoryImpl: Domain.HistoryRepository {
4142
if let index = _histories.firstIndex(where: { $0.id == history.id }) {
4243
_histories[index] = history
4344
} else {
44-
_histories.insert(history, at: 0)
45+
var histories = _histories
46+
histories.append(history)
47+
histories.sort(by: {$0.date > $1.date})
48+
_histories = histories
4549
}
4650

4751
let url = FunctionsURL.history(.posthistory)

dg-muscle-ios/sources/Domain/History/Repository/HistoryRepository.swift

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public protocol HistoryRepository {
1212
var histories: AnyPublisher<[History], Never> { get }
1313
var runDistanceSubject: PassthroughSubject<Double, Never> { get }
1414
var runDurationSubject: PassthroughSubject<Int, Never> { get }
15+
var dateToSelectHistory: PassthroughSubject<Date, Never> { get }
1516

1617
func get() -> [History]
1718
func get(historyId: String) -> History?
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//
2+
// GetHistoryFromDateUsecase.swift
3+
// Domain
4+
//
5+
// Created by 신동규 on 7/4/24.
6+
//
7+
8+
import Foundation
9+
10+
public final class GetHistoryFromDateUsecase {
11+
private let historyRepository: HistoryRepository
12+
13+
public init(historyRepository: HistoryRepository) {
14+
self.historyRepository = historyRepository
15+
}
16+
17+
public func implement(date: Date) -> History? {
18+
historyRepository.get().first(where: {
19+
Calendar.current.isDate($0.date, inSameDayAs: date)
20+
})
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//
2+
// PushDateToSelectHistoryUsecase.swift
3+
// Domain
4+
//
5+
// Created by 신동규 on 7/4/24.
6+
//
7+
8+
import Foundation
9+
10+
public final class PushDateToSelectHistoryUsecase {
11+
private let historyRepository: HistoryRepository
12+
13+
public init(historyRepository: HistoryRepository) {
14+
self.historyRepository = historyRepository
15+
}
16+
17+
public func implement(date: Date) {
18+
historyRepository.dateToSelectHistory.send(date)
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// SubscribeDateToSelectHistoryUsecase.swift
3+
// Domain
4+
//
5+
// Created by 신동규 on 7/4/24.
6+
//
7+
8+
import Foundation
9+
import Combine
10+
11+
public final class SubscribeDateToSelectHistoryUsecase {
12+
private let historyRepository: HistoryRepository
13+
14+
public init(historyRepository: HistoryRepository) {
15+
self.historyRepository = historyRepository
16+
}
17+
18+
public func implement() -> PassthroughSubject<Date, Never> {
19+
historyRepository.dateToSelectHistory
20+
}
21+
}

dg-muscle-ios/sources/MockData/Repository/HistoryRepositoryMock.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public final class HistoryRepositoryMock: HistoryRepository {
1717

1818
public var runDistanceSubject: PassthroughSubject<Double, Never> = .init()
1919
public var runDurationSubject: PassthroughSubject<Int, Never> = .init()
20+
public var dateToSelectHistory: PassthroughSubject<Date, Never> = .init()
2021

2122
public init() { }
2223

@@ -32,7 +33,10 @@ public final class HistoryRepositoryMock: HistoryRepository {
3233
if let index = _histories.firstIndex(where: { $0.id == history.id }) {
3334
_histories[index] = history
3435
} else {
35-
_histories.insert(history, at: 0)
36+
var histories = _histories
37+
histories.append(history)
38+
histories.sort(by: {$0.date > $1.date})
39+
_histories = histories
3640
}
3741
}
3842

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//
2+
// DateToSelectHistoryView.swift
3+
// Domain
4+
//
5+
// Created by 신동규 on 7/4/24.
6+
//
7+
8+
import SwiftUI
9+
import Domain
10+
import MockData
11+
import Common
12+
13+
public struct DateToSelectHistoryView: View {
14+
15+
let pushDateToSelectHistoryUsecase: PushDateToSelectHistoryUsecase
16+
@State var date: Date
17+
18+
private let now = Date()
19+
20+
public init(historyRepository: HistoryRepository) {
21+
pushDateToSelectHistoryUsecase = .init(historyRepository: historyRepository)
22+
self.date = Calendar.current.date(byAdding: .day, value: -1, to: Date()) ?? Date()
23+
}
24+
25+
public var body: some View {
26+
VStack {
27+
DatePicker("Date to select record", selection: $date, displayedComponents: .date)
28+
29+
HStack {
30+
Spacer()
31+
Button("Select") {
32+
URLManager.shared.open(url: "dgmuscle://pop")
33+
34+
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
35+
pushDateToSelectHistoryUsecase.implement(date: date)
36+
}
37+
}
38+
.buttonStyle(.bordered)
39+
}
40+
}
41+
.padding()
42+
.onChange(of: date) { oldValue, newValue in
43+
if newValue >= now || Calendar.current.isDate(newValue, inSameDayAs: now) {
44+
date = oldValue
45+
}
46+
}
47+
}
48+
}
49+
50+
#Preview {
51+
DateToSelectHistoryView(historyRepository: HistoryRepositoryMock())
52+
.preferredColorScheme(.dark)
53+
}

dg-muscle-ios/sources/Presentation/History/View/List/HistoryListView.swift

+5
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ public struct HistoryListView: View {
105105
)
106106
}
107107
.padding(.trailing)
108+
.contextMenu {
109+
Button("Record past workout") {
110+
URLManager.shared.open(url: "dgmuscle://datetoselecthistory")
111+
}
112+
}
108113
}
109114
}
110115
}

dg-muscle-ios/sources/Presentation/History/View/List/HistoryListViewModel.swift

+20-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ final class HistoryListViewModel: ObservableObject {
2222
let subscribeExercisesUsecase: SubscribeExercisesUsecase
2323
let subscribeHistoriesGroupedByMonthUsecase: SubscribeHistoriesGroupedByMonthUsecase
2424
let subscribeHeatMapColorUsecase: SubscribeHeatMapColorUsecase
25+
let subscribeDateToSelectHistoryUsecase: SubscribeDateToSelectHistoryUsecase
26+
let getHistoryFromDateUsecase: GetHistoryFromDateUsecase
27+
let postHistoryUsecase: PostHistoryUsecase
2528

2629
private var cancellables = Set<AnyCancellable>()
2730
init(today: Date,
@@ -34,6 +37,9 @@ final class HistoryListViewModel: ObservableObject {
3437
subscribeExercisesUsecase = .init(exerciseRepository: exerciseRepository)
3538
subscribeHistoriesGroupedByMonthUsecase = .init(historyRepository: historyRepository)
3639
subscribeHeatMapColorUsecase = .init(userRepository: userRepository)
40+
subscribeDateToSelectHistoryUsecase = .init(historyRepository: historyRepository)
41+
getHistoryFromDateUsecase = .init(historyRepository: historyRepository)
42+
postHistoryUsecase = .init(historyRepository: historyRepository)
3743

3844
bind()
3945
}
@@ -88,6 +94,19 @@ final class HistoryListViewModel: ObservableObject {
8894
self?.hasExercise = !exercises.isEmpty
8995
}
9096
.store(in: &cancellables)
97+
98+
subscribeDateToSelectHistoryUsecase
99+
.implement()
100+
.receive(on: DispatchQueue.main)
101+
.sink { [weak self] date in
102+
if let history = self?.getHistoryFromDateUsecase.implement(date: date) {
103+
URLManager.shared.open(url: "dgmuscle://history?id=\(history.id)")
104+
} else {
105+
let history: Domain.History = .init(id: UUID().uuidString, date: date, memo: nil, records: [], run: nil)
106+
self?.postHistoryUsecase.implement(history: history)
107+
URLManager.shared.open(url: "dgmuscle://history?id=\(history.id)")
108+
}
109+
}
110+
.store(in: &cancellables)
91111
}
92112
}
93-

dg-muscle-ios/sources/Presentation/Main/Coordinator/Coordinator.swift

+4
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ public final class Coordinator {
9898
path.append(HistoryNavigation(name: .manageMemo(memo)))
9999
}
100100

101+
public func dateToSelectHistory() {
102+
path.append(HistoryNavigation(name: .dateToSelectHistory))
103+
}
104+
101105
public func profile() {
102106
path.append(MyNavigation(name: .profile))
103107
}

dg-muscle-ios/sources/Presentation/Main/Navigation/HistoryNavigation.swift

+1
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,6 @@ extension HistoryNavigation {
3737
case setDistance(Double)
3838
case setDuration(Int)
3939
case manageMemo(Binding<String>)
40+
case dateToSelectHistory
4041
}
4142
}

dg-muscle-ios/sources/Presentation/Main/View/NavigationView.swift

+2
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ public struct NavigationView: View {
106106
)
107107
case .manageMemo(let memo):
108108
ManageMemoView(memo: memo)
109+
case .dateToSelectHistory:
110+
DateToSelectHistoryView(historyRepository: historyRepository)
109111
}
110112
}
111113
.navigationDestination(for: MyNavigation.self) { navigation in

0 commit comments

Comments
 (0)