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..e173d9de --- /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 { + let procedureId: Int + let downtimeDays: Int +} + +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/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/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..2f5ca60d 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 @@ -29,12 +31,40 @@ 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() } } + + 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: CreateProfileResponseDTO.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 f8160306..a0a8b67e 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) } @@ -76,5 +72,9 @@ final class DomainDependencyAssembler: DependencyAssembler { DIContainer.shared.register(type: FetchUserInfoUseCase.self) { return DefaultFetchUserInfoUserCase(repository: myPageRepository) } + + 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..74918270 --- /dev/null +++ b/Cherrish-iOS/Cherrish-iOS/Domain/UseCase/CreateUserProcedureUseCase.swift @@ -0,0 +1,34 @@ +// +// CreateUserProcedureUseCase.swift +// Cherrish-iOS +// +// Created by 어재선 on 1/21/26. +// + +import Foundation + +protocol CreateUserProcedureUseCase { + func execute(scheduledDate: String, recoveryDate: String, treatments: [TreatmentEntity]) async throws +} + +struct DefaultCreateUserProcedureUseCase: CreateUserProcedureUseCase { + + private let repository: TreatmentInterface + + init(repository: TreatmentInterface) { + self.repository = repository + } + + 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/CalendarMain/CalendarView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarView.swift index 16f11360..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,6 +150,7 @@ extension CalendarView { .foregroundStyle(.gray600) .frame(width: 24.adjustedW, height: 24.adjustedH) .onTapGesture { + viewModel.sendDateToTreatmentView() calendarCoordinator.push(.selectTreatment) } case .selectedProcedure: @@ -252,9 +253,11 @@ extension CalendarView { leadingIcon: Image(.plus), trailingIcon: nil, action: { + viewModel.sendDateToTreatmentView() 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 fdc772cf..369dff13 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Calendar/CalendarMain/CalendarViewModel.swift @@ -26,14 +26,17 @@ final class CalendarViewModel: ObservableObject { private let fetchProcedureCountOfMonthUseCase: FetchProcedureCountOfMonth private let fetchTodayProcedureListUseCase: FetchTodayProcedureListUseCase private let fetchProcedureDowntimeUseCase: FetchProcedureDowntimeUseCase + private let calendarTreatmentFlowState: CalendarTreatmentFlowState init( fetchProcedureCountOfMonthUseCase: FetchProcedureCountOfMonth, fetchTodayProcedureListUseCase: FetchTodayProcedureListUseCase, - fetchProcedureDowntimeUseCase: FetchProcedureDowntimeUseCase + fetchProcedureDowntimeUseCase: FetchProcedureDowntimeUseCase, + calendarTreatmentFlowState: CalendarTreatmentFlowState ) { self.fetchProcedureCountOfMonthUseCase = fetchProcedureCountOfMonthUseCase self.fetchTodayProcedureListUseCase = fetchTodayProcedureListUseCase + self.calendarTreatmentFlowState = calendarTreatmentFlowState self.fetchProcedureDowntimeUseCase = fetchProcedureDowntimeUseCase } @@ -94,6 +97,10 @@ final class CalendarViewModel: ObservableObject { return procedureList.isEmpty } + func sendDateToTreatmentView() { + calendarTreatmentFlowState.selectedDate = 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..d113c2de --- /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 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 cf35b030..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 @@ -55,6 +55,9 @@ struct NoTreatmentView: View { .onAppear { tabBarCoordinator.isTabbarHidden = true } + .onTapGesture { + hideKeyboard() + } } @ViewBuilder @@ -62,7 +65,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 +74,6 @@ struct NoTreatmentView: View { month: $viewModel.month, day: $viewModel.day ) - .padding(.horizontal, 34.adjustedW) .id(String(describing: viewModel.state)) case .treatmentFilter: @@ -113,7 +114,20 @@ struct NoTreatmentView: View { leadingIcon: nil, trailingIcon: nil ) { - viewModel.next() + if viewModel.state == .downTimeSetting { + Task { + do { + try await viewModel.createUserProcedure() + } catch { + CherrishLogger.error(error) + } + + tabBarCoordinator.isTabbarHidden = false + calendarCoordinator.popToRoot() + } + } else { + viewModel.next() + } } .padding(.horizontal, 25.adjustedW) } @@ -160,7 +174,7 @@ private struct TreatmentSelectedCategory: View { Spacer() } - + .padding(.horizontal, 34.adjustedW) Spacer() .frame(height: 40.adjustedH) ScrollView(.vertical, showsIndicators:false) { @@ -182,7 +196,7 @@ private struct TreatmentSelectedCategory: View { ) ) } - } + } .padding(.horizontal, 34.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..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 @@ -110,7 +110,20 @@ struct TreatmentView: View { leadingIcon: nil, trailingIcon: nil ) { - viewModel.next() + if viewModel.state == .downTimeSetting { + Task { + do { + try await viewModel.createUserProcedure() + } catch { + CherrishLogger.error(error) + } + + 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 0413318e..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 @@ -20,10 +20,19 @@ 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) { + init( + fetchCategoriesUseCase: FetchTreatmentCategoriesUseCase, + fetchTreatmentsUseCase: FetchTreatmentsUseCase, + calendarTreatmentFlowState: CalendarTreatmentFlowState, + createUserProcedureUseCase: CreateUserProcedureUseCase + ) { self.fetchCategoriesUseCase = fetchCategoriesUseCase self.fetchTreatmentsUseCase = fetchTreatmentsUseCase + self.calendarTreatmentFlowState = calendarTreatmentFlowState + self.createUserProcedureUseCase = createUserProcedureUseCase } var step: Int { state.rawValue } @@ -64,7 +73,7 @@ final class NoTreatmentViewModel: ObservableObject{ do { categories = try await fetchCategoriesUseCase.execute() } catch { - + CherrishLogger.debug(error) } } @@ -74,6 +83,23 @@ final class NoTreatmentViewModel: ObservableObject{ treatments = try await fetchTreatmentsUseCase.execute(id: selectedCategory?.id, keyword: "") } catch { treatments = [] + CherrishLogger.debug(error) + } + } + + func createUserProcedure() async throws { + guard let scheduledDate = calendarTreatmentFlowState.selectedDate else { + return + } + + guard let recoverDate = Date.from(year: year, month: month, day: day) else { + return + } + + do { + try await createUserProcedureUseCase.execute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) + } catch { + 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 05288c9f..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 @@ -19,10 +19,20 @@ final class TreatmentViewModel: ObservableObject{ @Published var searchText = "" private let fetchTreatmentsUseCase: FetchTreatmentsUseCase + private let createUserProcedureUseCase: CreateUserProcedureUseCase + private let calendarTreatmentFlowState: CalendarTreatmentFlowState - init(fetchTreatmentsUseCase: FetchTreatmentsUseCase) { + + init( + fetchTreatmentsUseCase: FetchTreatmentsUseCase, + calendarTreatmentFlowState: CalendarTreatmentFlowState, + createUserProcedureUseCase: CreateUserProcedureUseCase + ) { self.fetchTreatmentsUseCase = fetchTreatmentsUseCase + self.createUserProcedureUseCase = createUserProcedureUseCase + self.calendarTreatmentFlowState = calendarTreatmentFlowState } + var step: Int { state.rawValue } @@ -37,26 +47,43 @@ 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 = [] } } + + func createUserProcedure() async throws { + guard let scheduledDate = calendarTreatmentFlowState.selectedDate else { + return + } + + guard let recoverDate = Date.from(year: year, month: month, day: day) else { + return + } + + do { + try await createUserProcedureUseCase.execute(scheduledDate: scheduledDate.toScheduledAtFormat, recoveryDate: recoverDate.toRecoveryDateFormat, treatments: selectedTreatments) + } catch { + CherrishLogger.network(error) + } + } + func next() { state.next() } @@ -73,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 } } @@ -91,7 +125,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/Feature/Onboarding/SplashView.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Onboarding/SplashView.swift index 24193cc7..6447115d 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Onboarding/SplashView.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Feature/Onboarding/SplashView.swift @@ -9,8 +9,13 @@ import SwiftUI struct SplashView: View { @EnvironmentObject private var appCoordinator: AppCoordinator - private let userDefaultService: UserDefaultService = DefaultUserDefaultService() - + + private let userDefaultService: UserDefaultService + + init(userDefaultService: UserDefaultService = DefaultUserDefaultService()) { + self.userDefaultService = userDefaultService + } + var body: some View { ZStack(alignment: .center) { LinearGradient( diff --git a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date+.swift b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date+.swift index e6ab2b30..42a2684a 100644 --- a/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date+.swift +++ b/Cherrish-iOS/Cherrish-iOS/Presentation/Global/Extension/Date+.swift @@ -45,3 +45,36 @@ extension Date { return abs(calendar.dateComponents([.day], from: fromDate, to: toDate).day ?? 0) } } + +extension Date { + private static let scheduledAtFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss" + 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 { + return Date.dateFormatter.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 6c5b75a3..57f6e344 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 @@ -34,11 +38,17 @@ final class PresentationDependencyAssembler: DependencyAssembler { 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, - fetchProcedureDowntimeUseCase: fetchProcedureDowntimeUseCase + fetchProcedureDowntimeUseCase: fetchProcedureDowntimeUseCase, + calendarTreatmentFlowState: calendarTreatmentFlowState ) } @@ -63,13 +73,27 @@ final class PresentationDependencyAssembler: DependencyAssembler { return SelectTreatmentViewModel() } - DIContainer.shared.register(type: NoTreatmentViewModel.self) { - return NoTreatmentViewModel(fetchCategoriesUseCase: fetchTreatmentCategoriesUseCase, fetchTreatmentsUseCase: fetchTreatmentsUseCase) + + + 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, + createUserProcedureUseCase: createUserProcedureUseCase + ) + } DIContainer.shared.register(type: TreatmentViewModel.self) { - return TreatmentViewModel(fetchTreatmentsUseCase: fetchTreatmentsUseCase) + return TreatmentViewModel( + fetchTreatmentsUseCase: fetchTreatmentsUseCase, + calendarTreatmentFlowState: calendarTreatmentFlowState, + createUserProcedureUseCase: createUserProcedureUseCase + ) } guard let fetchUserInfoUseCase = DIContainer.shared.resolve(type: FetchUserInfoUseCase.self) else {