From bfd83c7368917e82dceef6ccc4d4204328e96212 Mon Sep 17 00:00:00 2001 From: yeonee Date: Tue, 20 Jan 2026 23:56:50 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20#100=20=EC=9D=98=EC=A1=B4=EC=84=B1?= =?UTF-8?q?=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cherrish-iOS/Data/DataDependencyAssembler.swift | 7 ++++++- .../Cherrish-iOS/Domain/DomainDependencyAssembler.swift | 8 ++++++++ .../Presentation/PresentationDependencyAssembler.swift | 8 ++++++++ Cherrish-iOS/Cherrish-iOS/Presentation/ViewFactory.swift | 5 ++++- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift index 6090a47e..4aa59b1f 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift @@ -42,6 +42,11 @@ final class DataDependencyAssembler: DependencyAssembler { return DefaultTreatmentRepository(networkService: self.networkService, userDefaultService: self.userDefaultService) } - + DIContainer.shared.register(type: MyPageInterface.self) { + return DefaultMyPageRepository( + networkService: self.networkService, + userDefaultService: self.userDefaultService + ) + } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift index 1b8726cd..f8160306 100644 --- a/Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift @@ -68,5 +68,13 @@ final class DomainDependencyAssembler: DependencyAssembler { DIContainer.shared.register(type: FetchTreatmentsUseCase.self) { return DefaultFetchTreatmentsUseCase(repository: treatmentRepository) } + + guard let myPageRepository = DIContainer.shared.resolve(type: MyPageInterface.self) else { + return + } + + DIContainer.shared.register(type: FetchUserInfoUseCase.self) { + return DefaultFetchUserInfoUserCase(repository: myPageRepository) + } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift index d491900a..6c5b75a3 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift @@ -71,5 +71,13 @@ final class PresentationDependencyAssembler: DependencyAssembler { DIContainer.shared.register(type: TreatmentViewModel.self) { return TreatmentViewModel(fetchTreatmentsUseCase: fetchTreatmentsUseCase) } + + guard let fetchUserInfoUseCase = DIContainer.shared.resolve(type: FetchUserInfoUseCase.self) else { + return + } + + DIContainer.shared.register(type: MyPageViewModel.self) { + return MyPageViewModel(fetchUserInfoUseCase: fetchUserInfoUseCase) + } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/ViewFactory.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/ViewFactory.swift index 3bd8ec20..ca56d8a8 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/ViewFactory.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/ViewFactory.swift @@ -62,7 +62,10 @@ final class ViewFactory: ViewFactoryProtocol { } func makeMyPageView() -> MyPageView { - return MyPageView() + guard let viewModel = DIContainer.shared.resolve(type: MyPageViewModel.self) else { + fatalError() + } + return MyPageView(viewModel: viewModel) } func makeSelectTreatmentView() -> SelectTreatmentView { From fe53b51d84e5d032825babdc3cd312f96dc51ea9 Mon Sep 17 00:00:00 2001 From: yeonee Date: Tue, 20 Jan 2026 23:57:14 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20#100=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20API=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Model/UserInfoResponseDTO.swift | 19 ++++++ .../Data/Network/EndPoint/MyPageAPI.swift | 58 +++++++++++++++++++ .../Data/Repository/MyPageRepository.swift | 30 ++++++++++ .../Domain/Interface/MyPageInterface.swift | 12 ++++ .../Domain/Model/UserInfoEntity.swift | 13 +++++ .../Domain/UseCase/FetchUserInfoUseCase.swift | 24 ++++++++ .../Feature/MyPage/MyPageView.swift | 13 ++++- .../Feature/MyPage/MyPageViewModel.swift | 25 ++++++++ 8 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 Cherrish-iOS/Cherrish-iOS/Data/Model/UserInfoResponseDTO.swift create mode 100644 Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/MyPageAPI.swift create mode 100644 Cherrish-iOS/Cherrish-iOS/Data/Repository/MyPageRepository.swift create mode 100644 Cherrish-iOS/Cherrish-iOS/Domain/Interface/MyPageInterface.swift create mode 100644 Cherrish-iOS/Cherrish-iOS/Domain/Model/UserInfoEntity.swift create mode 100644 Cherrish-iOS/Cherrish-iOS/Domain/UseCase/FetchUserInfoUseCase.swift create mode 100644 Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageViewModel.swift diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Model/UserInfoResponseDTO.swift b/Cherrish-iOS/Cherrish-iOS/Data/Model/UserInfoResponseDTO.swift new file mode 100644 index 00000000..c630721f --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Data/Model/UserInfoResponseDTO.swift @@ -0,0 +1,19 @@ +// +// UserInfoResponseDTO.swift +// Cherrish-iOS +// +// Created by 이나연 on 1/20/26. +// + +import Foundation + +struct UserInfoResponseDTO: Decodable { + let name: String + let daysSinceSignup: Int +} + +extension UserInfoResponseDTO { + func toEntity() -> UserInfoEntity { + .init(name: name, daysSinceSignup: daysSinceSignup) + } +} diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/MyPageAPI.swift b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/MyPageAPI.swift new file mode 100644 index 00000000..98935bb9 --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/MyPageAPI.swift @@ -0,0 +1,58 @@ +// +// MyPageAPI.swift +// Cherrish-iOS +// +// Created by 이나연 on 1/20/26. +// + +import Foundation + +import Alamofire + +enum MyPageAPI { + case users(userID: Int) +} + +extension MyPageAPI: EndPoint { + var basePath: String { + return "/api" + } + + var path: String { + switch self { + case .users: + return "/users" + } + } + + var method: Alamofire.HTTPMethod { + switch self { + case .users: + return .get + } + } + + var headers: HeaderType { + switch self { + case .users(let userID): + return .withAuth(userID: userID) + } + } + + var parameterEncoding: any Alamofire.ParameterEncoding { + switch self { + case .users: + return URLEncoding.default + } + } + + var queryParameters: [String : Any]? { + return nil + } + + var bodyParameters: Alamofire.Parameters? { + return nil + } + + +} diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Repository/MyPageRepository.swift b/Cherrish-iOS/Cherrish-iOS/Data/Repository/MyPageRepository.swift new file mode 100644 index 00000000..32a25075 --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Data/Repository/MyPageRepository.swift @@ -0,0 +1,30 @@ +// +// MyPageRepository.swift +// Cherrish-iOS +// +// Created by 이나연 on 1/20/26. +// + +import Foundation + +struct DefaultMyPageRepository: MyPageInterface { + private let networkService: NetworkService + private let userDefaultService: UserDefaultService + + init( + networkService: NetworkService, + userDefaultService: UserDefaultService + ) { + self.networkService = networkService + self.userDefaultService = userDefaultService + } + + func fetchUserInfo() async throws -> UserInfoEntity { + let userID: Int = userDefaultService.load(key: .userID) ?? 1 + let response = try await networkService.request( + MyPageAPI.users(userID: userID), + decodingType: UserInfoResponseDTO.self) + + return response.toEntity() + } +} diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/Interface/MyPageInterface.swift b/Cherrish-iOS/Cherrish-iOS/Domain/Interface/MyPageInterface.swift new file mode 100644 index 00000000..18095358 --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Domain/Interface/MyPageInterface.swift @@ -0,0 +1,12 @@ +// +// MyPageInterface.swift +// Cherrish-iOS +// +// Created by 이나연 on 1/20/26. +// + +import Foundation + +protocol MyPageInterface { + func fetchUserInfo() async throws -> UserInfoEntity +} diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/Model/UserInfoEntity.swift b/Cherrish-iOS/Cherrish-iOS/Domain/Model/UserInfoEntity.swift new file mode 100644 index 00000000..b7ce916b --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Domain/Model/UserInfoEntity.swift @@ -0,0 +1,13 @@ +// +// UserInfoEntity.swift +// Cherrish-iOS +// +// Created by 이나연 on 1/20/26. +// + +import Foundation + +struct UserInfoEntity { + let name: String + let daysSinceSignup: Int +} diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/FetchUserInfoUseCase.swift b/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/FetchUserInfoUseCase.swift new file mode 100644 index 00000000..80991048 --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/FetchUserInfoUseCase.swift @@ -0,0 +1,24 @@ +// +// FetchUserInfoUseCase.swift +// Cherrish-iOS +// +// Created by 이나연 on 1/20/26. +// + +import Foundation + +protocol FetchUserInfoUseCase { + func execute() async throws -> UserInfoEntity +} + +struct DefaultFetchUserInfoUserCase: FetchUserInfoUseCase { + private let repository: MyPageInterface + + init(repository: MyPageInterface) { + self.repository = repository + } + + func execute() async throws -> UserInfoEntity { + return try await repository.fetchUserInfo() + } +} diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift index 9f3c60ea..812a4419 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageView.swift @@ -8,6 +8,8 @@ import SwiftUI struct MyPageView: View { + @StateObject var viewModel: MyPageViewModel + var body: some View { VStack { Spacer() @@ -18,6 +20,13 @@ struct MyPageView: View { .padding(.horizontal, 35) grayEmptyBar } + .task { + do { + try await viewModel.fetchUserInfo() + } catch { + CherrishLogger.error(error) + } + } } } @@ -29,10 +38,10 @@ extension MyPageView { .frame(width: 48.adjustedW, height: 48.adjustedH) VStack(alignment: .leading, spacing: 0){ - TypographyText("안녕하세요, 김채채 님", style: .title1_sb_18, color: .gray1000) + TypographyText("안녕하세요, \(viewModel.name)님", style: .title1_sb_18, color: .gray1000) .frame(height: 27.adjustedH) - TypographyText("관리 시작 D + 13", style: .body1_m_14, color: .gray800) + TypographyText("관리 시작 D + \(viewModel.day)", style: .body1_m_14, color: .gray800) .frame(height: 20.adjustedH) } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageViewModel.swift new file mode 100644 index 00000000..54a09637 --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageViewModel.swift @@ -0,0 +1,25 @@ +// +// MyPageViewModel.swift +// Cherrish-iOS +// +// Created by 이나연 on 1/20/26. +// + +import Foundation + +final class MyPageViewModel: ObservableObject { + @Published private(set) var name: String = "" + @Published private(set) var day: Int = 1 + + private let fetchUserInfoUseCase: FetchUserInfoUseCase + + init(fetchUserInfoUseCase: FetchUserInfoUseCase) { + self.fetchUserInfoUseCase = fetchUserInfoUseCase + } + + func fetchUserInfo() async throws { + let response = try await fetchUserInfoUseCase.execute() + name = response.name + day = response.daysSinceSignup + } +} From 366c107e61f8e2d18f39645ccc51aa1283ea4157 Mon Sep 17 00:00:00 2001 From: yeonee Date: Wed, 21 Jan 2026 06:07:59 +0900 Subject: [PATCH 3/4] =?UTF-8?q?refactor:=20#100=20main=20actor=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Feature/MyPage/MyPageViewModel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageViewModel.swift index 54a09637..003b8a1a 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/MyPage/MyPageViewModel.swift @@ -17,6 +17,7 @@ final class MyPageViewModel: ObservableObject { self.fetchUserInfoUseCase = fetchUserInfoUseCase } + @MainActor func fetchUserInfo() async throws { let response = try await fetchUserInfoUseCase.execute() name = response.name From 632ef3a61c74b307f104cfce302ef4ec5fc3b50e Mon Sep 17 00:00:00 2001 From: yeonee Date: Wed, 21 Jan 2026 06:14:03 +0900 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20#100=20=EB=B9=8C=EB=93=9C=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Feature/Onboarding/SplashView.swift | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Onboarding/SplashView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Onboarding/SplashView.swift index c2be14aa..24193cc7 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Onboarding/SplashView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Onboarding/SplashView.swift @@ -10,13 +10,7 @@ import SwiftUI struct SplashView: View { @EnvironmentObject private var appCoordinator: AppCoordinator private let userDefaultService: UserDefaultService = DefaultUserDefaultService() - - private let userDefaultService: UserDefaultService - - init(userDefaultService: UserDefaultService = DefaultUserDefaultService()) { - self.userDefaultService = userDefaultService - } - + var body: some View { ZStack(alignment: .center) { LinearGradient(