From 481a5e34b4932a68cc4671b3be9e5c94471f1ba6 Mon Sep 17 00:00:00 2001 From: yeonee Date: Wed, 21 Jan 2026 05:40:11 +0900 Subject: [PATCH 1/6] feat: #125 flow state --- .../CalendarViewModel.swift | 9 ++++- .../Calendar/CalendarTreatmentFlowState.swift | 12 +++++++ .../NoTreatment/NoTreatmentViewModel.swift | 12 +++++-- .../Treatment/TreatmentViewModel.swift | 33 +++++++++++-------- .../PresentationDependencyAssembler.swift | 25 +++++++++++--- 5 files changed, 70 insertions(+), 21 deletions(-) rename Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/{ => CalendarMain}/CalendarViewModel.swift (92%) create mode 100644 Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarTreatmentFlowState.swift diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift similarity index 92% rename from Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarViewModel.swift rename to Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift index 11328831..f16e1c7f 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift @@ -23,13 +23,16 @@ final class CalendarViewModel: ObservableObject { private let fetchProcedureCountOfMonthUseCase: FetchProcedureCountOfMonth private let fetchTodayProcedureListUseCase: FetchTodayProcedureList + private let calendarTreatmentFlowState: CalendarTreatmentFlowState init( fetchProcedureCountOfMonthUseCase: FetchProcedureCountOfMonth, - fetchTodayProcedureListUseCase: FetchTodayProcedureList + fetchTodayProcedureListUseCase: FetchTodayProcedureList, + calendarTreatmentFlowState: CalendarTreatmentFlowState ) { self.fetchProcedureCountOfMonthUseCase = fetchProcedureCountOfMonthUseCase self.fetchTodayProcedureListUseCase = fetchTodayProcedureListUseCase + self.calendarTreatmentFlowState = calendarTreatmentFlowState } func select(date: Date) { @@ -74,6 +77,10 @@ final class CalendarViewModel: ObservableObject { return procedureList.isEmpty } + func sendDateToTreatmentView() { + calendarTreatmentFlowState.selectedDaet = selectedDate + } + @MainActor func fetchProcedureCountsOfMonth() async throws { let calendar = Calendar.current diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarTreatmentFlowState.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarTreatmentFlowState.swift new file mode 100644 index 00000000..4b8fad97 --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarTreatmentFlowState.swift @@ -0,0 +1,12 @@ +// +// CalendarTreatmentFlowState.swift +// Cherrish-iOS +// +// Created by 이나연 on 1/21/26. +// + +import Foundation + +final class CalendarTreatmentFlowState: ObservableObject { + @Published var selectedDaet: Date? +} 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 0413318e..219d7373 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 @@ -20,10 +20,17 @@ final class NoTreatmentViewModel: ObservableObject{ private let fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase private let fetchTreatmentsUseCase: FetchTreatmentsUseCase + private let calendarTreatmentFlowState: CalendarTreatmentFlowState - init(fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase, fetchTreatmentsUseCase: FetchTreatmentsUseCase) { + + init( + fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase, + fetchTreatmentsUseCase: FetchTreatmentsUseCase, + calendarTreatmentFlowState: CalendarTreatmentFlowState + ) { self.fetchCategoriesUseCase = fetchCategoriesUseCase self.fetchTreatmentsUseCase = fetchTreatmentsUseCase + self.calendarTreatmentFlowState = calendarTreatmentFlowState } var step: Int { state.rawValue } @@ -64,7 +71,7 @@ final class NoTreatmentViewModel: ObservableObject{ do { categories = try await fetchCategoriesUseCase.execute() } catch { - + CherrishLogger.debug(error) } } @@ -74,6 +81,7 @@ final class NoTreatmentViewModel: ObservableObject{ treatments = try await fetchTreatmentsUseCase.execute(id: selectedCategory?.id, keyword: "") } catch { treatments = [] + CherrishLogger.debug(error) } } 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 05288c9f..a2055672 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 @@ -19,9 +19,14 @@ final class TreatmentViewModel: ObservableObject{ @Published var searchText = "" private let fetchTreatmentsUseCase: FetchTreatmentsUseCase + private let calendarTreatmentFlowState: CalendarTreatmentFlowState - init(fetchTreatmentsUseCase: FetchTreatmentsUseCase) { + init( + fetchTreatmentsUseCase: FetchTreatmentsUseCase, + calendarTreatmentFlowState: CalendarTreatmentFlowState + ) { self.fetchTreatmentsUseCase = fetchTreatmentsUseCase + self.calendarTreatmentFlowState = calendarTreatmentFlowState } var step: Int { state.rawValue } @@ -37,21 +42,21 @@ final class TreatmentViewModel: ObservableObject{ } var canProceed: Bool { - switch state { - case .targetDdaySetting: - return isDateTextFieldNotEmpty() - case .treatmentFilter: - return !selectedTreatments.isEmpty - case .downTimeSetting: - return selectedTreatments.allSatisfy { $0.setDowntime != nil } - - } - } + switch state { + case .targetDdaySetting: + return isDateTextFieldNotEmpty() + case .treatmentFilter: + return !selectedTreatments.isEmpty + case .downTimeSetting: + return selectedTreatments.allSatisfy { $0.setDowntime != nil } + + } + } @MainActor func fetchTreatments() async throws { do { - treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: searchText) + treatments = try await fetchTreatmentsUseCase.execute(id: nil, keyword: searchText) } catch { treatments = [] } @@ -78,7 +83,7 @@ final class TreatmentViewModel: ObservableObject{ let dayInt = Int(day), dayInt >= 1, dayInt <= 31 else { return false } - + return true } @@ -91,7 +96,7 @@ extension TreatmentViewModel { guard !isSelected(treatment) else { return } selectedTreatments.append(treatment) } - + func removeTreatment(_ treatment: TreatmentEntity) { selectedTreatments.removeAll { $0.id == treatment.id } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift index a6cc612a..1260f4cd 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift @@ -17,6 +17,10 @@ final class PresentationDependencyAssembler: DependencyAssembler { func assemble() { preAssembler.assemble() + DIContainer.shared.register(type: CalendarTreatmentFlowState.self) { + return CalendarTreatmentFlowState() + } + guard let createProfileUseCase = DIContainer.shared.resolve(type: CreateProfileUseCase.self) else { CherrishLogger.error(CherrishError.DIFailedError) return @@ -27,16 +31,22 @@ final class PresentationDependencyAssembler: DependencyAssembler { } guard let fetchProcedureCountOfMonthUseCase = DIContainer.shared.resolve(type: FetchProcedureCountOfMonth.self), - let fetchTodayProcedureListUseCase = DIContainer.shared.resolve(type: FetchTodayProcedureList.self) + let fetchTodayProcedureListUseCase = DIContainer.shared.resolve(type: FetchTodayProcedureList.self) else { CherrishLogger.error(CherrishError.DIFailedError) return } + guard let calendarTreatmentFlowState = DIContainer.shared.resolve(type: CalendarTreatmentFlowState.self) else { + CherrishLogger.error(CherrishError.DIFailedError) + return + } + DIContainer.shared.register(type: CalendarViewModel.self) { return CalendarViewModel( fetchProcedureCountOfMonthUseCase: fetchProcedureCountOfMonthUseCase, - fetchTodayProcedureListUseCase: fetchTodayProcedureListUseCase + fetchTodayProcedureListUseCase: fetchTodayProcedureListUseCase, + calendarTreatmentFlowState: calendarTreatmentFlowState ) } @@ -62,12 +72,19 @@ final class PresentationDependencyAssembler: DependencyAssembler { } DIContainer.shared.register(type: NoTreatmentViewModel.self) { - return NoTreatmentViewModel(fetchCategoriesUseCase: fetchTreatmentCategoriesUseCase, fetchTreatmentsUseCase: fetchTreatmentsUseCase) + return NoTreatmentViewModel( + fetchCategoriesUseCase: fetchTreatmentCategoriesUseCase, + fetchTreatmentsUseCase: fetchTreatmentsUseCase, + calendarTreatmentFlowState: calendarTreatmentFlowState + ) } DIContainer.shared.register(type: TreatmentViewModel.self) { - return TreatmentViewModel(fetchTreatmentsUseCase: fetchTreatmentsUseCase) + return TreatmentViewModel( + fetchTreatmentsUseCase: fetchTreatmentsUseCase, + calendarTreatmentFlowState: calendarTreatmentFlowState + ) } } } From 5e8482abefa849e9d6170da914f829af71827a95 Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Wed, 21 Jan 2026 06:11:33 +0900 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20#125=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 --- .../Cherrish-iOS/Data/Network/EndPoint/HomeAPI.swift | 2 +- .../Treatment/View/NoTreatment/NoTreatmentView.swift | 6 ++---- .../Presentation/Feature/Onboarding/SplashView.swift | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/HomeAPI.swift b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/HomeAPI.swift index 80ff67d1..3f554c7b 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/HomeAPI.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/HomeAPI.swift @@ -47,7 +47,7 @@ extension HomeAPI: EndPoint { } } - var queryParameters: [String: String]? { + var queryParameters: [String: Any]? { switch self { case .fetchDashboard: return nil 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 cf35b030..1250d044 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 @@ -62,7 +62,6 @@ struct NoTreatmentView: View { switch viewModel.state { case .treatmentSelectedCategory: TreatmentSelectedCategory(viewModel: viewModel) - .padding(.horizontal, 34.adjustedW) .id(String(describing: viewModel.state)) case .targetDdaySetting: @@ -72,7 +71,6 @@ struct NoTreatmentView: View { month: $viewModel.month, day: $viewModel.day ) - .padding(.horizontal, 34.adjustedW) .id(String(describing: viewModel.state)) case .treatmentFilter: @@ -160,7 +158,7 @@ private struct TreatmentSelectedCategory: View { Spacer() } - + .padding(.horizontal, 34.adjustedW) Spacer() .frame(height: 40.adjustedH) ScrollView(.vertical, showsIndicators:false) { @@ -182,7 +180,7 @@ private struct TreatmentSelectedCategory: View { ) ) } - } + } .padding(.horizontal, 34.adjustedW) } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Onboarding/SplashView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Onboarding/SplashView.swift index c2be14aa..6447115d 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Onboarding/SplashView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Onboarding/SplashView.swift @@ -9,7 +9,6 @@ import SwiftUI struct SplashView: View { @EnvironmentObject private var appCoordinator: AppCoordinator - private let userDefaultService: UserDefaultService = DefaultUserDefaultService() private let userDefaultService: UserDefaultService From 0019d9efa3404ab59dfa259c6a10bbd441823d7a Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Wed, 21 Jan 2026 15:07:45 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20#125=20=EB=84=A4=ED=8A=B8=EC=9B=8C?= =?UTF-8?q?=ED=81=AC=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/DataDependencyAssembler.swift | 2 - .../Model/CreateUserProcedureRequestDTO.swift | 19 ++++++++ .../Data/Network/EndPoint/TreatmentAPI.swift | 43 +++++++++++++++---- .../Data/Repository/TreatmentRepository.swift | 17 ++++++++ .../Domain/DomainDependencyAssembler.swift | 8 ++-- .../Domain/Interface/TreatmentInterface.swift | 1 + .../Domain/Model/TreatmentEntity.swift | 10 ++++- .../UseCase/CreateUserProcedureUseCase.swift | 25 +++++++++++ .../Calendar/CalendarMain/CalendarView.swift | 3 ++ .../CalendarMain/CalendarViewModel.swift | 6 ++- .../View/NoTreatment/NoTreatmentView.swift | 10 ++++- .../View/Treatment/TreatmentView.swift | 10 ++++- .../NoTreatment/NoTreatmentViewModel.swift | 22 +++++++++- .../Treatment/TreatmentViewModel.swift | 37 ++++++++++++++-- .../Presentation/Global/Extension/Date+.swift | 26 +++++++++++ .../PresentationDependencyAssembler.swift | 17 ++++++-- 16 files changed, 227 insertions(+), 29 deletions(-) create mode 100644 Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureRequestDTO.swift create mode 100644 Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift diff --git a/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift index 6090a47e..6ede8fc7 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/DataDependencyAssembler.swift @@ -41,7 +41,5 @@ final class DataDependencyAssembler: DependencyAssembler { DIContainer.shared.register(type: TreatmentInterface.self) { return DefaultTreatmentRepository(networkService: self.networkService, userDefaultService: self.userDefaultService) } - - } } diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureRequestDTO.swift b/Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureRequestDTO.swift new file mode 100644 index 00000000..c3c05d28 --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureRequestDTO.swift @@ -0,0 +1,19 @@ +// +// UserProcedureItemRequestDTO.swift +// Cherrish-iOS +// +// Created by 어재선 on 1/21/26. +// + +import Foundation + +struct UserProcedureItemRequestDTO: Encodable, Decodable { + let procedureId: Int + let downtimeDays: Int +} + +struct CreateUserProcedureRequestDTO: Encodable, Decodable { + let scheduledAt: String + let recoveryTargetDate: String + let procedures: [UserProcedureItemRequestDTO] +} diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift index 780acfad..ae05291b 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/Network/EndPoint/TreatmentAPI.swift @@ -11,14 +11,16 @@ import Alamofire enum TreatmentAPI: EndPoint { case fetchCategories(userId: Int) case fetchProcedures(userId: Int, id: Int? = nil, text: String? = nil) + case createUserProcedure(userId: Int, request: CreateUserProcedureRequestDTO) var basePath: String { switch self { case .fetchCategories: return "/api" - case .fetchProcedures: return "/api" + case .createUserProcedure: + return "/api" } } @@ -28,6 +30,8 @@ enum TreatmentAPI: EndPoint { return "/worries" case .fetchProcedures: return "/procedures" + case .createUserProcedure: + return "/user-procedures" } } @@ -37,6 +41,8 @@ enum TreatmentAPI: EndPoint { return .get case .fetchProcedures: return .get + case .createUserProcedure: + return .post } } @@ -46,6 +52,9 @@ enum TreatmentAPI: EndPoint { return .withAuth(userID: userId) case .fetchProcedures(let userId, _, _): return .withAuth(userID: userId) + case .createUserProcedure(let userId, _): + return .withAuth(userID: userId) + } } @@ -56,6 +65,8 @@ enum TreatmentAPI: EndPoint { return URLEncoding.default case .fetchProcedures: return URLEncoding.default + case .createUserProcedure: + return JSONEncoding.default } } @@ -65,22 +76,36 @@ enum TreatmentAPI: EndPoint { return nil case .fetchProcedures(_, let id, let text): var params: [String: Any] = [:] - if let id = id { - params["worryId"] = id - } - if let text = text { - params["keyword"] = "\(text)" - } - return params + if let id = id { + params["worryId"] = id + } + if let text = text { + params["keyword"] = "\(text)" + } + return params + case .createUserProcedure: + return nil } } + var bodyParameters: Alamofire.Parameters? { switch self { case .fetchCategories: return .none case .fetchProcedures: return .none + case .createUserProcedure(_, let request): + return [ + "scheduledAt": request.scheduledAt, + "recoveryTargetDate": request.recoveryTargetDate, + "procedures": request.procedures.map { + [ + "procedureId": $0.procedureId, + "downtimeDays": $0.downtimeDays + ] + } + ] } - } + } } diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift b/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift index b9f3c230..591e677a 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift @@ -8,6 +8,8 @@ import Foundation struct DefaultTreatmentRepository: TreatmentInterface { + + private let networkService: NetworkService private let userDefaultService: UserDefaultService @@ -32,9 +34,24 @@ struct DefaultTreatmentRepository: TreatmentInterface { let response = try await networkService.request(TreatmentAPI.fetchProcedures(userId: userId,id: id, text: keyword), decodingType: ProceduresResponseDTO.self) return response.procedures.map { $0.toEntity() } } + + func createUserProcedure(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws { + let userId: Int = userDefaultService.load(key: .userID) ?? 1 + let request = CreateUserProcedureRequestDTO( + scheduledAt: scheduledDate, + recoveryTargetDate: recoveryDate, + procedures: treatments.compactMap { $0.toRequestDTO() } + ) + let _ = try await networkService.request(TreatmentAPI.createUserProcedure(userId: userId, request: request), decodingType: UserProcedureItemRequestDTO.self) + } } struct MockTreatmentRepository: TreatmentInterface { + + func createUserProcedure(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) { + + } + func fetchTreatment(id: Int?, keyword: String?) async throws -> [TreatmentEntity] { return [] } diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift index 1b8726cd..f478d3bd 100644 --- a/Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Domain/DomainDependencyAssembler.swift @@ -25,10 +25,6 @@ final class DomainDependencyAssembler: DependencyAssembler { return } - guard let treatmentCategoryRepository = DIContainer.shared.resolve(type: TreatmentInterface.self) else { - return - } - DIContainer.shared.register(type: FetchProcedureCountOfMonth.self) { return DefaultFetchProcedureCountOfMonth(repository: calendarRepository) } @@ -68,5 +64,9 @@ final class DomainDependencyAssembler: DependencyAssembler { DIContainer.shared.register(type: FetchTreatmentsUseCase.self) { return DefaultFetchTreatmentsUseCase(repository: treatmentRepository) } + + DIContainer.shared .register(type: CreateUserProcedureUseCase.self) { + return DefaultCreateUserProcedureUseCase(repository: treatmentRepository) + } } } diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/Interface/TreatmentInterface.swift b/Cherrish-iOS/Cherrish-iOS/Domain/Interface/TreatmentInterface.swift index f715e020..68019ea8 100644 --- a/Cherrish-iOS/Cherrish-iOS/Domain/Interface/TreatmentInterface.swift +++ b/Cherrish-iOS/Cherrish-iOS/Domain/Interface/TreatmentInterface.swift @@ -10,4 +10,5 @@ import Foundation protocol TreatmentInterface { func fetchCategories() async throws -> [TreatmentCategoryEntity] func fetchTreatment(id: Int?, keyword: String?) async throws -> [TreatmentEntity] + func createUserProcedure(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws } diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/Model/TreatmentEntity.swift b/Cherrish-iOS/Cherrish-iOS/Domain/Model/TreatmentEntity.swift index 3f76c349..3a3e8b0b 100644 --- a/Cherrish-iOS/Cherrish-iOS/Domain/Model/TreatmentEntity.swift +++ b/Cherrish-iOS/Cherrish-iOS/Domain/Model/TreatmentEntity.swift @@ -20,5 +20,13 @@ struct TreatmentEntity: Identifiable, Equatable, Hashable { } } - +extension TreatmentEntity { + func toRequestDTO() -> UserProcedureItemRequestDTO? { + guard let downtime = setDowntime else { return nil } + return UserProcedureItemRequestDTO( + procedureId: id, + downtimeDays: downtime + ) + } +} diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift b/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift new file mode 100644 index 00000000..57cae44d --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift @@ -0,0 +1,25 @@ +// +// CreateUserProcedureUseCase.swift +// Cherrish-iOS +// +// Created by 어재선 on 1/21/26. +// + +import Foundation + +protocol CreateUserProcedureUseCase { + func excute(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws +} + +struct DefaultCreateUserProcedureUseCase: CreateUserProcedureUseCase { + + private let repository: TreatmentInterface + + init(repository: TreatmentInterface) { + self.repository = repository + } + + func excute(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws { + return try await repository.createUserProcedure(scheduledDate: scheduledDate, recoveryDate: recoveryDate, treatments: treatments) + } +} diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift index 16f11360..788ffd20 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift @@ -150,6 +150,7 @@ extension CalendarView { .foregroundStyle(.gray600) .frame(width: 24.adjustedW, height: 24.adjustedH) .onTapGesture { + viewModel.confirmDate() calendarCoordinator.push(.selectTreatment) } case .selectedProcedure: @@ -252,9 +253,11 @@ extension CalendarView { leadingIcon: Image(.plus), trailingIcon: nil, action: { + viewModel.confirmDate() calendarCoordinator.push( .selectTreatment ) + } ) .padding(.horizontal, 24) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift index cbee38bc..2ab37a2d 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift @@ -31,7 +31,7 @@ final class CalendarViewModel: ObservableObject { init( fetchProcedureCountOfMonthUseCase: FetchProcedureCountOfMonth, fetchTodayProcedureListUseCase: FetchTodayProcedureListUseCase, - fetchProcedureDowntimeUseCase: FetchProcedureDowntimeUseCase + fetchProcedureDowntimeUseCase: FetchProcedureDowntimeUseCase, calendarTreatmentFlowState: CalendarTreatmentFlowState ) { self.fetchProcedureCountOfMonthUseCase = fetchProcedureCountOfMonthUseCase @@ -40,6 +40,10 @@ final class CalendarViewModel: ObservableObject { self.fetchProcedureDowntimeUseCase = fetchProcedureDowntimeUseCase } + func confirmDate() { + calendarTreatmentFlowState.selectedDaet = selectedDate + } + func select(date: Date) { selectedDate = date } 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 1250d044..8da83f26 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 @@ -111,7 +111,15 @@ struct NoTreatmentView: View { leadingIcon: nil, trailingIcon: nil ) { - viewModel.next() + if viewModel.state == .downTimeSetting { + Task { + try await viewModel.createUserProcedure() + tabBarCoordinator.isTabbarHidden = false + calendarCoordinator.popToRoot() + } + } else { + viewModel.next() + } } .padding(.horizontal, 25.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 5781e5c5..ce926a85 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 @@ -110,7 +110,15 @@ struct TreatmentView: View { leadingIcon: nil, trailingIcon: nil ) { - viewModel.next() + if viewModel.state == .downTimeSetting { + Task { + try await viewModel.createUserProcedure() + tabBarCoordinator.isTabbarHidden = false + calendarCoordinator.popToRoot() + } + } else { + viewModel.next() + } } .padding(.horizontal, 25.adjustedW) } 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 219d7373..9c625546 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 @@ -21,16 +21,18 @@ final class NoTreatmentViewModel: ObservableObject{ private let fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase private let fetchTreatmentsUseCase: FetchTreatmentsUseCase private let calendarTreatmentFlowState: CalendarTreatmentFlowState - + private let createUserProcedureUseCase: CreateUserProcedureUseCase init( fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase, fetchTreatmentsUseCase: FetchTreatmentsUseCase, - calendarTreatmentFlowState: CalendarTreatmentFlowState + calendarTreatmentFlowState: CalendarTreatmentFlowState, + createUserProcedureUseCase: CreateUserProcedureUseCase ) { self.fetchCategoriesUseCase = fetchCategoriesUseCase self.fetchTreatmentsUseCase = fetchTreatmentsUseCase self.calendarTreatmentFlowState = calendarTreatmentFlowState + self.createUserProcedureUseCase = createUserProcedureUseCase } var step: Int { state.rawValue } @@ -85,6 +87,22 @@ final class NoTreatmentViewModel: ObservableObject{ } } + func createUserProcedure() async throws { + guard let scheduledDate = calendarTreatmentFlowState.selectedDaet else { + return + } + + guard let recoverDate = Date.from(year: year, month: month, day: day) else { + return + } + + do { + try await createUserProcedureUseCase.excute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) + } catch { + CherrishLogger.network(CherrishError.networkRequestFailed) + } + } + func selectCategory(_ category: TreatmentCategoryEntity) { selectedCategory = category } 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 a2055672..581fd1f4 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 @@ -19,15 +19,20 @@ final class TreatmentViewModel: ObservableObject{ @Published var searchText = "" private let fetchTreatmentsUseCase: FetchTreatmentsUseCase + private let createUserProcedureUseCase: CreateUserProcedureUseCase private let calendarTreatmentFlowState: CalendarTreatmentFlowState + init( fetchTreatmentsUseCase: FetchTreatmentsUseCase, - calendarTreatmentFlowState: CalendarTreatmentFlowState + calendarTreatmentFlowState: CalendarTreatmentFlowState, + createUserProcedureUseCase: CreateUserProcedureUseCase ) { self.fetchTreatmentsUseCase = fetchTreatmentsUseCase + self.createUserProcedureUseCase = createUserProcedureUseCase self.calendarTreatmentFlowState = calendarTreatmentFlowState } + var step: Int { state.rawValue } @@ -62,6 +67,23 @@ final class TreatmentViewModel: ObservableObject{ } } + + func createUserProcedure() async throws { + guard let scheduledDate = calendarTreatmentFlowState.selectedDaet else { + return + } + + guard let recoverDate = Date.from(year: year, month: month, day: day) else { + return + } + + do { + try await createUserProcedureUseCase.excute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) + } catch { + CherrishLogger.network(CherrishError.networkRequestFailed) + } + } + func next() { state.next() } @@ -78,14 +100,21 @@ final class TreatmentViewModel: ObservableObject{ guard !year.isEmpty, !month.isEmpty, !day.isEmpty else { return false } + guard let yearInt = Int(year), yearInt >= 2020, - let monthInt = Int(month), monthInt >= 1, monthInt <= 12, - let dayInt = Int(day), dayInt >= 1, dayInt <= 31 else { + let monthInt = Int(month), (1...12).contains(monthInt), + let dayInt = Int(day), (1...31).contains(dayInt) else { return false } - return true + let components = DateComponents(year: yearInt, month: monthInt, day: dayInt) + guard let date = Calendar.current.date(from: components), + Calendar.current.dateComponents([.year, .month, .day], from: date) == components else { + return false + } + + return true } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date+.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date+.swift index e6ab2b30..9c157588 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date+.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date+.swift @@ -45,3 +45,29 @@ extension Date { return abs(calendar.dateComponents([.day], from: fromDate, to: toDate).day ?? 0) } } + +extension Date { + var toScheduledAtFormat: String { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss" + return formatter.string(from: self) + } + + var toRecoveryDateFormat: String { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd" + return formatter.string(from: self) + } + + static func from(year: String, month: String, day: String) -> Date? { + guard let y = Int(year), + let m = Int(month), + let d = Int(day) else { return nil } + + var components = DateComponents() + components.year = y + components.month = m + components.day = d + return Calendar.current.date(from: components) + } +} diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift index a4738c52..5c54ff10 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift @@ -32,6 +32,7 @@ final class PresentationDependencyAssembler: DependencyAssembler { guard let fetchProcedureCountOfMonthUseCase = DIContainer.shared.resolve(type: FetchProcedureCountOfMonth.self), let fetchTodayProcedureListUseCase = DIContainer.shared.resolve(type: FetchTodayProcedureListUseCase.self), + let fetchProcedureDowntimeUseCase = DIContainer.shared.resolve(type: FetchProcedureDowntimeUseCase.self) else { CherrishLogger.error(CherrishError.DIFailedError) return @@ -46,7 +47,8 @@ final class PresentationDependencyAssembler: DependencyAssembler { return CalendarViewModel( fetchProcedureCountOfMonthUseCase: fetchProcedureCountOfMonthUseCase, fetchTodayProcedureListUseCase: fetchTodayProcedureListUseCase, - fetchProcedureDowntimeUseCase: fetchProcedureDowntimeUseCase + fetchProcedureDowntimeUseCase: fetchProcedureDowntimeUseCase, + calendarTreatmentFlowState: calendarTreatmentFlowState ) } @@ -71,19 +73,26 @@ final class PresentationDependencyAssembler: DependencyAssembler { return SelectTreatmentViewModel() } + + + guard let createUserProcedureUseCase = DIContainer.shared.resolve(type: CreateUserProcedureUseCase.self) else { + return + } + DIContainer.shared.register(type: NoTreatmentViewModel.self) { return NoTreatmentViewModel( fetchCategoriesUseCase: fetchTreatmentCategoriesUseCase, fetchTreatmentsUseCase: fetchTreatmentsUseCase, - calendarTreatmentFlowState: calendarTreatmentFlowState + calendarTreatmentFlowState: calendarTreatmentFlowState, + createUserProcedureUseCase: createUserProcedureUseCase ) } - DIContainer.shared.register(type: TreatmentViewModel.self) { return TreatmentViewModel( fetchTreatmentsUseCase: fetchTreatmentsUseCase, - calendarTreatmentFlowState: calendarTreatmentFlowState + calendarTreatmentFlowState: calendarTreatmentFlowState, + createUserProcedureUseCase: createUserProcedureUseCase, ) } } From 4d89faca2b9803f08204af86b97667ecf04847d4 Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Wed, 21 Jan 2026 20:10:35 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20#125=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Model/CreateUserProcedureRequestDTO.swift | 4 ++-- .../CreateUserProcedureResponseDTO.swift | 22 +++++++++++++++++++ .../Data/Repository/TreatmentRepository.swift | 17 ++++++++++++-- .../UseCase/CreateUserProcedureUseCase.swift | 4 ++-- .../View/NoTreatment/NoTreatmentView.swift | 3 +++ .../NoTreatment/NoTreatmentViewModel.swift | 4 ++-- .../Treatment/TreatmentViewModel.swift | 4 ++-- .../Presentation/Global/Extension/Date+.swift | 17 +++++++++----- 8 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureResponseDTO.swift diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureRequestDTO.swift b/Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureRequestDTO.swift index c3c05d28..e173d9de 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureRequestDTO.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureRequestDTO.swift @@ -7,12 +7,12 @@ import Foundation -struct UserProcedureItemRequestDTO: Encodable, Decodable { +struct UserProcedureItemRequestDTO: Encodable { let procedureId: Int let downtimeDays: Int } -struct CreateUserProcedureRequestDTO: Encodable, Decodable { +struct CreateUserProcedureRequestDTO: Encodable { let scheduledAt: String let recoveryTargetDate: String let procedures: [UserProcedureItemRequestDTO] diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureResponseDTO.swift b/Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureResponseDTO.swift new file mode 100644 index 00000000..5d08e459 --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Data/Model/CreateUserProcedureResponseDTO.swift @@ -0,0 +1,22 @@ +// +// CreateUserProcedureResponseDTO.swift +// Cherrish-iOS +// +// Created by 어재선 on 1/21/26. +// + +import Foundation + + +struct CreateUserProcedureResponseDTO: Decodable { + let userProcedureId: Int + let procedureId: Int + let procedureName: String + let scheduledAt: String + let downtimeDays: Int + let recoveryTargetDate: String +} + +struct CreateUserProceduresResponseDTO: Decodable { + let procedures: [CreateUserProcedureResponseDTO] +} diff --git a/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift b/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift index 591e677a..2f5ca60d 100644 --- a/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift +++ b/Cherrish-iOS/Cherrish-iOS/Data/Repository/TreatmentRepository.swift @@ -31,7 +31,14 @@ struct DefaultTreatmentRepository: TreatmentInterface { func fetchTreatment(id: Int?, keyword: String?) async throws -> [TreatmentEntity] { 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) + let response = try await networkService.request( + TreatmentAPI.fetchProcedures( + userId: userId, + id: id, + text: keyword + ), + decodingType: ProceduresResponseDTO.self + ) return response.procedures.map { $0.toEntity() } } @@ -42,7 +49,13 @@ struct DefaultTreatmentRepository: TreatmentInterface { recoveryTargetDate: recoveryDate, procedures: treatments.compactMap { $0.toRequestDTO() } ) - let _ = try await networkService.request(TreatmentAPI.createUserProcedure(userId: userId, request: request), decodingType: UserProcedureItemRequestDTO.self) + let _ = try await networkService.request( + TreatmentAPI.createUserProcedure( + userId: userId, + request: request + ), + decodingType: CreateProfileResponseDTO.self + ) } } diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift b/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift index 57cae44d..f6728a5b 100644 --- a/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift +++ b/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift @@ -8,7 +8,7 @@ import Foundation protocol CreateUserProcedureUseCase { - func excute(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws + func execute(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws } struct DefaultCreateUserProcedureUseCase: CreateUserProcedureUseCase { @@ -19,7 +19,7 @@ struct DefaultCreateUserProcedureUseCase: CreateUserProcedureUseCase { self.repository = repository } - func excute(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws { + func execute(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws { return try await repository.createUserProcedure(scheduledDate: scheduledDate, recoveryDate: recoveryDate, treatments: treatments) } } 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 8da83f26..5b17fd7e 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 @@ -55,6 +55,9 @@ struct NoTreatmentView: View { .onAppear { tabBarCoordinator.isTabbarHidden = true } + .onTapGesture { + hideKeyboard() + } } @ViewBuilder 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 9c625546..32947ab9 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 @@ -97,9 +97,9 @@ final class NoTreatmentViewModel: ObservableObject{ } do { - try await createUserProcedureUseCase.excute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) + try await createUserProcedureUseCase.execute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) } catch { - CherrishLogger.network(CherrishError.networkRequestFailed) + CherrishLogger.network(error) } } 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 581fd1f4..ab3270f7 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 @@ -78,9 +78,9 @@ final class TreatmentViewModel: ObservableObject{ } do { - try await createUserProcedureUseCase.excute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) + try await createUserProcedureUseCase.execute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) } catch { - CherrishLogger.network(CherrishError.networkRequestFailed) + CherrishLogger.network(error) } } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date+.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date+.swift index 9c157588..42a2684a 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date+.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date+.swift @@ -47,16 +47,23 @@ extension Date { } extension Date { - var toScheduledAtFormat: String { + private static let scheduledAtFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss" - return formatter.string(from: self) + formatter.locale = Locale(identifier: "ko_KR") + formatter.timeZone = TimeZone(identifier: "Asia/Seoul") + return formatter + }() +} + + +extension Date { + var toScheduledAtFormat: String { + return Date.scheduledAtFormatter.string(from: self) } var toRecoveryDateFormat: String { - let formatter = DateFormatter() - formatter.dateFormat = "yyyy-MM-dd" - return formatter.string(from: self) + return Date.dateFormatter.string(from: self) } static func from(year: String, month: String, day: String) -> Date? { From d6f7755fdaa9a73f921bcbe62ddf26999c89d07d Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Wed, 21 Jan 2026 20:12:18 +0900 Subject: [PATCH 5/6] =?UTF-8?q?chore:=20#125=20=EA=B0=9C=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Domain/UseCase/CreateUserProcedureUseCase.swift | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift b/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift index f6728a5b..74918270 100644 --- a/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift +++ b/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift @@ -19,7 +19,16 @@ struct DefaultCreateUserProcedureUseCase: CreateUserProcedureUseCase { self.repository = repository } - func execute(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws { - return try await repository.createUserProcedure(scheduledDate: scheduledDate, recoveryDate: recoveryDate, treatments: treatments) + func execute( + scheduledDate: String, + recoveryDate: String, + treatments: [TreatmentEntity] + ) async throws { + return try await repository + .createUserProcedure( + scheduledDate: scheduledDate, + recoveryDate: recoveryDate, + treatments: treatments + ) } } From d8546f458a4290f1ef764cee0ba96ef21abdaa4a Mon Sep 17 00:00:00 2001 From: JaeSunEo Date: Wed, 21 Jan 2026 20:28:48 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20#125=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 --- .../Feature/Calendar/CalendarMain/CalendarView.swift | 4 ++-- .../Feature/Calendar/CalendarMain/CalendarViewModel.swift | 6 +----- .../Feature/Calendar/CalendarTreatmentFlowState.swift | 2 +- .../Treatment/View/NoTreatment/NoTreatmentView.swift | 7 ++++++- .../Calendar/Treatment/View/Treatment/TreatmentView.swift | 7 ++++++- .../ViewModel/NoTreatment/NoTreatmentViewModel.swift | 2 +- .../Treatment/ViewModel/Treatment/TreatmentViewModel.swift | 2 +- .../Presentation/PresentationDependencyAssembler.swift | 2 +- 8 files changed, 19 insertions(+), 13 deletions(-) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift index 788ffd20..e244ecdd 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift @@ -150,7 +150,7 @@ extension CalendarView { .foregroundStyle(.gray600) .frame(width: 24.adjustedW, height: 24.adjustedH) .onTapGesture { - viewModel.confirmDate() + viewModel.sendDateToTreatmentView() calendarCoordinator.push(.selectTreatment) } case .selectedProcedure: @@ -253,7 +253,7 @@ extension CalendarView { leadingIcon: Image(.plus), trailingIcon: nil, action: { - viewModel.confirmDate() + viewModel.sendDateToTreatmentView() calendarCoordinator.push( .selectTreatment ) diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift index 2ab37a2d..369dff13 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift @@ -40,10 +40,6 @@ final class CalendarViewModel: ObservableObject { self.fetchProcedureDowntimeUseCase = fetchProcedureDowntimeUseCase } - func confirmDate() { - calendarTreatmentFlowState.selectedDaet = selectedDate - } - func select(date: Date) { selectedDate = date } @@ -102,7 +98,7 @@ final class CalendarViewModel: ObservableObject { } func sendDateToTreatmentView() { - calendarTreatmentFlowState.selectedDaet = selectedDate + calendarTreatmentFlowState.selectedDate = selectedDate } @MainActor diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarTreatmentFlowState.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarTreatmentFlowState.swift index 4b8fad97..d113c2de 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarTreatmentFlowState.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarTreatmentFlowState.swift @@ -8,5 +8,5 @@ import Foundation final class CalendarTreatmentFlowState: ObservableObject { - @Published var selectedDaet: Date? + @Published var selectedDate: Date? } 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 5b17fd7e..9b6ba0d7 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 @@ -116,7 +116,12 @@ struct NoTreatmentView: View { ) { if viewModel.state == .downTimeSetting { Task { - try await viewModel.createUserProcedure() + do { + try await viewModel.createUserProcedure() + } catch { + CherrishLogger.error(error) + } + tabBarCoordinator.isTabbarHidden = false calendarCoordinator.popToRoot() } 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 ce926a85..e6302211 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 @@ -112,7 +112,12 @@ struct TreatmentView: View { ) { if viewModel.state == .downTimeSetting { Task { - try await viewModel.createUserProcedure() + do { + try await viewModel.createUserProcedure() + } catch { + CherrishLogger.error(error) + } + tabBarCoordinator.isTabbarHidden = false calendarCoordinator.popToRoot() } 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 32947ab9..a154d906 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 @@ -88,7 +88,7 @@ final class NoTreatmentViewModel: ObservableObject{ } func createUserProcedure() async throws { - guard let scheduledDate = calendarTreatmentFlowState.selectedDaet else { + guard let scheduledDate = calendarTreatmentFlowState.selectedDate else { return } 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 ab3270f7..3b01522a 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 @@ -69,7 +69,7 @@ final class TreatmentViewModel: ObservableObject{ func createUserProcedure() async throws { - guard let scheduledDate = calendarTreatmentFlowState.selectedDaet else { + guard let scheduledDate = calendarTreatmentFlowState.selectedDate else { return } diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift index 3e66d37c..57f6e344 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/PresentationDependencyAssembler.swift @@ -92,7 +92,7 @@ final class PresentationDependencyAssembler: DependencyAssembler { return TreatmentViewModel( fetchTreatmentsUseCase: fetchTreatmentsUseCase, calendarTreatmentFlowState: calendarTreatmentFlowState, - createUserProcedureUseCase: createUserProcedureUseCase, + createUserProcedureUseCase: createUserProcedureUseCase ) }