-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
00449d1
commit 77e793b
Showing
3 changed files
with
372 additions
and
0 deletions.
There are no files selected for viewing
60 changes: 60 additions & 0 deletions
60
HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingState.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} | ||
} | ||
|
61 changes: 61 additions & 0 deletions
61
HMH_Tuist_iOS/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingUseCase.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Void, Error> | ||
} | ||
|
||
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<Void, Error> { | ||
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() | ||
} | ||
} | ||
|
251 changes: 251 additions & 0 deletions
251
...S/Projects/Features/OnboardingFeature/Sources/Refactor/OnboardingViewModel_Refactor.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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..<currentSurveyItems.count { | ||
state.surveyButtonItems[state.onboardingState.rawValue][i].isSelected = (i == index) | ||
} | ||
// 다음 버튼 활성화 | ||
state.isNextAvailable = true | ||
|
||
case .problemSurveySelect: | ||
// 다중 선택 상태: 최대 두 개의 선택만 허용 | ||
let selectedCount = currentSurveyItems.filter { $0.isSelected }.count | ||
|
||
if currentSurveyItems[index].isSelected { | ||
// 이미 선택된 경우 해제 | ||
state.surveyButtonItems[state.onboardingState.rawValue][index].isSelected = false | ||
} else if selectedCount < 2 { | ||
// 선택 가능하면 활성화 | ||
state.surveyButtonItems[state.onboardingState.rawValue][index].isSelected = true | ||
} | ||
|
||
// 다음 버튼 활성화 여부 결정 | ||
state.isNextAvailable = state.surveyButtonItems[state.onboardingState.rawValue].contains { $0.isSelected } | ||
|
||
default: | ||
break | ||
} | ||
} | ||
|
||
private func initializeSurveyButtonItems() -> [[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..<self.state.surveyButtonItems[state.rawValue].count { | ||
self.state.surveyButtonItems[state.rawValue][i].isSelected = false | ||
} | ||
} | ||
|
||
|
||
private func handleNextButtonTap() { | ||
switch state.onboardingState { | ||
case .timeSurveySelect: | ||
saveTimeSurvey() | ||
case .problemSurveySelect: | ||
saveProblemSurvey() | ||
case .challangePeriodSelect: | ||
savePeriod() | ||
case .goalTimeSelect: | ||
saveGoalTime() | ||
case .permissionSelect: | ||
savePermission() | ||
} | ||
} | ||
|
||
private func saveTimeSurvey() { | ||
for index in 0..<4{ | ||
if state.surveyButtonItems[state.onboardingState.rawValue][index].isSelected { | ||
self.averageUseTime = state.surveyButtonItems[state.onboardingState.rawValue][index].buttonTitle | ||
} | ||
} | ||
addOnboardingState() | ||
offIsCompleted() | ||
} | ||
|
||
private func saveProblemSurvey() { | ||
for index in 0..<4{ | ||
if state.surveyButtonItems[state.onboardingState.rawValue][index].isSelected { | ||
self.problems.append(state.surveyButtonItems[state.onboardingState.rawValue][index].buttonTitle) | ||
} | ||
} | ||
addOnboardingState() | ||
offIsCompleted() | ||
} | ||
|
||
private func savePeriod() { | ||
for index in 0..<4{ | ||
if state.surveyButtonItems[state.onboardingState.rawValue] [index].isSelected { | ||
self.period = removeLastCharacterAndConvertToInt(from: state.surveyButtonItems[state.onboardingState.rawValue] [index].buttonTitle) | ||
} | ||
} | ||
addOnboardingState() | ||
} | ||
|
||
private func saveGoalTime() { | ||
|
||
} | ||
|
||
private func savePermission() { | ||
// screenViewModel.requestAuthorization() | ||
// if screenViewModel.authorizationCenter.authorizationStatus == .approved { | ||
// onboardingState += 1 | ||
// } | ||
} | ||
|
||
private func saveApp() { | ||
// screenViewModel.requestAuthorization() | ||
// if screenViewModel.authorizationCenter.authorizationStatus == .approved { | ||
// onboardingState += 1 | ||
// } | ||
} | ||
|
||
private func addOnboardingState() { | ||
state.onboardingState.rawValue += 1 | ||
} | ||
|
||
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 | ||
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) | ||
} | ||
|
||
|
||
} | ||
|