From 77e793befd4bd945279d25368450de39644b2e08 Mon Sep 17 00:00:00 2001 From: kim-seonwoo Date: Sun, 24 Nov 2024 20:00:08 +0900 Subject: [PATCH] =?UTF-8?q?[Feat/#114]=20=EC=98=A8=EB=B3=B4=EB=94=A9=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=A6=AC=ED=8E=99=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Refactor/OnboardingState.swift | 60 +++++ .../Sources/Refactor/OnboardingUseCase.swift | 61 +++++ .../OnboardingViewModel_Refactor.swift | 251 ++++++++++++++++++ 3 files changed, 372 insertions(+) create mode 100644 HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingState.swift create mode 100644 HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingUseCase.swift create mode 100644 HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingViewModel_Refactor.swift diff --git a/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingState.swift b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingState.swift new file mode 100644 index 00000000..047a985c --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingState.swift @@ -0,0 +1,60 @@ +// +// OnboardingState.swift +// OnboardingFeature +// +// Created by Seonwoo Kim on 11/23/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import Foundation +import DSKit + +enum OnboardingState: Int { + case timeSurveySelect = 0 + case problemSurveySelect + case challangePeriodSelect + case goalTimeSelect + case permissionSelect +} + +extension OnboardingState { + var mainTitle: String { + switch self { + case .timeSurveySelect: + return StringLiteral.OnboardigMain.timeSurveySelect + case .problemSurveySelect: + return StringLiteral.OnboardigMain.problemSurveySelect + case .challangePeriodSelect: + return StringLiteral.OnboardigMain.periodSelect + case .permissionSelect: + return StringLiteral.OnboardigMain.permissionSelect + case .goalTimeSelect: + return StringLiteral.OnboardigMain.appGoalTimeSelect + } + } + + var subTitle: String { + switch self { + case .timeSurveySelect: + return "" + case .problemSurveySelect: + return StringLiteral.OnboardigSub.problemSurveySelect + case .challangePeriodSelect: + return StringLiteral.OnboardigSub.periodSelect + case .permissionSelect: + return StringLiteral.OnboardigSub.permissionSelect + case .goalTimeSelect: + return StringLiteral.OnboardigSub.appGoalTimeSelect + } + } + + var nextButtonTitle: String { + switch self { + case .timeSurveySelect, .problemSurveySelect, .challangePeriodSelect, .goalTimeSelect: + return StringLiteral.OnboardingButton.next + case .permissionSelect: + return StringLiteral.OnboardingButton.permission + } + } +} + diff --git a/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingUseCase.swift b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingUseCase.swift new file mode 100644 index 00000000..2cfa0edc --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingUseCase.swift @@ -0,0 +1,61 @@ +// +// OnboardingUseCase.swift +// OnboardingFeatureInterface +// +// Created by Seonwoo Kim on 11/18/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import Foundation +import Combine + +import Domain +import Core + +public protocol OnboardingUseCaseType { + func postSignUpData( + socialPlatform: String, + userName: String, + averageUseTime: String, + problems: [String], + period: Int + ) -> AnyPublisher +} + +public final class OnboardingUseCase: OnboardingUseCaseType { + + private let repository: AuthRepositoryType + + public init(repository: AuthRepositoryType) { + self.repository = repository + } + + public func postSignUpData( + socialPlatform: String, + userName: String, + averageUseTime: String, + problems: [String], + period: Int + ) -> AnyPublisher { + let challengeInfo = ChallengeInfo(period: period, goalTime: 0, apps: []) + + return repository.signUp( + socialPlatform: socialPlatform, + name: userName, + averageUseTime: averageUseTime, + problem: problems, + challengeInfo: challengeInfo + ) + .map { auth -> Void in +// UserManager.shared.accessToken = auth.accessToken +// UserManager.shared.refreshToken = auth.refreshToken + print("Sign-up successful with user: \(auth)") + } + .mapError { error -> Error in + print("Sign-up failed with error: \(error)") + return error + } + .eraseToAnyPublisher() + } +} + 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 new file mode 100644 index 00000000..b3767c3a --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingViewModel_Refactor.swift @@ -0,0 +1,251 @@ +// +// 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_Refactor : ObservableObject { + + private let useCase: OnboardingUseCaseType + private var cancelBag = CancelBag() + + @Published private(set) var state = State(onboardingState: .timeSurveySelect, surveyButtonItems: [[]], isNextAvailable: false) + var userName: String + var averageUseTime: String + var problems: [String] + var period: Int + + public init(useCase: OnboardingUseCaseType) { + self.useCase = useCase + self.state = State( + onboardingState: .timeSurveySelect, + surveyButtonItems: initializeSurveyButtonItems(), + isNextAvailable: false + ) + self.userName = "" + self.averageUseTime = "" + self.problems = [] + self.period = 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 + } + + 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] + + // index 유효성 검증 + guard index >= 0 && index < currentSurveyItems.count else { return } + + // 상태에 따라 다른 선택 로직 적용 + switch state.onboardingState { + case .timeSurveySelect, .challangePeriodSelect, .goalTimeSelect: + // 단일 선택 상태 + for i in 0.. [[SurveyButtonInfo]] { + return [ + [ + SurveyButtonInfo(buttonTitle: StringLiteral.TimeSurveySelect.firstSelect, isSelected: false), + SurveyButtonInfo(buttonTitle: StringLiteral.TimeSurveySelect.secondSelect, isSelected: false), + SurveyButtonInfo(buttonTitle: StringLiteral.TimeSurveySelect.thirdSelect, isSelected: false), + SurveyButtonInfo(buttonTitle: StringLiteral.TimeSurveySelect.fourthSelect, isSelected: false), + ], + [ + SurveyButtonInfo(buttonTitle: StringLiteral.ProblemSurveySelect.firstSelect, isSelected: false), + SurveyButtonInfo(buttonTitle: StringLiteral.ProblemSurveySelect.secondSelect, isSelected: false), + SurveyButtonInfo(buttonTitle: StringLiteral.ProblemSurveySelect.thirdSelect, isSelected: false), + SurveyButtonInfo(buttonTitle: StringLiteral.ProblemSurveySelect.fourthSelect, isSelected: false), + ], + [ + SurveyButtonInfo(buttonTitle: StringLiteral.PeriodSelect.firstSelect, isSelected: false), + SurveyButtonInfo(buttonTitle: StringLiteral.PeriodSelect.secondSelect, isSelected: false), + SurveyButtonInfo(buttonTitle: StringLiteral.PeriodSelect.thirdSelect, isSelected: false), + SurveyButtonInfo(buttonTitle: StringLiteral.PeriodSelect.fourthSelect, isSelected: false), + ] + ] + } + + private func resetSelections(for state: OnboardingState) { + guard state.rawValue < self.state.surveyButtonItems.count else { return } + for i in 0.. 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 + offIsCompleted() + case .appSelect: + guard let previousState = OnboardingState(rawValue: state.onboardingState.rawValue - 1) else { return } + state.onboardingState = previousState + offIsCompleted() + default: + guard let previousState = OnboardingState(rawValue: state.onboardingState.rawValue - 1) else { return } + state.onboardingState = previousState + onIsCompleted() + } + } + + + private func offIsCompleted() { + state.isNextAvailable = false + } + + private func onIsCompleted() { + state.isNextAvailable = true + } + + private func completOnboarding() { + useCase.postSignUpData(socialPlatform: <#T##String#>, userName: <#T##String#>, averageUseTime: <#T##String#>, problems: <#T##[String]#>, period: <#T##Int#>) + .sink(receiveCompletion: { _ in }) { + } + .store(in: cancelBag) + } + + +} +