diff --git a/HMH_Tuist_iOS/Projects/App/Sources/Common/Custom/PickerView.swift b/HMH_Tuist_iOS/Projects/App/Sources/Common/Custom/PickerView.swift index 3bd83e89..c750a5d3 100644 --- a/HMH_Tuist_iOS/Projects/App/Sources/Common/Custom/PickerView.swift +++ b/HMH_Tuist_iOS/Projects/App/Sources/Common/Custom/PickerView.swift @@ -73,7 +73,7 @@ class PickerCoordinator: NSObject, UIPickerViewDelegate, UIPickerViewDataSource func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { selectedTime.wrappedValue = times[row] - viewModel.isCompleted = true +// viewModel.isCompleted = true } func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat { diff --git a/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingUseCase.swift b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingUseCase.swift index 52879bd2..0648be64 100644 --- a/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingUseCase.swift +++ b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingUseCase.swift @@ -18,12 +18,15 @@ public protocol OnboardingUseCaseType { userName: String, averageUseTime: String, problems: [String], - period: Int + period: Int, + goalTime: Int ) -> AnyPublisher + func calculateGoalTime(hour: String, minute: String) -> Int + func removeLastCharacterAndConvertToInt(from string: String) -> Int? } public final class OnboardingUseCase: OnboardingUseCaseType { - + private let repository: AuthRepositoryType public init(repository: AuthRepositoryType) { @@ -35,9 +38,10 @@ public final class OnboardingUseCase: OnboardingUseCaseType { userName: String, averageUseTime: String, problems: [String], - period: Int + period: Int, + goalTime: Int ) -> AnyPublisher { - let challengeInfo = ChallengeInfo(period: period, goalTime: 0, apps: []) + let challengeInfo = ChallengeInfo(period: period, goalTime: goalTime, apps: []) return repository.signUp( socialPlatform: socialPlatform, @@ -56,5 +60,24 @@ public final class OnboardingUseCase: OnboardingUseCaseType { } .eraseToAnyPublisher() } + + public func calculateGoalTime(hour: String, minute: String) -> Int { + let hourInt = Int(hour) ?? 0 + let minuteInt = Int(minute) ?? 0 + + let totalMinutes = hourInt * 60 + minuteInt + let totalMilliseconds = totalMinutes * 60 * 1000 + return totalMilliseconds + } + + public func removeLastCharacterAndConvertToInt(from string: String) -> Int? { + guard !string.isEmpty else { + return nil + } + + let modifiedString = String(string.dropLast()) + + return Int(modifiedString) + } } diff --git a/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingViewModel_Refactor.swift b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingViewModel_Refactor.swift deleted file mode 100644 index 2df2948d..00000000 --- a/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingViewModel_Refactor.swift +++ /dev/null @@ -1,237 +0,0 @@ -// -// OnboardingViewModel_Refactor.swift -// OnboardingFeatureInterface -// -// Created by Seonwoo Kim on 11/18/24. -// Copyright © 2024 HMH-iOS. All rights reserved. -// - -import Foundation -import Combine - -import Core -import Domain -import DSKit - -public final class OnboardingViewModel : ObservableObject { - - private let useCase: OnboardingUseCaseType - private var cancelBag = CancelBag() - - @Published private(set) var state = State(onboardingState: .timeSurveySelect, surveyButtonItems: [[]], isNextAvailable: false, surveyState: 0) - @Published - var selectedAppHour: String - @Published - var selectedAppMinute: String - - var userName: String - var averageUseTime: String - var problems: [String] - var period: Int - var appGoalTime: Int - - public init(useCase: OnboardingUseCaseType) { - self.useCase = useCase - self.state = State( - onboardingState: .timeSurveySelect, - surveyButtonItems: SurveyButtonInfo.initializeSurveyButtonItems(), - isNextAvailable: false, - surveyState: 0 - ) - self.userName = "" - self.averageUseTime = "" - self.problems = [] - self.period = 0 - self.selectedAppHour = "" - self.selectedAppMinute = "" - self.appGoalTime = 0 - } - - // MARK: Action - - enum Action { - case nextButtonTap - case arrowButtonTap - case surveyButtonTap(index: Int) - } - - // MARK: State - - struct State { - var onboardingState: OnboardingState - var surveyButtonItems: [[SurveyButtonInfo]] - var isNextAvailable: Bool - var surveyState: Int - } - - func send(action: Action) { - switch action { - case .nextButtonTap: - handleNextButtonTap() - case .arrowButtonTap: - handleBackButtonTap() - case .surveyButtonTap(index: let index): - surveyButtonTap(index: index) - } - } - - func surveyButtonTap(index: Int) { - guard state.onboardingState.rawValue < state.surveyButtonItems.count else { return } - - let currentSurveyItems = state.surveyButtonItems[state.onboardingState.rawValue] - - switch state.onboardingState { - case .timeSurveySelect, .challangePeriodSelect, .goalTimeSelect: - for i in 0.. Int { - let hourInt = Int(hour ?? "") ?? 0 - let minuteInt = Int(minute ?? "") ?? 0 - - let totalMinutes = hourInt * 60 + minuteInt - let totalMilliseconds = totalMinutes * 60 * 1000 - return totalMilliseconds - } - - private func addOnboardingState() { - guard let nextState = OnboardingState(rawValue: state.onboardingState.rawValue + 1) else { return } - state.onboardingState = nextState - - if nextState.rawValue <= 2 { - state.surveyState = nextState.rawValue - } - } - - - private func removeLastCharacterAndConvertToInt(from string: String) -> Int? { - guard !string.isEmpty else { - return nil - } - - let modifiedString = String(string.dropLast()) - - return Int(modifiedString) - } - - private func handleBackButtonTap() { - switch state.onboardingState { - case .timeSurveySelect: - UserManager.shared.appStateString = "login" - offIsCompleted() - case .problemSurveySelect, .challangePeriodSelect, .goalTimeSelect: - guard let previousState = OnboardingState(rawValue: state.onboardingState.rawValue - 1) else { return } - state.onboardingState = previousState - state.surveyState = previousState.rawValue - resetSelections(for: previousState) - offIsCompleted() - default: - guard let previousState = OnboardingState(rawValue: state.onboardingState.rawValue - 1) else { return } - state.onboardingState = previousState - onIsCompleted() - } - - print(state.onboardingState.rawValue) - } - - - private func offIsCompleted() { - state.isNextAvailable = false - } - - private func onIsCompleted() { - state.isNextAvailable = true - } - - private func completOnboarding() { - useCase.postSignUpData(socialPlatform: "KAKAO", userName: "", averageUseTime: averageUseTime, problems: problems, period: period) - .sink(receiveCompletion: { _ in }) { - } - .store(in: cancelBag) - } - -} diff --git a/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/ViewModels/OnboardingViewModel.swift b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/ViewModels/OnboardingViewModel.swift index 8c5027ce..933431db 100644 --- a/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/ViewModels/OnboardingViewModel.swift +++ b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/ViewModels/OnboardingViewModel.swift @@ -1,398 +1,216 @@ -//// -//// OnboardingViewModel.swift -//// HMH_iOS -//// -//// Created by Seonwoo Kim on 3/24/24. -//// // -//import SwiftUI -//import FamilyControls -//import Foundation +// OnboardingViewModel.swift +// OnboardingFeatureInterface // -//import Core -//import DSKit -//import Domain +// Created by Seonwoo Kim on 11/18/24. +// Copyright © 2024 HMH-iOS. All rights reserved. // -// -//public class OnboardingViewModel_refactor: ObservableObject { -// -// //TODO: 말썽꾸러기 스크린뷰모델 -//// var screenViewModel: ScreenTimeViewModel -// -// @Published -// var surveyButtonItems: [[SurveyButtonInfo]] -// -// var problems: [String] -// -// @Published -// var onboardingState: Int -// -// @Published -// public var isCompleted: Bool -// -// @Published -// var isPickerPresented: Bool = false -// -// @Published -// var isOnboardingError : Bool = false -// -// @Published -// var isCompletePresented: Bool = false -// -// @Published -// var selectedGoalTime: String -// -// @Published -// var selectedAppHour: String -// -// @Published -// var selectedAppMinute: String -// -// var averageUseTime: String -// -// var period: Int -// -// var isChallengeMode: Bool -// -// var goalTime: Int -// -// var appGoalTime: Int -// -// @AppStorage("socialPlatform") private var socialPlatform = "" -// @AppStorage("userName") private var userName = "" -// -// @MainActor func saveOnboardingData() { -// print(onboardingState) -// switch onboardingState { -// case 0: -// for index in 0..<4{ -// if surveyButtonItems[onboardingState][index].isSelected { -// self.averageUseTime = surveyButtonItems[onboardingState][index].buttonTitle -// } -// } -// addOnboardingState() -// offIsCompleted() -// case 1: -// for index in 0..<4{ -// if surveyButtonItems[onboardingState][index].isSelected { -// self.problems.append(surveyButtonItems[onboardingState][index].buttonTitle) -// } -// } -// addOnboardingState() -// offIsCompleted() -// case 2: -// for index in 0..<4{ -// if surveyButtonItems[onboardingState] [index].isSelected { -// self.period = removeLastCharacterAndConvertToInt(from: surveyButtonItems[onboardingState] [index].buttonTitle) ?? 0 -// -// print(surveyButtonItems[onboardingState] [index].buttonTitle) -// -// } -// } -// if isChallengeMode { -// onboardingState = 6 -// } else { -// addOnboardingState() -// } -// case 3: -// break -// //TODO: 말썽꾸러기 스크린뷰모델 -//// screenViewModel.requestAuthorization() -//// if screenViewModel.authorizationCenter.authorizationStatus == .approved { -//// onboardingState += 1 -//// } -// case 4: -// isPickerPresented = true -// case 5: -// self.appGoalTime = convertToTotalMilliseconds(hour: selectedAppHour, minute: selectedAppMinute) -// if isChallengeMode { -// //TODO: 말썽꾸러기 스크린뷰모델 -//// screenViewModel.handleStartDeviceActivityMonitoring(interval: appGoalTime) -// addOnboardingState() -// } else { -// addOnboardingState() -// } -// offIsCompleted() -// case 6: -// self.goalTime = convertToTotalMilliseconds(hour: selectedGoalTime, minute: "0") -// //TODO: 말썽꾸러기 스크린뷰모델 -//// screenViewModel.handleTotalDeviceActivityMonitoring(interval: goalTime) -// if isChallengeMode { -// postCreateChallengeData() -// isCompletePresented = true -// } else { -// postSignUpLoginData() -// } -// offIsCompleted() -// default: -// break -// } -// } -// -// func alertAction() { -// postCreateChallengeData() -// addOnboardingState() -// isCompletePresented = false -// } -// -// func addOnboardingState() { -// onboardingState += 1 -// } -// -// func backButtonTapped() { -// switch onboardingState { -// case 0: -// UserManager.shared.appStateString = "login" -// offIsCompleted() -// case 1, 2, 3 : -// onboardingState -= 1 -// offIsCompleted() -// resetAllSelections() -// case 6: -// onboardingState -= 1 -// offIsCompleted() -// default: -// onIsCompleted() -// onboardingState -= 1 -// } -// } -// -// func onIsCompleted() { -// isCompleted = true -// } -// -// func offIsCompleted() { -// isCompleted = false -// } -// -// func resetOnboardingState() { -// onboardingState = 0 -// } -// -// public func getSurveyState() -> Int { -// return onboardingState <= 2 ? onboardingState : 0 -// } -// -// func pushToComplete() { -// // if onboardingState == 6 { -// // NavigationLink(PermissionView) -// // } -// } -// -// func removeLastCharacterAndConvertToInt(from string: String) -> Int? { -// guard !string.isEmpty else { -// return nil -// } -// -// let modifiedString = String(string.dropLast()) -// -// return Int(modifiedString) -// } -// -// -// @MainActor func postSignUpLoginData() { -// //TODO: 네트워크 부분은 의존성 정리한 뒤에 다시 연결해봅시다 -//// let appValues = [ Apps( -//// appCode: "app goalTime", -//// goalTime: appGoalTime -//// ) -//// ] -//// let request = SignUpRequestDTO( -//// socialPlatform: socialPlatform, -//// name: userName, -//// onboarding: Onboarding( -//// averageUseTime: self.averageUseTime, -//// problem: self.problems -//// ), -//// challenge: Challenge( -//// period: self.period, -//// goalTime: self.goalTime, -//// apps: appValues -//// ) -//// ) -//// -//// let provider = Providers.AuthProvider -//// provider.request(target: .signUp(data: request), instance: BaseResponse.self) { data in -//// print(data.status) -//// if data.status == 201 { -//// UserManager.shared.appStateString = "onboardingComplete" -//// UserManager.shared.accessToken = data.data?.token.accessToken ?? "" -//// UserManager.shared.refreshToken = data.data?.token.refreshToken ?? "" -//// } else if data.message == "이미 회원가입된 유저입니다." { -//// self.isOnboardingError = true -//// } else { -//// self.isOnboardingError = true -//// } -//// } -// } -// -// func postCreateChallengeData() { -// //TODO: 네트워크 부분은 의존성 정리한 뒤에 다시 연결해봅시다 -//// let request = CreateChallengeRequestDTO(period: self.period, goalTime: self.goalTime) -//// -//// let provider = Providers.challengeProvider -//// provider.request(target: .createChallenge(data: request), instance: BaseResponse.self) { data in -//// print(data.status) -//// } -// } -// -// func patchApp(appGoalTime: Int) { -// //TODO: 네트워크 부분은 의존성 정리한 뒤에 다시 연결해봅시다 -//// let applist = [ -//// Apps( -//// appCode: "#temp", -//// goalTime: appGoalTime -//// ) -//// ] -//// let requestDTO = AddAppRequestDTO(apps: applist) -//// Providers.challengeProvider.request(target: .addApp(data: requestDTO), -//// instance: BaseResponse.self) { result in -//// print("result: \(result)") -//// } -// } -// -// @MainActor func createAppChallengeData(appGoalTime: Int) { -// //TODO: 네트워크 부분은 의존성 정리한 뒤에 다시 연결해봅시다 -//// var applist: [Apps] = [] -//// // screenViewModel.hashVaule -//// applist = [Apps(appCode: "#24333", goalTime: appGoalTime)] -//// Providers.challengeProvider.request(target: .addApp(data: AddAppRequestDTO(apps: applist)), instance: BaseResponse.self) { [weak self] result in -//// UserManager.shared.appStateString = "home" -//// self?.screenViewModel.handleStartDeviceActivityMonitoring(includeUsageThreshold: true, interval: self?.appGoalTime ?? 0) -//// } -// } -// -// func changeSurveyButtonStatus(num: Int) { -// if onboardingState == 1 { -// let selectedCount = surveyButtonItems[onboardingState].filter { $0.isSelected }.count -// if surveyButtonItems[onboardingState][num].isSelected { -// surveyButtonItems[onboardingState][num].isSelected.toggle() -// } else if selectedCount < 2 { -// surveyButtonItems[onboardingState][num].isSelected = true -// } -// } else { -// for index in 0..<4 { -// surveyButtonItems[onboardingState][index].isSelected = (index == num) -// } -// } -// } -// -// -// func convertToTotalMilliseconds(hour: String?, minute: String?) -> Int { -// let hourInt = Int(hour ?? "") ?? 0 -// let minuteInt = Int(minute ?? "") ?? 0 -// -// let totalMinutes = hourInt * 60 + minuteInt -// let totalMilliseconds = totalMinutes * 60 * 1000 -// return totalMilliseconds -// } -// -// -// func getOnboardigMain() -> String { -// switch onboardingState { -// case 0: -// StringLiteral.OnboardigMain.timeSurveySelect -// case 1: -// StringLiteral.OnboardigMain.problemSurveySelect -// case 2: -// StringLiteral.OnboardigMain.periodSelect -// case 3: -// StringLiteral.OnboardigMain.permissionSelect -// case 4: -// StringLiteral.OnboardigMain.appSelect -// case 5: -// StringLiteral.OnboardigMain.appGoalTimeSelect -// case 6: -// StringLiteral.OnboardigMain.goalTimeSelect -// default: -// "" -// } -// } -// -// func getOnboardigSub() -> String { -// switch onboardingState { -// case 0: -// "" -// case 1: -// StringLiteral.OnboardigSub.problemSurveySelect -// case 2: -// StringLiteral.OnboardigSub.periodSelect -// case 3: -// StringLiteral.OnboardigSub.permissionSelect -// case 4: -// StringLiteral.OnboardigSub.appSelect -// case 5: -// StringLiteral.OnboardigSub.appGoalTimeSelect -// case 6: -// StringLiteral.OnboardigSub.goalTimeSelect -// default: -// "" -// } -// } -// -// func getNextButton() -> String { -// switch onboardingState { -// case 0, 1, 2, 5: -// StringLiteral.OnboardingButton.next -// case 3: -// StringLiteral.OnboardingButton.permission -// case 4: -// StringLiteral.OnboardingButton.appSelect -// case 6: -// StringLiteral.OnboardingButton.complete -// default: -// "" -// } -// } -// -// func handleOnAppear() { -// if onboardingState == 3 && isChallengeMode { -// isPickerPresented = true -// } -// } -// -// func resetAllSelections() { -// for i in 0.. some View { HStack { Button(action: { - onboardingViewModel.send(action: .arrowButtonTap) + viewModel.send(action: .arrowButtonTap) }, label: { Image(uiImage: DSKitAsset.chevronLeft.image) .frame(width: 24, height: 24) @@ -133,21 +75,21 @@ extension OnboardingContentView { .cornerRadius(1.0) Rectangle() .foregroundColor(DSKitAsset.bluePurpleLine.swiftUIColor) - .frame(width: CGFloat(onboardingViewModel.state.onboardingState.rawValue) / CGFloat(5) * 334, height: 4) + .frame(width: CGFloat(viewModel.state.onboardingState.rawValue) / CGFloat(5) * 334, height: 4) .cornerRadius(10.0) - .animation(Animation.spring(duration: 0.5), value: onboardingViewModel.state.onboardingState) + .animation(Animation.spring(duration: 0.5), value: viewModel.state.onboardingState) } } } private func OnboardingTitleView() -> some View { VStack(alignment: .leading, spacing: 8) { - Text(onboardingViewModel.state.onboardingState.mainTitle) - .font(.title3_semibold_22) + Text(viewModel.state.onboardingState.mainTitle) + .font(DSKitFontFamily.Pretendard.semiBold.swiftUIFont(size: 22)) .lineSpacing(1.5) .foregroundStyle(DSKitAsset.whiteText.swiftUIColor) - Text(onboardingViewModel.state.onboardingState.subTitle) - .font(.detail1_regular_14) + Text(viewModel.state.onboardingState.subTitle) + .font(DSKitFontFamily.Pretendard.regular.swiftUIFont(size: 14)) .lineSpacing(1.5) .foregroundStyle(DSKitAsset.gray2.swiftUIColor) } @@ -155,11 +97,11 @@ extension OnboardingContentView { private func SurveyContainerView() -> some View { VStack { - switch onboardingViewModel.state.onboardingState { + switch viewModel.state.onboardingState { case .timeSurveySelect, .problemSurveySelect, .challangePeriodSelect: - SurveyView(viewModel: onboardingViewModel) + SurveyView(viewModel: viewModel) case .goalTimeSelect: - AppGoalTimeView(viewModel: onboardingViewModel) + AppGoalTimeView(viewModel: viewModel) default: EmptyView() } diff --git a/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Views/StoryContentView.swift b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Views/StoryContentView.swift index 51231f99..25e23241 100644 --- a/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Views/StoryContentView.swift +++ b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Views/StoryContentView.swift @@ -22,7 +22,7 @@ struct StoryContentView: View { Spacer() .frame(height: 40) Text("아무데나 눌러서 이동") - .font(.text5_medium_16) + .font(DSKitFontFamily.Pretendard.medium.swiftUIFont(size: 16)) .foregroundColor(DSKitAsset.gray1.swiftUIColor) } diff --git a/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Views/SurveyButton.swift b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Views/SurveyButton.swift index 5d95c8b0..d1a844cd 100644 --- a/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Views/SurveyButton.swift +++ b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Views/SurveyButton.swift @@ -21,7 +21,7 @@ struct SurveyButton: View { // viewModel.onIsCompleted() } label: { Text(viewModel.state.surveyButtonItems[viewModel.state.surveyState][numberOfRow].buttonTitle) - .font(.text4_semibold_16) + .font(DSKitFontFamily.Pretendard.semiBold.swiftUIFont(size: 16)) .frame(minWidth: 100, maxWidth: .infinity, minHeight: 44, maxHeight: 44, alignment: .center) } .frame(maxWidth: .infinity)