Skip to content

Commit 8e6610b

Browse files
authored
Feat: 루틴 등록 / 수정 로직 구현
* feat: DTO -> Parameter 변환을 위한 Encodable extension 구현 * feat: 루틴 생성/수정 관련 DTO 정의 * feat: 루틴 endpoint 수정 - 루틴 생성 추가 - 루틴 수정 추가 - 루틴 단건 조회 추가 * fix: routine 엔티티의 id를 옵셔널로 수정 * feat: 루틴 repository 구현 * feat: 루틴 생성/수정 UseCase 구현 - 루틴 요약, 서브 루틴 요약 엔티티 생성 * feat: 루틴 등록/수정 로직 View와 연결
1 parent a5eff16 commit 8e6610b

23 files changed

Lines changed: 436 additions & 43 deletions
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// Encodable+.swift
3+
// DataSource
4+
//
5+
// Created by 이동현 on 8/3/25.
6+
//
7+
8+
import Foundation
9+
10+
extension Encodable {
11+
var dictionary: [String: Any] {
12+
guard
13+
let data = try? JSONEncoder().encode(self),
14+
let dictionary = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
15+
else { return [:] }
16+
return dictionary
17+
}
18+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// RoutienCreationDTO.swift
3+
// DataSource
4+
//
5+
// Created by 이동현 on 8/3/25.
6+
//
7+
8+
struct RoutineCreationDTO: Codable {
9+
let routineName: String
10+
let repeatDay: [String]
11+
let executionTime: String
12+
let subRoutineName: [String]
13+
}

Projects/DataSource/Sources/DTO/RoutineResponseDTO.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ struct RoutineResponseDTO: Decodable {
2626

2727
extension RoutineResponseDTO {
2828
func toRoutineEntity() -> RoutineEntity {
29+
let sortedSubRoutinesDTO = subRoutineSearchResultDto.sorted { $0.sortOrder < $1.sortOrder }
30+
2931
return RoutineEntity(
3032
routineId: routineId,
3133
historySeq: historySeq,
3234
routineName: routineName,
3335
repeatDay: repeatDay,
3436
executionTime: executionTime,
35-
subRoutineSearchResultDto: subRoutineSearchResultDto.map({ $0.toSubRoutineEntity() }),
37+
subRoutineSearchResultDto: sortedSubRoutinesDTO.map({ $0.toSubRoutineEntity() }),
3638
modifiedYn: modifiedYn,
3739
routineCompletionId: routineCompletionId,
3840
completeYn: completeYn,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//
2+
// RoutineUpdateDTO.swift
3+
// DataSource
4+
//
5+
// Created by 이동현 on 8/3/25.
6+
//
7+
8+
struct RoutineUpdateDTO: Codable {
9+
let routineId: String
10+
let routineName: String
11+
let repeatDay: [String]
12+
let executionTime: String
13+
let subRoutineInfos: [SubRoutineUpdateDTO]
14+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//
2+
// SubRoutineUpdateDTO.swift
3+
// DataSource
4+
//
5+
// Created by 이동현 on 8/3/25.
6+
//
7+
8+
struct SubRoutineUpdateDTO: Codable {
9+
let subRoutineId: String?
10+
let subRoutineName: String?
11+
let sortOrder: Int?
12+
}

Projects/DataSource/Sources/Endpoint/RoutineEndpoint.swift

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
//
77

88
enum RoutineEndpoint {
9+
case createRoutine(routine: RoutineCreationDTO)
10+
case fetchRoutine(routineId: String)
911
case fetchRoutines(startDate: String, endDate: String)
12+
case updateRoutine(routine: RoutineUpdateDTO)
1013
}
1114

1215
extension RoutineEndpoint: Endpoint {
@@ -16,13 +19,21 @@ extension RoutineEndpoint: Endpoint {
1619

1720
var path: String {
1821
switch self {
19-
case .fetchRoutines: baseURL
22+
case .fetchRoutine(let routineId):
23+
"\(baseURL)/\(routineId)"
24+
default:
25+
baseURL
2026
}
2127
}
2228

2329
var method: HTTPMethod {
2430
switch self {
25-
case .fetchRoutines: .get
31+
case .createRoutine:
32+
.post
33+
case .fetchRoutine, .fetchRoutines:
34+
.get
35+
case .updateRoutine:
36+
.patch
2637
}
2738
}
2839

@@ -40,11 +51,20 @@ extension RoutineEndpoint: Endpoint {
4051
return [
4152
"startDate": startDate,
4253
"endDate": endDate]
54+
default:
55+
return [:]
4356
}
4457
}
4558

4659
var bodyParameters: [String : Any] {
47-
return [:]
60+
switch self {
61+
case .createRoutine(let routine):
62+
return routine.dictionary
63+
case .updateRoutine(let routine):
64+
return routine.dictionary
65+
default:
66+
return [:]
67+
}
4868
}
4969

5070
var isAuthorized: Bool {

Projects/DataSource/Sources/Repository/RoutineRepository.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,26 @@ import Domain
1010
final class RoutineRepository: RoutineRepositoryProtocol {
1111
private let networkService = NetworkService.shared
1212

13+
func createRoutine(routineSummary: RoutineSummaryEntity, subRoutineSummaries: [SubRoutineSummaryEntity]) async throws {
14+
let subRoutineNames = subRoutineSummaries.compactMap { $0.subRoutineName }
15+
16+
let routineCreationDTO = RoutineCreationDTO(
17+
routineName: routineSummary.routineName,
18+
repeatDay: routineSummary.repeatDay.map { $0.rawValue },
19+
executionTime: routineSummary.executionTime,
20+
subRoutineName: subRoutineNames)
21+
let endpoint = RoutineEndpoint.createRoutine(routine: routineCreationDTO)
22+
23+
_ = try await networkService.request(endpoint: endpoint, type: EmptyResponseDTO.self)
24+
}
25+
26+
func fetchRoutine(routineId: String) async throws -> RoutineEntity? {
27+
let endpoint = RoutineEndpoint.fetchRoutine(routineId: routineId)
28+
guard let response = try await networkService.request(endpoint: endpoint, type: RoutineResponseDTO.self) else { return nil }
29+
30+
return response.toRoutineEntity()
31+
}
32+
1333
func fetchRoutines(from startDate: String, to endDate: String) async throws -> [String: [RoutineEntity]] {
1434
let endpoint = RoutineEndpoint.fetchRoutines(startDate: startDate, endDate: endDate)
1535
guard let response = try await networkService.request(endpoint: endpoint, type: RoutineDictionaryDTO.self)
@@ -21,4 +41,25 @@ final class RoutineRepository: RoutineRepositoryProtocol {
2141
}
2242
return result
2343
}
44+
45+
func updateRoutine(routineSummary: RoutineSummaryEntity, subRoutineSummaries: [SubRoutineSummaryEntity]) async throws {
46+
guard let routineId = routineSummary.routineId else { return }
47+
48+
let subRoutineDTO = subRoutineSummaries.map {
49+
SubRoutineUpdateDTO(
50+
subRoutineId: $0.subRoutineId,
51+
subRoutineName: $0.subRoutineName,
52+
sortOrder: $0.sortOrder)
53+
}
54+
55+
let routineUpdateDTO = RoutineUpdateDTO(
56+
routineId: routineId,
57+
routineName: routineSummary.routineName,
58+
repeatDay: routineSummary.repeatDay.map { $0.rawValue },
59+
executionTime: routineSummary.executionTime,
60+
subRoutineInfos: subRoutineDTO)
61+
let endpoint = RoutineEndpoint.updateRoutine(routine: routineUpdateDTO)
62+
63+
_ = try await networkService.request(endpoint: endpoint, type: EmptyResponseDTO.self)
64+
}
2465
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// Week.swift
3+
// Domain
4+
//
5+
// Created by 이동현 on 8/3/25.
6+
//
7+
8+
public enum WeekType: String, CaseIterable {
9+
case monday = "MONDAY"
10+
case tuesday = "TUESDAY"
11+
case wednesday = "WEDNESDAY"
12+
case thursday = "THURSDAY"
13+
case friday = "FRIDAY"
14+
case saturday = "SATURDAY"
15+
case sunday = "SUNDAY"
16+
}

Projects/Domain/Sources/Entity/RoutineEntity.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
//
77

88
public struct RoutineEntity {
9-
public let routineId: String
9+
public let routineId: String?
1010
public let historySeq: Int
1111
public let routineName: String
12-
public let repeatDay: [String]
12+
public let repeatDay: [WeekType]
1313
public let executionTime: String
1414
public let subRoutineSearchResultDto: [SubRoutineEntity]
1515
public let modifiedYn: Bool
@@ -18,7 +18,7 @@ public struct RoutineEntity {
1818
public let routineType: String
1919

2020
public init(
21-
routineId: String,
21+
routineId: String?,
2222
historySeq: Int,
2323
routineName: String,
2424
repeatDay: [String]?,
@@ -29,10 +29,12 @@ public struct RoutineEntity {
2929
completeYn: Bool,
3030
routineType: String
3131
) {
32+
let weekType: [WeekType] = repeatDay?.compactMap(WeekType.init(rawValue:)) ?? []
33+
3234
self.routineId = routineId
3335
self.historySeq = historySeq
3436
self.routineName = routineName
35-
self.repeatDay = repeatDay ?? []
37+
self.repeatDay = weekType
3638
self.executionTime = executionTime
3739
self.subRoutineSearchResultDto = subRoutineSearchResultDto
3840
self.modifiedYn = modifiedYn
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// RoutineSummaryEntity.swift
3+
// Domain
4+
//
5+
// Created by 이동현 on 8/3/25.
6+
//
7+
8+
public struct RoutineSummaryEntity {
9+
public let routineId: String?
10+
public let routineName: String
11+
public let repeatDay: [WeekType]
12+
public let executionTime: String
13+
14+
public init(
15+
routineId: String?,
16+
routineName: String,
17+
repeatDay: [String]?,
18+
executionTime: String
19+
) {
20+
let weekType: [WeekType] = repeatDay?.compactMap(WeekType.init(rawValue:)) ?? []
21+
22+
self.routineId = routineId
23+
self.routineName = routineName
24+
self.repeatDay = weekType
25+
self.executionTime = executionTime
26+
}
27+
}

0 commit comments

Comments
 (0)