From 3a835c4c72aa16d3b7086ecfba7b9f8ae190d8a6 Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Tue, 20 Jan 2026 15:54:29 +0900 Subject: [PATCH 01/11] =?UTF-8?q?feat:=20#114=20=EB=84=A4=ED=8A=B8?= =?UTF-8?q?=EC=9B=8C=ED=81=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/DataDependencyAssembler.swift | 4 +- .../Data/Model/ProcedureResponseDTO.swift | 36 +++++++ .../Data/Network/EndPoint/TreatmentAPI.swift | 88 +++++++++++++++++ .../Data/Repository/TreatmentRepository.swift | 16 +++ .../Domain/DomainDependencyAssembler.swift | 8 +- .../Domain/Interface/TreatmentInterface.swift | 1 + .../Domain/Model/TreatmentEntity.swift | 97 +------------------ .../UseCase/FetchTreatmentsUseCase.swift | 25 +++++ .../NoTreatment/NoTreatmentFilterView.swift | 3 + .../NoTreatment/NoTreatmentViewModel.swift | 73 +++++++++----- .../Treatment/TreatmentViewModel.swift | 2 +- .../PresentationDependencyAssembler.swift | 8 +- 12 files changed, 238 insertions(+), 123 deletions(-) create mode 100644 Cherrish-iOS/Cherrish-iOS/Data/Model/ProcedureResponseDTO.swift create mode 100644 Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift create mode 100644 Cherrish-iOS/Cherrish-iOS/Domain/UseCase/FetchTreatmentsUseCase.swift diff --git a/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift index 8e587531..2dcff7ff 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift @@ -24,7 +24,9 @@ final class DataDependencyAssembler: DependencyAssembler { } DIContainer.shared.register(type: TreatmentInterface.self) { - return MockTreatmentRepository() + return DefaultTreatmentRepository(networkService: self.networkService) } + + } } diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Model/ProcedureResponseDTO.swift b/Cherrish-iOS/Cherrish-iOS/Data/Model/ProcedureResponseDTO.swift new file mode 100644 index 00000000..b281f19e --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Data/Model/ProcedureResponseDTO.swift @@ -0,0 +1,36 @@ +// +// ProcedureResponseDTO.swift +// Cherrish-iOS +// +// Created by 어재선 on 1/20/26. +// + +import Foundation + +struct ProcedureDTO: Decodable { + let id: Int + let name: String + let worries: [TreatmentCategoryResponseDTO] + let minDowntimeDays: Int + let maxDowntimeDays: Int +} + +struct ProceduresResponseDTO: Decodable { + let procedures: [ProcedureDTO] +} + + +extension ProcedureDTO { + func toEntity() -> TreatmentEntity { + return TreatmentEntity( + id: id, + name: name, + benefits: worries.map { + $0.toEntity().title + }, + downtimeMin: minDowntimeDays, + downtimeMax: maxDowntimeDays, + setDowntime: nil + ) + } +} diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift new file mode 100644 index 00000000..960a4665 --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift @@ -0,0 +1,88 @@ +// +// TreatmentAPI.swift +// Cherrish-iOS +// +// Created by 어재선 on 1/20/26. +// + +import Foundation +import Alamofire + +enum TreatmentAPI: EndPoint { + case fetchCategories + case fetchProcedures(id: Int?, text: String?) + + var basePath: String { + switch self { + case .fetchCategories: + return "/api" + + case .fetchProcedures: + return "/api" + } + } + + var path: String { + switch self { + case .fetchCategories: + return "/worries" + case .fetchProcedures: + return "/procedures" + } + } + + var method: Alamofire.HTTPMethod { + switch self { + case .fetchCategories: + return .get + case .fetchProcedures: + return .get + } + } + + var headers: HeaderType { + switch self { + case .fetchCategories: + return .basic + case .fetchProcedures: + return .basic + } + } + + + var parameterEncoding: any Alamofire.ParameterEncoding { + switch self { + case .fetchCategories: + return JSONEncoding.default + case .fetchProcedures: + return JSONEncoding.default + } + } + + var queryParameters: [String : String]? { + switch self { + case .fetchCategories: + return nil + case .fetchProcedures(let id, let text): + var params: [String: String] = [:] + if let id = id { + params["worryId"] = "\(id)" + } + if let text = text { + params["keyword"] = "\(text)" + } + return params + } + } + + var bodyParameters: Alamofire.Parameters? { + switch self { + case .fetchCategories: + return .none + case .fetchProcedures: + return .none + } + } + + +} diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift b/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift index dc6e343b..c7e73f49 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift @@ -8,12 +8,28 @@ import Foundation struct DefaultTreatmentRepository: TreatmentInterface { + + private let networkService: NetworkService + + init(networkService: NetworkService) { + self.networkService = networkService + } + func fetchCategories() async throws -> [TreatmentCategoryEntity] { return [] } + + func fetchTreatment(id: Int?, keyword: String?) async throws -> [TreatmentEntity] { + let response = try await networkService.request(TreatmentAPI.fetchProcedures(id: id, text: keyword), decodingType: ProceduresResponseDTO.self) + return response.procedures.map { $0.toEntity() } + } } struct MockTreatmentRepository: TreatmentInterface { + func fetchTreatment(id: Int?, keyword: String?) async throws -> [TreatmentEntity] { + return [] + } + func fetchCategories() async throws -> [TreatmentCategoryEntity] { return [ TreatmentCategoryEntity(id: 1, title: "피부결 ∙ 각질"), diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift index 75d9a489..35d0c97a 100644 --- a/Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift @@ -37,12 +37,16 @@ final class DomainDependencyAssembler: DependencyAssembler { return DefaultFetchTodayProcedure(repository: calendarRepository) } - guard let treatmentCategoryRepository = DIContainer.shared.resolve(type: TreatmentInterface.self) else { + guard let treatmentRepository = DIContainer.shared.resolve(type: TreatmentInterface.self) else { return } DIContainer.shared.register(type: FetchTreatmentCategoriesUseCase.self) { - return DefaultFetchTreatmentCategoriesUseCase(repository: treatmentCategoryRepository) + return DefaultFetchTreatmentCategoriesUseCase(repository: treatmentRepository) + } + + DIContainer.shared.register(type: FetchTreatmentsUseCase.self) { + return DefaultFetchTreatmentsUseCase(repository: treatmentRepository) } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/Interface/TreatmentInterface.swift b/Cherrish-iOS/Cherrish-iOS/Domain/Interface/TreatmentInterface.swift index 46930e80..f715e020 100644 --- a/Cherrish-iOS/Cherrish-iOS/Domain/Interface/TreatmentInterface.swift +++ b/Cherrish-iOS/Cherrish-iOS/Domain/Interface/TreatmentInterface.swift @@ -9,4 +9,5 @@ import Foundation protocol TreatmentInterface { func fetchCategories() async throws -> [TreatmentCategoryEntity] + func fetchTreatment(id: Int?, keyword: String?) async throws -> [TreatmentEntity] } diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/Model/TreatmentEntity.swift b/Cherrish-iOS/Cherrish-iOS/Domain/Model/TreatmentEntity.swift index 3f5431cf..ce1932a6 100644 --- a/Cherrish-iOS/Cherrish-iOS/Domain/Model/TreatmentEntity.swift +++ b/Cherrish-iOS/Cherrish-iOS/Domain/Model/TreatmentEntity.swift @@ -8,103 +8,10 @@ import Foundation struct TreatmentEntity: Identifiable, Equatable, Hashable { - var id: Self { self } + let id: Int let name: String let benefits: [String] let downtimeMin: Int let downtimeMax: Int -} - -extension TreatmentEntity { - static let mockData: [TreatmentEntity] = [ - // 피부결 · 각질 - TreatmentEntity( - name: "아쿠아필", - benefits: ["각질 제거", "모공 청소", "피부결 개선"], - downtimeMin: 0, - downtimeMax: 1 - ), - TreatmentEntity( - name: "크리스탈 필링", - benefits: ["각질 제거", "피부 톤 개선", "잔주름 완화"], - downtimeMin: 1, - downtimeMax: 3 - ), - - // 색소 · 잡티 - TreatmentEntity( - name: "피코토닝", - benefits: ["색소 침착 개선", "잡티 제거", "피부 톤 균일화"], - downtimeMin: 0, - downtimeMax: 1 - ), - TreatmentEntity( - name: "레이저토닝", - benefits: ["기미 개선", "색소 침착 완화", "피부 톤 업"], - downtimeMin: 1, - downtimeMax: 2 - ), - - // 홍조 - TreatmentEntity( - name: "브이빔 레이저", - benefits: ["홍조 완화", "혈관 축소", "피부 진정"], - downtimeMin: 1, - downtimeMax: 3 - ), - TreatmentEntity( - name: "엑셀브이", - benefits: ["홍조 개선", "안면홍조 치료", "혈관 병변 제거"], - downtimeMin: 2, - downtimeMax: 5 - ), - - // 탄력 · 주름 - TreatmentEntity( - name: "울쎄라", - benefits: ["리프팅", "탄력 개선", "주름 완화"], - downtimeMin: 3, - downtimeMax: 7 - ), - TreatmentEntity( - name: "써마지", - benefits: ["피부 탄력", "콜라겐 생성", "처진 피부 개선"], - downtimeMin: 0, - downtimeMax: 2 - ), - TreatmentEntity( - name: "보톡스", - benefits: ["주름 개선", "이마 주름", "미간 주름"], - downtimeMin: 0, - downtimeMax: 1 - ), - - // 모공 - TreatmentEntity( - name: "프락셀", - benefits: ["모공 축소", "피부 재생", "흉터 개선"], - downtimeMin: 5, - downtimeMax: 7 - ), - TreatmentEntity( - name: "모공보톡스", - benefits: ["모공 축소", "피지 조절", "매끈한 피부"], - downtimeMin: 0, - downtimeMax: 1 - ), - - // 트러블 - TreatmentEntity( - name: "PDT", - benefits: ["여드름 치료", "피지 조절", "염증 완화"], - downtimeMin: 2, - downtimeMax: 5 - ), - TreatmentEntity( - name: "압출 관리", - benefits: ["여드름 제거", "모공 청소", "피부 진정"], - downtimeMin: 1, - downtimeMax: 3 - ) - ] + let setDowntime: Int? } diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/FetchTreatmentsUseCase.swift b/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/FetchTreatmentsUseCase.swift new file mode 100644 index 00000000..75aead51 --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/FetchTreatmentsUseCase.swift @@ -0,0 +1,25 @@ +// +// FetchTreatmentsUseCase.swift +// Cherrish-iOS +// +// Created by 어재선 on 1/20/26. +// + +import Foundation + +protocol FetchTreatmentsUseCase { + func execute(id: Int?, keyword: String?) async throws -> [TreatmentEntity] +} + +struct DefaultFetchTreatmentsUseCase: FetchTreatmentsUseCase { + + private let repository: TreatmentInterface + + init(repository: TreatmentInterface) { + self.repository = repository + } + + func execute(id: Int?, keyword: String?) async throws -> [TreatmentEntity] { + return try await repository.fetchTreatment(id: id, keyword: keyword) + } +} diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentFilterView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentFilterView.swift index 77111e4d..eaaeddc0 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentFilterView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentFilterView.swift @@ -33,6 +33,9 @@ struct NoTreatmentFilterView: View { } } } + .task { + await viewModel.testfetchTreatments() + } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift index 23199495..aad93b10 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift @@ -15,29 +15,31 @@ final class NoTreatmentViewModel: ObservableObject{ @Published var year: String = "" @Published var month: String = "" @Published var day: String = "" - @Published var treatments: [TreatmentEntity] = TreatmentEntity.mockData - @Published var selectedTreatments: [TreatmentEntity] = [] + @Published private(set) var treatments: [TreatmentEntity] = [] + @Published private(set) var selectedTreatments: [TreatmentEntity] = [] private let fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase + private let fetchTreatmentsUseCase: FetchTreatmentsUseCase var step: Int { state.rawValue } var canProceed: Bool { - switch state { - case .treatmentSelectedCategory: - return selectedCategory != nil - case .targetDdaySetting: - return isDateTextFieldNotEmpty() - case .treatmentFilter: - return !selectedTreatments.isEmpty - case .downTimeSetting: - return true - } - } - - init(fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase) { - self.fetchCategoriesUseCase = fetchCategoriesUseCase + switch state { + case .treatmentSelectedCategory: + return selectedCategory != nil + case .targetDdaySetting: + return isDateTextFieldNotEmpty() + case .treatmentFilter: + return !selectedTreatments.isEmpty + case .downTimeSetting: + return true } + } + + init(fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase, fetchTreatmentsUseCase: FetchTreatmentsUseCase) { + self.fetchCategoriesUseCase = fetchCategoriesUseCase + self.fetchTreatmentsUseCase = fetchTreatmentsUseCase + } var today: (year: Int, month: Int, day: Int) { let calendar = Calendar.current @@ -59,16 +61,25 @@ final class NoTreatmentViewModel: ObservableObject{ @MainActor func loadCategories() async { - do { - categories = try await fetchCategoriesUseCase.execute() - } catch { - - } + do { + categories = try await fetchCategoriesUseCase.execute() + } catch { + } + } + + @MainActor + func testfetchTreatments() async { + do { + treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: "") + } catch { + treatments = [] + } + } func selectCategory(_ category: TreatmentCategoryEntity) { - selectedCategory = category - } + selectedCategory = category + } func toInt(_ value: String) -> Int { Int(value) ?? 0 @@ -94,5 +105,21 @@ final class NoTreatmentViewModel: ObservableObject{ return true } + +} + +extension NoTreatmentViewModel { + + func addTreatment(_ treatment: TreatmentEntity) { + guard !isSelected(treatment) else { return } + selectedTreatments.append(treatment) + } + + func removeTreatment(_ treatment: TreatmentEntity) { + selectedTreatments.removeAll { $0.id == treatment.id } + } + func isSelected(_ treatment: TreatmentEntity) -> Bool { + selectedTreatments.contains(where: { $0.id == treatment.id }) + } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift index 20ea6ad9..830db439 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift @@ -14,7 +14,7 @@ final class TreatmentViewModel: ObservableObject{ @Published var year: String = "" @Published var month: String = "" @Published var day: String = "" - @Published var treatments: [TreatmentEntity] = TreatmentEntity.mockData + @Published var treatments: [TreatmentEntity] = [] @Published var selectedTreatments: [TreatmentEntity] = [] @Published var searchText = "" @Published var filteredTreatments: [TreatmentEntity] = [] diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift index efe6d323..d8016240 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift @@ -43,10 +43,16 @@ final class PresentationDependencyAssembler: DependencyAssembler { return HomeViewModel(fetchDashboardDataUseCase: fetchDashboardData) } + guard let fetchTreatmentsUseCase = DIContainer.shared.resolve(type: FetchTreatmentsUseCase.self) else { + return + } + DIContainer.shared.register(type: NoTreatmentViewModel.self) { let repository = MockTreatmentRepository() let useCase = DefaultFetchTreatmentCategoriesUseCase(repository: repository) - return NoTreatmentViewModel(fetchCategoriesUseCase: useCase) + + + return NoTreatmentViewModel(fetchCategoriesUseCase: useCase,fetchTreatmentsUseCase: fetchTreatmentsUseCase) } } } From 236af340541f9b4fea5cb1a8d5977ce55fe98e8b Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Tue, 20 Jan 2026 15:54:47 +0900 Subject: [PATCH 02/11] =?UTF-8?q?fix:=20#114=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NoTreatmentViewModel+Filter.swift | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel+Filter.swift diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel+Filter.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel+Filter.swift deleted file mode 100644 index bea06940..00000000 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel+Filter.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// NoTreatmentViewModel+Filter.swift -// Cherrish-iOS -// -// Created by 어재선 on 1/16/26. -// - -import Foundation - -extension NoTreatmentViewModel { - - func addTreatment(_ treatment: TreatmentEntity) { - guard !isSelected(treatment) else { return } - selectedTreatments.append(treatment) - } - - func removeTreatment(_ treatment: TreatmentEntity) { - selectedTreatments.removeAll { $0.id == treatment.id } - } - func isSelected(_ treatment: TreatmentEntity) -> Bool { - selectedTreatments.contains(where: { $0.id == treatment.id }) - } -} From 2ecdc12f78bc4a2070cdcab56e30f26181ec9b5d Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Tue, 20 Jan 2026 23:23:51 +0900 Subject: [PATCH 03/11] =?UTF-8?q?feat:=20#114=20=EC=8B=9C=EC=88=A0=20?= =?UTF-8?q?=ED=95=84=ED=84=B0=20=EB=84=A4=ED=8A=B8=EC=9B=8C=ED=81=AC=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Network/EndPoint/TreatmentAPI.swift | 8 ++-- .../Domain/Model/TreatmentEntity.swift | 9 +++- .../Treatment/View/DownTimeSettingView.swift | 26 ++++++----- .../View/DowntimeBottomSheetView.swift | 17 +++++-- .../NoTreatment/NoTreatmentFilterView.swift | 2 +- .../View/NoTreatment/NoTreatmentView.swift | 7 ++- .../View/Treatment/TreatmentFilterView.swift | 42 +++++++++-------- .../View/Treatment/TreatmentView.swift | 2 +- .../NoTreatment/NoTreatmentViewModel.swift | 24 +++++----- .../Treatment/TreatmentViewModel+Filter.swift | 23 ---------- .../Treatment/TreatmentViewModel+Search.swift | 36 --------------- .../Treatment/TreatmentViewModel.swift | 45 ++++++++++++++----- .../PresentationDependencyAssembler.swift | 3 +- 13 files changed, 114 insertions(+), 130 deletions(-) delete mode 100644 Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel+Filter.swift delete mode 100644 Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel+Search.swift diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift index 960a4665..57ec0c3b 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift @@ -10,7 +10,7 @@ import Alamofire enum TreatmentAPI: EndPoint { case fetchCategories - case fetchProcedures(id: Int?, text: String?) + case fetchProcedures(id: Int? = nil, text: String? = nil) var basePath: String { switch self { @@ -59,14 +59,14 @@ enum TreatmentAPI: EndPoint { } } - var queryParameters: [String : String]? { + var queryParameters: [String : Any]? { switch self { case .fetchCategories: return nil case .fetchProcedures(let id, let text): - var params: [String: String] = [:] + var params: [String: Any] = [:] if let id = id { - params["worryId"] = "\(id)" + params["worryId"] = id } if let text = text { params["keyword"] = "\(text)" diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/Model/TreatmentEntity.swift b/Cherrish-iOS/Cherrish-iOS/Domain/Model/TreatmentEntity.swift index ce1932a6..3f76c349 100644 --- a/Cherrish-iOS/Cherrish-iOS/Domain/Model/TreatmentEntity.swift +++ b/Cherrish-iOS/Cherrish-iOS/Domain/Model/TreatmentEntity.swift @@ -13,5 +13,12 @@ struct TreatmentEntity: Identifiable, Equatable, Hashable { let benefits: [String] let downtimeMin: Int let downtimeMax: Int - let setDowntime: Int? + var setDowntime: Int? + + mutating func updateDowntime(_ value: Int) { + setDowntime = value + } } + + + diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DownTimeSettingView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DownTimeSettingView.swift index 53f15a87..3454b24a 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DownTimeSettingView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DownTimeSettingView.swift @@ -9,9 +9,10 @@ import SwiftUI struct DownTimeSettingView: View { @State var selectedTreatment: TreatmentEntity? = nil - var treatments: [TreatmentEntity] + @Binding var treatments: [TreatmentEntity] let setday: (year: Int, month: Int, day: Int) let today: (year: Int, month: Int, day: Int) + var body: some View { VStack { Spacer() @@ -39,7 +40,7 @@ struct DownTimeSettingView: View { ), isCompleted: .constant( - false + treatment.setDowntime == nil ? false : true ), action: { selectedTreatment = treatment @@ -84,14 +85,19 @@ struct DownTimeSettingView: View { } .padding(.horizontal, 25.adjustedW) .sheet(item: $selectedTreatment) { treatment in - DowntimeBottomSheetView( - treatment: treatment, - today: today, - setday: setday - ) - .presentationDetents([.extraLarge]) - .presentationBackground(.gray0) - .presentationDragIndicator(.visible) + if let index = treatments.firstIndex(where: { $0.id == treatment.id }) { + DowntimeBottomSheetView( + treatment: $treatments[index], + selectedTreatment: $selectedTreatment, + today: today, + setday: setday + ) + .presentationDetents([.extraLarge]) + .presentationBackground(.gray0) + .presentationDragIndicator(.visible) + } + + } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DowntimeBottomSheetView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DowntimeBottomSheetView.swift index 1b446ee7..87b332c0 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DowntimeBottomSheetView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DowntimeBottomSheetView.swift @@ -8,13 +8,15 @@ import SwiftUI struct DowntimeBottomSheetView: View { - let treatment: TreatmentEntity + @Binding var treatment: TreatmentEntity + @Binding var selectedTreatment: TreatmentEntity? let today: (year: Int, month: Int, day: Int) let setday: (year: Int, month: Int, day: Int) @State private var selectedDowntime: Int = 1 @State private var rate: Double = 0.0 @State private var betweenDays: Int = 0 + var body: some View { VStack(spacing: 0) { Spacer() @@ -61,7 +63,7 @@ struct DowntimeBottomSheetView: View { } extension DowntimeBottomSheetView { - + private var speechBubble: some View { ZStack { Image(.speechBubble) @@ -183,7 +185,11 @@ extension DowntimeBottomSheetView { ), leadingIcon: .none, trailingIcon: .none, - action: { }) + action: { + treatment.updateDowntime(0) + selectedTreatment = nil + + }) .frame(width: geo.size.width * 2/3 - 2) CherrishButton( @@ -194,7 +200,10 @@ extension DowntimeBottomSheetView { ), leadingIcon: .none, trailingIcon: .none, - action: { }) + action: { + treatment.updateDowntime(selectedDowntime) + selectedTreatment = nil + }) .frame( width: geo.size.width * 1/3 - 2 ) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentFilterView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentFilterView.swift index eaaeddc0..5b343f66 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentFilterView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentFilterView.swift @@ -34,7 +34,7 @@ struct NoTreatmentFilterView: View { } } .task { - await viewModel.testfetchTreatments() + await viewModel.fetchNoTreatments() } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentView.swift index 81b5be44..7cf36215 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/NoTreatment/NoTreatmentView.swift @@ -10,7 +10,7 @@ import SwiftUI struct NoTreatmentView: View { @EnvironmentObject private var calendarCoordinator: CalendarCoordinator @EnvironmentObject private var tabBarCoordinator: TabBarCoordinator - @ObservedObject var viewModel: NoTreatmentViewModel + @StateObject var viewModel: NoTreatmentViewModel var body: some View { VStack(spacing: 0) { @@ -50,7 +50,7 @@ struct NoTreatmentView: View { } .ignoresSafeArea(.keyboard) .task { - await viewModel.loadCategories() + await viewModel.fetchCategories() } .onAppear { tabBarCoordinator.isTabbarHidden = true @@ -77,10 +77,9 @@ struct NoTreatmentView: View { case .treatmentFilter: NoTreatmentFilterView(viewModel: viewModel) - case .downTimeSetting: DownTimeSettingView( - treatments: viewModel.selectedTreatments, + treatments: $viewModel.selectedTreatments, setday: ( viewModel.toInt( viewModel.year diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift index 06cb07f9..8a6d3186 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift @@ -11,7 +11,15 @@ struct TreatmentFilterView: View { @ObservedObject var viewModel: TreatmentViewModel var body: some View { VStack { - TreatmentSearchBarTextField(text: $viewModel.searchText, enter: { }, isDisabled: !viewModel.searchText.isEmpty) + TreatmentSearchBarTextField( + text: $viewModel.searchText, + enter: { + Task { + await viewModel.fetchTreatments() + } + }, + isDisabled: true + ) ScrollView(.vertical, showsIndicators: false) { HStack(alignment: .top,spacing: 4) { @@ -23,7 +31,7 @@ struct TreatmentFilterView: View { style: .body3_r_12, color: .gray600 ) - .lineLimit(2) + .lineLimit(2) } @@ -31,30 +39,20 @@ struct TreatmentFilterView: View { } .frame(height: 34.adjustedH) - - if viewModel.filteredTreatments.isEmpty { - ForEach(viewModel.treatments, id: \.id) { treatment in - TreatmentRowView( - displayMode: .checkBoxView, - treatmentEntity: treatment, - isSelected: .constant(viewModel.isSelected(treatment)), - action: { viewModel.addTreatment(treatment) } - ) - } - } else { - ForEach(viewModel.filteredTreatments, id: \.id) { - treatment in - TreatmentRowView( - displayMode: .checkBoxView, - treatmentEntity: treatment, - isSelected: .constant(viewModel.isSelected(treatment)), - action: { viewModel.addTreatment(treatment) } - ) - } + ForEach(viewModel.treatments, id: \.id) { treatment in + TreatmentRowView( + displayMode: .checkBoxView, + treatmentEntity: treatment, + isSelected: .constant(viewModel.isSelected(treatment)), + action: { viewModel.addTreatment(treatment) } + ) } } } + .task { + await viewModel.fetchTreatments() + } .padding(.horizontal, 24.5.adjustedW) } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift index cea9a4e2..7801dde0 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift @@ -79,7 +79,7 @@ struct TreatmentView: View { case .downTimeSetting: DownTimeSettingView( - treatments: viewModel.selectedTreatments, + treatments: $viewModel.selectedTreatments, setday: ( viewModel.toInt( viewModel.year diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift index aad93b10..44cb3004 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift @@ -8,19 +8,24 @@ import Foundation final class NoTreatmentViewModel: ObservableObject{ - @Published var state: NoTreatmentStep = .treatmentSelectedCategory @Published private(set) var categories: [TreatmentCategoryEntity] = [] @Published private(set) var selectedCategory: TreatmentCategoryEntity? + @Published private(set) var treatments: [TreatmentEntity] = [] + @Published var selectedTreatments: [TreatmentEntity] = [] + @Published var state: NoTreatmentStep = .treatmentSelectedCategory @Published var dDay: DdayState? @Published var year: String = "" @Published var month: String = "" @Published var day: String = "" - @Published private(set) var treatments: [TreatmentEntity] = [] - @Published private(set) var selectedTreatments: [TreatmentEntity] = [] private let fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase private let fetchTreatmentsUseCase: FetchTreatmentsUseCase + init(fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase, fetchTreatmentsUseCase: FetchTreatmentsUseCase) { + self.fetchCategoriesUseCase = fetchCategoriesUseCase + self.fetchTreatmentsUseCase = fetchTreatmentsUseCase + } + var step: Int { state.rawValue } var canProceed: Bool { @@ -35,12 +40,7 @@ final class NoTreatmentViewModel: ObservableObject{ return true } } - - init(fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase, fetchTreatmentsUseCase: FetchTreatmentsUseCase) { - self.fetchCategoriesUseCase = fetchCategoriesUseCase - self.fetchTreatmentsUseCase = fetchTreatmentsUseCase - } - + var today: (year: Int, month: Int, day: Int) { let calendar = Calendar.current let now = Date() @@ -60,7 +60,7 @@ final class NoTreatmentViewModel: ObservableObject{ } @MainActor - func loadCategories() async { + func fetchCategories() async { do { categories = try await fetchCategoriesUseCase.execute() } catch { @@ -69,9 +69,9 @@ final class NoTreatmentViewModel: ObservableObject{ } @MainActor - func testfetchTreatments() async { + func fetchNoTreatments() async { do { - treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: "") + treatments = try await fetchTreatmentsUseCase.execute(id: selectedCategory?.id, keyword: "") } catch { treatments = [] } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel+Filter.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel+Filter.swift deleted file mode 100644 index b7ce7fd1..00000000 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel+Filter.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// TreatmentViewModel+Filter.swift -// Cherrish-iOS -// -// Created by 어재선 on 1/16/26. -// - -import Foundation - -extension TreatmentViewModel { - - func addTreatment(_ treatment: TreatmentEntity) { - guard !isSelected(treatment) else { return } - selectedTreatments.append(treatment) - } - - func removeTreatment(_ treatment: TreatmentEntity) { - selectedTreatments.removeAll { $0.id == treatment.id } - } - func isSelected(_ treatment: TreatmentEntity) -> Bool { - selectedTreatments.contains(where: { $0.id == treatment.id }) - } -} diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel+Search.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel+Search.swift deleted file mode 100644 index bac3eaa7..00000000 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel+Search.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// TreatmentViewModel+Search.swift -// Cherrish-iOS -// -// Created by 어재선 on 1/17/26. -// - -import Combine -import Foundation - -extension TreatmentViewModel { - - func setupSearch() { - $searchText - .debounce(for: .milliseconds(300), scheduler: RunLoop.main) - .removeDuplicates() - .sink { [weak self] text in - self?.filterTreatments(by: text) - } - .store(in: &cancellables) - } - - func filterTreatments(by text: String) { - if text.isEmpty { - filteredTreatments = treatments - } else { - filteredTreatments = treatments.filter { - $0.name.localizedCaseInsensitiveContains(text) - } - } - } - - func clearSearch() { - searchText = "" - } -} diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift index 830db439..3b92bfc1 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift @@ -9,19 +9,22 @@ import SwiftUI import Combine final class TreatmentViewModel: ObservableObject{ + @Published private(set) var treatments: [TreatmentEntity] = [] + @Published var selectedTreatments: [TreatmentEntity] = [] @Published var state: TreatmentStep = .targetDdaySetting @Published var dDay: DdayState? @Published var year: String = "" @Published var month: String = "" @Published var day: String = "" - @Published var treatments: [TreatmentEntity] = [] - @Published var selectedTreatments: [TreatmentEntity] = [] @Published var searchText = "" - @Published var filteredTreatments: [TreatmentEntity] = [] - var step: Int { state.rawValue } + private let fetchTreatmentsUseCase: FetchTreatmentsUseCase - var cancellables = Set() + init(fetchTreatmentsUseCase: FetchTreatmentsUseCase) { + self.fetchTreatmentsUseCase = fetchTreatmentsUseCase + } + + var step: Int { state.rawValue } var today: (year: Int, month: Int, day: Int) { let calendar = Calendar.current @@ -33,10 +36,6 @@ final class TreatmentViewModel: ObservableObject{ ) } - init() { - filteredTreatments = treatments - setupSearch() - } var canProceed: Bool { switch state { case .targetDdaySetting: @@ -44,10 +43,20 @@ final class TreatmentViewModel: ObservableObject{ case .treatmentFilter: return !selectedTreatments.isEmpty case .downTimeSetting: - return true + return selectedTreatments.allSatisfy { $0.setDowntime != nil } + } } + @MainActor + func fetchTreatments() async { + do { + treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: searchText) + } catch { + treatments = [] + } + } + func next() { state.next() } @@ -73,6 +82,20 @@ final class TreatmentViewModel: ObservableObject{ return true } +} + + +extension TreatmentViewModel { - + func addTreatment(_ treatment: TreatmentEntity) { + guard !isSelected(treatment) else { return } + selectedTreatments.append(treatment) + } + + func removeTreatment(_ treatment: TreatmentEntity) { + selectedTreatments.removeAll { $0.id == treatment.id } + } + func isSelected(_ treatment: TreatmentEntity) -> Bool { + selectedTreatments.contains(where: { $0.id == treatment.id }) + } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift index 2b23894a..6abbe3bd 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift @@ -59,8 +59,9 @@ final class PresentationDependencyAssembler: DependencyAssembler { return NoTreatmentViewModel(fetchCategoriesUseCase: useCase,fetchTreatmentsUseCase: fetchTreatmentsUseCase) } + DIContainer.shared.register(type: TreatmentViewModel.self) { - return TreatmentViewModel() + return TreatmentViewModel(fetchTreatmentsUseCase: fetchTreatmentsUseCase) } } } From a30a0f9b094405e8764f1c0267d80c50ca70abde Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Tue, 20 Jan 2026 23:49:52 +0900 Subject: [PATCH 04/11] =?UTF-8?q?fix:=20#114=20=EC=BD=94=EB=A6=AC=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/DataDependencyAssembler.swift | 4 +++- .../Data/Network/EndPoint/TreatmentAPI.swift | 18 +++++++++--------- .../Data/Repository/TreatmentRepository.swift | 7 +++++-- .../NoTreatment/NoTreatmentViewModel.swift | 2 +- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift index 2dcff7ff..60e89c60 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift @@ -9,9 +9,11 @@ import Foundation final class DataDependencyAssembler: DependencyAssembler { private let networkService: NetworkService + private let userDefaultService: UserDefaultService init() { self.networkService = DefaultNetworkService() + self.userDefaultService = DefaultUserDefaultService() } func assemble() { @@ -24,7 +26,7 @@ final class DataDependencyAssembler: DependencyAssembler { } DIContainer.shared.register(type: TreatmentInterface.self) { - return DefaultTreatmentRepository(networkService: self.networkService) + return DefaultTreatmentRepository(networkService: self.networkService, userDefaultService: self.userDefaultService) } diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift index 57ec0c3b..3812572c 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift @@ -9,8 +9,8 @@ import Foundation import Alamofire enum TreatmentAPI: EndPoint { - case fetchCategories - case fetchProcedures(id: Int? = nil, text: String? = nil) + case fetchCategories(userId: Int) + case fetchProcedures(userId: Int, id: Int? = nil, text: String? = nil) var basePath: String { switch self { @@ -42,10 +42,10 @@ enum TreatmentAPI: EndPoint { var headers: HeaderType { switch self { - case .fetchCategories: - return .basic - case .fetchProcedures: - return .basic + case .fetchCategories(let userId): + return .withAuth(userID: userId) + case .fetchProcedures(let userId, _, _): + return .withAuth(userID: userId) } } @@ -53,9 +53,9 @@ enum TreatmentAPI: EndPoint { var parameterEncoding: any Alamofire.ParameterEncoding { switch self { case .fetchCategories: - return JSONEncoding.default + return URLEncoding.default case .fetchProcedures: - return JSONEncoding.default + return URLEncoding.default } } @@ -63,7 +63,7 @@ enum TreatmentAPI: EndPoint { switch self { case .fetchCategories: return nil - case .fetchProcedures(let id, let text): + case .fetchProcedures(_, let id, let text): var params: [String: Any] = [:] if let id = id { params["worryId"] = id diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift b/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift index c7e73f49..fdaeebc9 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift @@ -10,9 +10,11 @@ import Foundation struct DefaultTreatmentRepository: TreatmentInterface { private let networkService: NetworkService + private let userDefaultService: UserDefaultService - init(networkService: NetworkService) { + init(networkService: NetworkService, userDefaultService: UserDefaultService) { self.networkService = networkService + self.userDefaultService = userDefaultService } func fetchCategories() async throws -> [TreatmentCategoryEntity] { @@ -20,7 +22,8 @@ struct DefaultTreatmentRepository: TreatmentInterface { } func fetchTreatment(id: Int?, keyword: String?) async throws -> [TreatmentEntity] { - let response = try await networkService.request(TreatmentAPI.fetchProcedures(id: id, text: keyword), decodingType: ProceduresResponseDTO.self) + let userId: Int = userDefaultService.load(key: .userID) ?? 1 + let response = try await networkService.request(TreatmentAPI.fetchProcedures(userId: userId,id: id, text: keyword), decodingType: ProceduresResponseDTO.self) return response.procedures.map { $0.toEntity() } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift index 44cb3004..0413318e 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/NoTreatment/NoTreatmentViewModel.swift @@ -37,7 +37,7 @@ final class NoTreatmentViewModel: ObservableObject{ case .treatmentFilter: return !selectedTreatments.isEmpty case .downTimeSetting: - return true + return selectedTreatments.allSatisfy { $0.setDowntime != nil } } } From 1ad657e24f0db3d29d5879186d18f359511365e5 Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Tue, 20 Jan 2026 23:58:33 +0900 Subject: [PATCH 05/11] =?UTF-8?q?chore:=20#114=20=EA=B3=B5=EB=B0=B1=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift index 3812572c..780acfad 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift @@ -82,7 +82,5 @@ enum TreatmentAPI: EndPoint { case .fetchProcedures: return .none } - } - - + } } From b5cb1fb39a711f9a7551bf5e01167b65850a55c7 Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Wed, 21 Jan 2026 01:41:08 +0900 Subject: [PATCH 06/11] =?UTF-8?q?fix:=20#114=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Calendar/Treatment/View/Treatment/TreatmentView.swift | 2 +- .../Presentation/PresentationDependencyAssembler.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift index 7801dde0..f44fa197 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift @@ -10,7 +10,7 @@ import SwiftUI struct TreatmentView: View { @EnvironmentObject private var calendarCoordinator: CalendarCoordinator @EnvironmentObject private var tabBarCoordinator: TabBarCoordinator - @ObservedObject var viewModel: TreatmentViewModel + @StateObject var viewModel: TreatmentViewModel var body: some View { VStack(spacing: 0) { diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift index a365d3ad..ea7b7d70 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift @@ -57,7 +57,7 @@ final class PresentationDependencyAssembler: DependencyAssembler { } DIContainer.shared.register(type: NoTreatmentViewModel.self) { - return NoTreatmentViewModel(fetchCategoriesUseCase: useCase,fetchTreatmentsUseCase: fetchTreatmentsUseCase) + return NoTreatmentViewModel(fetchCategoriesUseCase: fetchTreatmentCategoriesUseCase, fetchTreatmentsUseCase: fetchTreatmentsUseCase) } From c23d7ba5b925ec637246bc708c2efb107841de58 Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Wed, 21 Jan 2026 01:44:34 +0900 Subject: [PATCH 07/11] =?UTF-8?q?fix:=20#114=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cherrish-iOS/Data/Network/EndPoint/OnboardingAPI.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/OnboardingAPI.swift b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/OnboardingAPI.swift index 79a3c077..0986c70c 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/OnboardingAPI.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/OnboardingAPI.swift @@ -41,7 +41,7 @@ enum OnboardingAPI: EndPoint { return JSONEncoding.default } - var queryParameters: [String: String]? { + var queryParameters: [String: Any]? { return nil } From 36b691f0263096228cb01f5d948f95b9afe4e330 Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Wed, 21 Jan 2026 02:12:37 +0900 Subject: [PATCH 08/11] =?UTF-8?q?fix:=20#114=20TextField=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Treatment/View/Treatment/TreatmentFilterView.swift | 4 ++-- .../Treatment/View/TreatmentSearchBarTextField.swift | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift index 8a6d3186..5c09c731 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift @@ -13,12 +13,12 @@ struct TreatmentFilterView: View { VStack { TreatmentSearchBarTextField( text: $viewModel.searchText, - enter: { + onTap: { Task { await viewModel.fetchTreatments() } }, - isDisabled: true + isDisabled: false ) ScrollView(.vertical, showsIndicators: false) { diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/TreatmentSearchBarTextField.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/TreatmentSearchBarTextField.swift index 2245b34e..359ab5ca 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/TreatmentSearchBarTextField.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/TreatmentSearchBarTextField.swift @@ -9,7 +9,7 @@ import SwiftUI struct TreatmentSearchBarTextField: View { @Binding var text: String - let enter: () -> Void + let onTap: () -> Void var isDisabled: Bool var body: some View { @@ -30,14 +30,14 @@ struct TreatmentSearchBarTextField: View { .multilineTextAlignment(.leading) .tint(.gray1000) .onSubmit { - enter() + onTap() } } .frame(height: 20.adjustedH) .padding(.vertical, 8.adjustedH) Button{ - enter() + onTap() } label: { ZStack { Image(.search) From 412a43761a12c275d8d161422e612dc879ac96d3 Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Wed, 21 Jan 2026 02:26:39 +0900 Subject: [PATCH 09/11] =?UTF-8?q?fix:=20#114=20try=20await=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/Treatment/TreatmentFilterView.swift | 12 ++++++++---- .../ViewModel/Treatment/TreatmentViewModel.swift | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift index 5c09c731..013fb197 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentFilterView.swift @@ -15,11 +15,12 @@ struct TreatmentFilterView: View { text: $viewModel.searchText, onTap: { Task { - await viewModel.fetchTreatments() + try await viewModel.fetchTreatments() } }, isDisabled: false ) + .padding(.horizontal, 25.adjustedW) ScrollView(.vertical, showsIndicators: false) { HStack(alignment: .top,spacing: 4) { @@ -39,6 +40,7 @@ struct TreatmentFilterView: View { } .frame(height: 34.adjustedH) + .padding(.horizontal, 25.adjustedW) ForEach(viewModel.treatments, id: \.id) { treatment in TreatmentRowView( displayMode: .checkBoxView, @@ -46,13 +48,15 @@ struct TreatmentFilterView: View { isSelected: .constant(viewModel.isSelected(treatment)), action: { viewModel.addTreatment(treatment) } ) - } + } .padding(.horizontal, 24.adjustedW) } } .task { - await viewModel.fetchTreatments() + Task { + try await viewModel.fetchTreatments() + } } - .padding(.horizontal, 24.5.adjustedW) + } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift index 3b92bfc1..05288c9f 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/ViewModel/Treatment/TreatmentViewModel.swift @@ -49,7 +49,7 @@ final class TreatmentViewModel: ObservableObject{ } @MainActor - func fetchTreatments() async { + func fetchTreatments() async throws { do { treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: searchText) } catch { From b463e53c90306e31a9c54818e9849e53fb960418 Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Wed, 21 Jan 2026 03:17:35 +0900 Subject: [PATCH 10/11] =?UTF-8?q?fix:=20#114=20=ED=8C=A8=EB=94=A9=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Treatment/View/Treatment/TreatmentView.swift | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift index f44fa197..21918f72 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift @@ -11,7 +11,7 @@ struct TreatmentView: View { @EnvironmentObject private var calendarCoordinator: CalendarCoordinator @EnvironmentObject private var tabBarCoordinator: TabBarCoordinator @StateObject var viewModel: TreatmentViewModel - + var body: some View { VStack(spacing: 0) { CherrishNavigationBar( @@ -36,7 +36,7 @@ struct TreatmentView: View { currentStep: .constant(viewModel.step) ) .padding(.horizontal, 33.5.adjustedW) - + Spacer() .frame(height: 20.adjustedH) @@ -51,13 +51,10 @@ struct TreatmentView: View { } .id(viewModel.step) } - .ignoresSafeArea(.keyboard,edges: .bottom) + .ignoresSafeArea(.keyboard ,edges: .bottom) .onTapGesture { hideKeyboard() } - .onAppear { - tabBarCoordinator.isTabbarHidden = true - } } @ViewBuilder @@ -70,8 +67,8 @@ struct TreatmentView: View { month: $viewModel.month, day: $viewModel.day ) - .padding(.leading, 34.adjustedW) - .padding(.trailing, 33.adjustedW) + .padding(.horizontal, 34.adjustedW) + .id(viewModel.state) case .treatmentFilter: From 6cc89cb7ed651ad2a0fbbc2d8c080d4ec142979d Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Wed, 21 Jan 2026 03:46:34 +0900 Subject: [PATCH 11/11] =?UTF-8?q?fix:=20#114=20=ED=8C=A8=EB=94=A9=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Treatment/View/DownTimeSettingView.swift | 93 ++++++++++--------- .../View/TargetDdaySettingView.swift | 1 + .../View/Treatment/TreatmentView.swift | 2 +- 3 files changed, 50 insertions(+), 46 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DownTimeSettingView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DownTimeSettingView.swift index 3454b24a..da3ad424 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DownTimeSettingView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/DownTimeSettingView.swift @@ -16,7 +16,7 @@ struct DownTimeSettingView: View { var body: some View { VStack { Spacer() - .frame(height: 30) + .frame(height: 30.adjustedH) HStack { TypographyText( @@ -28,62 +28,65 @@ struct DownTimeSettingView: View { Spacer() } + .padding(.horizontal, 25.adjustedW) ScrollView(.vertical, showsIndicators: false) { - Spacer() - .frame(height: 24.adjustedH) - ForEach(treatments, id: \.self) { treatment in - TreatmentRowView( - displayMode: .completeBoxView, - treatmentEntity: treatment, - isSelected: .constant( - selectedTreatment == treatment - - ), - isCompleted: .constant( - treatment.setDowntime == nil ? false : true - ), - action: { - selectedTreatment = treatment - }) - } - - Spacer() - .frame(height: 14.adjustedH) - - HStack(alignment: .top, spacing: 0) { - TypographyText( - "◎", - style: .body3_r_12, - color: .gray600 - ) + VStack { + Spacer() + .frame(height: 24.adjustedH) + ForEach(treatments, id: \.self) { treatment in + TreatmentRowView( + displayMode: .completeBoxView, + treatmentEntity: treatment, + isSelected: .constant( + selectedTreatment == treatment + + ), + isCompleted: .constant( + treatment.setDowntime == nil ? false : true + ), + action: { + selectedTreatment = treatment + }) + } - VStack(alignment: .leading, spacing: 0) { - TypographyText( - "본 정보는 의료 상담이나 진단을 대체하지 않으며,", - style: .body3_r_12, - color: .gray600 - ) - + Spacer() + .frame(height: 14.adjustedH) + + HStack(alignment: .top, spacing: 0) { TypographyText( - "실제 다운타임 및 회복 과정은 개인에 따라 다를 수 있습니다.", + "◎", style: .body3_r_12, color: .gray600 ) - TypographyText( - "정확한 내용은 의료진 상담을 통해 확인하세요.", - style: .body3_r_12, - color: .gray600 - ) + VStack(alignment: .leading, spacing: 0) { + TypographyText( + "본 정보는 의료 상담이나 진단을 대체하지 않으며,", + style: .body3_r_12, + color: .gray600 + ) + + TypographyText( + "실제 다운타임 및 회복 과정은 개인에 따라 다를 수 있습니다.", + style: .body3_r_12, + color: .gray600 + ) + + TypographyText( + "정확한 내용은 의료진 상담을 통해 확인하세요.", + style: .body3_r_12, + color: .gray600 + ) + + } + Spacer() } - - Spacer() } + .padding(.horizontal, 25.adjustedW) } } - .padding(.horizontal, 25.adjustedW) .sheet(item: $selectedTreatment) { treatment in if let index = treatments.firstIndex(where: { $0.id == treatment.id }) { DowntimeBottomSheetView( @@ -97,7 +100,7 @@ struct DownTimeSettingView: View { .presentationDragIndicator(.visible) } - + } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/TargetDdaySettingView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/TargetDdaySettingView.swift index f33536d1..17af9bc4 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/TargetDdaySettingView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/TargetDdaySettingView.swift @@ -96,6 +96,7 @@ struct TargetDdaySettingView: View { Spacer() } } + .padding(.horizontal, 34.adjustedW) } .scrollDismissesKeyboard(.interactively) } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift index 21918f72..5781e5c5 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/Treatment/View/Treatment/TreatmentView.swift @@ -67,7 +67,7 @@ struct TreatmentView: View { month: $viewModel.month, day: $viewModel.day ) - .padding(.horizontal, 34.adjustedW) + .id(viewModel.state)