-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/#121 챌린지 api 연결 #127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The head ref may contain hidden characters: "feat/#121-\uCC4C\uB9B0\uC9C0-api-\uC5F0\uACB0"
Feat/#121 챌린지 api 연결 #127
Changes from all commits
e9743b4
05ef4a3
621d74c
acf2a92
a62d48e
d3810f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| // | ||
| // FetchChallengesResponseDTO.swift | ||
| // Cherrish-iOS | ||
| // | ||
| // Created by 이나연 on 1/21/26. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| struct FetchChallengesResponseDTO: Decodable { | ||
| let challengeId: Int | ||
| let title: String | ||
| let currentDay: Int | ||
| let progressPercentage: Int | ||
| let cherryLevel: Int | ||
| let cherryLevelName: String | ||
| let progressToNextLevel: Double | ||
| let remainingRoutinesToNextLevel: Int | ||
| let todayRoutines: [RoutineResponseDTO] | ||
| let cheeringMessage: String | ||
| } | ||
|
|
||
| struct RoutineResponseDTO: Decodable { | ||
| let routineId: Int | ||
| let name: String | ||
| let scheduledDate: String | ||
| let isComplete: Bool | ||
| } | ||
|
|
||
| extension FetchChallengesResponseDTO { | ||
| func toEntity() -> ChallengeEntity { | ||
| .init( | ||
| challengeID: challengeId, | ||
| title: title, | ||
| currentDay: currentDay, | ||
| progressPercentage: progressPercentage, | ||
| cherryLevel: cherryLevel, | ||
| cherryLevelName: cherryLevelName, | ||
| progressToNextLevel: progressToNextLevel, | ||
| remainingRoutinesToNextLevel: remainingRoutinesToNextLevel, | ||
| todayRoutines: todayRoutines.map { $0.toEntity() } | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| extension RoutineResponseDTO { | ||
| func toEntity() -> RoutineEntity { | ||
| .init( | ||
| routineID: routineId, | ||
| name: name, | ||
| isComplete: isComplete | ||
| ) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // | ||
| // RoutineToggleResponseDTO.swift | ||
| // Cherrish-iOS | ||
| // | ||
| // Created by 이나연 on 1/21/26. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| struct RoutineToggleResponseDTO: Decodable { | ||
| let routineId: Int | ||
| let name: String | ||
| let isComplete: Bool | ||
| } | ||
|
|
||
| extension RoutineToggleResponseDTO { | ||
| func toEntity() -> RoutineEntity { | ||
| .init( | ||
| routineID: routineId, | ||
| name: name, | ||
| isComplete: isComplete | ||
| ) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| // | ||
| // DemoAPI.swift | ||
| // Cherrish-iOS | ||
| // | ||
| // Created by 이나연 on 1/21/26. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| import Alamofire | ||
|
|
||
| enum DemoAPI { | ||
| case fetchChallenges(userID: Int) | ||
| case advance(userID: Int) | ||
| case routineToggle(userID: Int, routineID: Int) | ||
| } | ||
|
|
||
| extension DemoAPI: EndPoint { | ||
| var basePath: String { | ||
| "/api/demo/challenges" | ||
| } | ||
|
|
||
| var path: String { | ||
| switch self { | ||
| case .fetchChallenges: | ||
| return "" | ||
| case .advance: | ||
| return "/advance-day" | ||
| case .routineToggle(_, let routineID): | ||
| return "/routines/\(routineID)/toggle" | ||
| } | ||
| } | ||
|
|
||
| var method: Alamofire.HTTPMethod { | ||
| switch self { | ||
| case .fetchChallenges: | ||
| return .get | ||
| case .advance: | ||
| return .post | ||
| case .routineToggle(_, let routineID): | ||
| return .patch | ||
| } | ||
| } | ||
|
|
||
| var headers: HeaderType { | ||
| switch self { | ||
| case .fetchChallenges(let userID), | ||
| .advance(let userID), | ||
| .routineToggle(let userID, _): | ||
| return .withAuth(userID: userID) | ||
| } | ||
| } | ||
|
|
||
| var parameterEncoding: any Alamofire.ParameterEncoding { | ||
| switch self { | ||
| case .fetchChallenges: | ||
| return URLEncoding.default | ||
| case .advance, .routineToggle: | ||
| return JSONEncoding.default | ||
| } | ||
| } | ||
|
|
||
| var queryParameters: [String : Any]? { | ||
| return nil | ||
| } | ||
|
|
||
| var bodyParameters: Alamofire.Parameters? { | ||
| return nil | ||
| } | ||
|
|
||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| // | ||
| // DemoRepository.swift | ||
| // Cherrish-iOS | ||
| // | ||
| // Created by 이나연 on 1/21/26. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| struct DefaultDemoRepository: DemoInterface { | ||
| private let networkService: NetworkService | ||
| private let userDefaultService: UserDefaultService | ||
|
|
||
| init( | ||
| networkService: NetworkService, | ||
| userDefaultService: UserDefaultService | ||
| ) { | ||
| self.networkService = networkService | ||
| self.userDefaultService = userDefaultService | ||
| } | ||
|
|
||
| func fetchChallenges() async throws -> ChallengeEntity { | ||
| let userID: Int = userDefaultService.load(key: .userID) ?? 1 | ||
| let response = try await networkService.request( | ||
| DemoAPI.fetchChallenges(userID: userID), | ||
| decodingType: FetchChallengesResponseDTO.self | ||
| ) | ||
|
|
||
| return response.toEntity() | ||
| } | ||
|
|
||
| func advance() async throws -> ChallengeEntity { | ||
| let userID: Int = userDefaultService.load(key: .userID) ?? 1 | ||
| let response = try await networkService.request( | ||
| DemoAPI.advance(userID: userID), | ||
| decodingType: FetchChallengesResponseDTO.self | ||
| ) | ||
| return response.toEntity() | ||
| } | ||
|
|
||
| func toggleRoutine(routineID: Int) async throws -> RoutineEntity { | ||
| let userID: Int = userDefaultService.load(key: .userID) ?? 1 | ||
| let response = try await networkService.request( | ||
| DemoAPI.routineToggle(userID: userID, routineID: routineID), | ||
| decodingType: RoutineToggleResponseDTO.self | ||
| ) | ||
| return response.toEntity() | ||
|
Comment on lines
+22
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🔧 수정 제안+enum DemoRepositoryError: Error {
+ case missingUserID
+}
+
struct DefaultDemoRepository: DemoInterface {
private let networkService: NetworkService
private let userDefaultService: UserDefaultService
@@
func fetchChallenges() async throws -> ChallengeEntity {
- let userID: Int = userDefaultService.load(key: .userID) ?? 1
+ guard let userID: Int = userDefaultService.load(key: .userID) else {
+ throw DemoRepositoryError.missingUserID
+ }
let response = try await networkService.request(
DemoAPI.fetchChallenges(userID: userID),
decodingType: FetchChallengesResponseDTO.self
)
return response.toEntity()
}
func advance() async throws -> ChallengeEntity {
- let userID: Int = userDefaultService.load(key: .userID) ?? 1
+ guard let userID: Int = userDefaultService.load(key: .userID) else {
+ throw DemoRepositoryError.missingUserID
+ }
let response = try await networkService.request(
DemoAPI.advance(userID: userID),
decodingType: FetchChallengesResponseDTO.self
)
return response.toEntity()
}
func toggleRoutine(routineID: Int) async throws -> RoutineEntity {
- let userID: Int = userDefaultService.load(key: .userID) ?? 1
+ guard let userID: Int = userDefaultService.load(key: .userID) else {
+ throw DemoRepositoryError.missingUserID
+ }
let response = try await networkService.request(
DemoAPI.routineToggle(userID: userID, routineID: routineID),
decodingType: RoutineToggleResponseDTO.self
)
return response.toEntity()
}
}🤖 Prompt for AI Agents |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -60,10 +60,26 @@ final class DomainDependencyAssembler: DependencyAssembler { | |
| guard let treatmentRepository = DIContainer.shared.resolve(type: TreatmentInterface.self) else { | ||
| return | ||
| } | ||
|
|
||
| DIContainer.shared.register(type: FetchTreatmentCategoriesUseCase.self) { | ||
| return DefaultFetchTreatmentCategoriesUseCase(repository: treatmentRepository) | ||
| } | ||
|
|
||
| guard let demoRepository = DIContainer.shared.resolve(type: DemoInterface.self) else { | ||
| return | ||
| } | ||
|
|
||
| DIContainer.shared.register(type: FetchChallengeUseCase.self) { | ||
| return DefaultFetchChallengeUseCase(repository: demoRepository) | ||
| } | ||
|
|
||
| DIContainer.shared.register(type: ToggleRoutineUseCase.self) { | ||
| return DefaultToggleRoutineUseCase(repository: demoRepository) | ||
| } | ||
|
|
||
| DIContainer.shared.register(type: AdvanceDayUseCase.self) { | ||
| return DefaultAdvanceDayUseCase(repository: demoRepository) | ||
| } | ||
|
Comment on lines
+68
to
+82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DemoInterface 미해결 시 이후 DI 등록이 끊기는 문제 Line 68-70의 ✅ 제안 수정 (데모만 선택적으로 등록)- guard let demoRepository = DIContainer.shared.resolve(type: DemoInterface.self) else {
- return
- }
-
- DIContainer.shared.register(type: FetchChallengeUseCase.self) {
- return DefaultFetchChallengeUseCase(repository: demoRepository)
- }
-
- DIContainer.shared.register(type: ToggleRoutineUseCase.self) {
- return DefaultToggleRoutineUseCase(repository: demoRepository)
- }
-
- DIContainer.shared.register(type: AdvanceDayUseCase.self) {
- return DefaultAdvanceDayUseCase(repository: demoRepository)
- }
+ if let demoRepository = DIContainer.shared.resolve(type: DemoInterface.self) {
+ DIContainer.shared.register(type: FetchChallengeUseCase.self) {
+ return DefaultFetchChallengeUseCase(repository: demoRepository)
+ }
+
+ DIContainer.shared.register(type: ToggleRoutineUseCase.self) {
+ return DefaultToggleRoutineUseCase(repository: demoRepository)
+ }
+
+ DIContainer.shared.register(type: AdvanceDayUseCase.self) {
+ return DefaultAdvanceDayUseCase(repository: demoRepository)
+ }
+ }🤖 Prompt for AI Agents |
||
|
|
||
| DIContainer.shared.register(type: FetchTreatmentsUseCase.self) { | ||
| return DefaultFetchTreatmentsUseCase(repository: treatmentRepository) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // | ||
| // DemoInterface.swift | ||
| // Cherrish-iOS | ||
| // | ||
| // Created by 이나연 on 1/21/26. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| protocol DemoInterface { | ||
| func fetchChallenges() async throws -> ChallengeEntity | ||
| func advance() async throws -> ChallengeEntity | ||
| func toggleRoutine(routineID: Int) async throws -> RoutineEntity | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // | ||
| // ChallengeEntity.swift | ||
| // Cherrish-iOS | ||
| // | ||
| // Created by 이나연 on 1/21/26. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| struct ChallengeEntity { | ||
| let challengeID: Int | ||
| let title: String | ||
| let currentDay: Int | ||
| let progressPercentage: Int | ||
| let cherryLevel: Int | ||
| let cherryLevelName: String | ||
| let progressToNextLevel: Double | ||
| let remainingRoutinesToNextLevel: Int | ||
| let todayRoutines: [RoutineEntity] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // | ||
| // RoutineEntity.swift | ||
| // Cherrish-iOS | ||
| // | ||
| // Created by 이나연 on 1/21/26. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| struct RoutineEntity { | ||
| let routineID: Int | ||
| let name: String | ||
| let isComplete: Bool | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // | ||
| // AdvanceDayUseCase.swift | ||
| // Cherrish-iOS | ||
| // | ||
| // Created by 송성용 on 1/21/26. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| protocol AdvanceDayUseCase { | ||
| func execute() async throws -> ChallengeEntity | ||
| } | ||
|
|
||
| struct DefaultAdvanceDayUseCase: AdvanceDayUseCase { | ||
| private let repository: DemoInterface | ||
|
|
||
| init(repository: DemoInterface) { | ||
| self.repository = repository | ||
| } | ||
|
|
||
| func execute() async throws -> ChallengeEntity { | ||
| try await repository.advance() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // | ||
| // FetchChallengeUseCase.swift | ||
| // Cherrish-iOS | ||
| // | ||
| // Created by 송성용 on 1/21/26. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| protocol FetchChallengeUseCase { | ||
| func execute() async throws -> ChallengeEntity | ||
| } | ||
|
|
||
| struct DefaultFetchChallengeUseCase: FetchChallengeUseCase { | ||
| private let repository: DemoInterface | ||
|
|
||
| init(repository: DemoInterface) { | ||
| self.repository = repository | ||
| } | ||
|
|
||
| func execute() async throws -> ChallengeEntity { | ||
| try await repository.fetchChallenges() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // | ||
| // ToggleRoutineUseCase.swift | ||
| // Cherrish-iOS | ||
| // | ||
| // Created by 송성용 on 1/21/26. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| protocol ToggleRoutineUseCase { | ||
| func execute(routineID: Int) async throws -> RoutineEntity | ||
| } | ||
|
|
||
| struct DefaultToggleRoutineUseCase: ToggleRoutineUseCase { | ||
| private let repository: DemoInterface | ||
|
|
||
| init(repository: DemoInterface) { | ||
| self.repository = repository | ||
| } | ||
|
|
||
| func execute(routineID: Int) async throws -> RoutineEntity { | ||
| try await repository.toggleRoutine(routineID: routineID) | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.