|
7 | 7 |
|
8 | 8 | import Combine |
9 | 9 | import Foundation |
10 | | - |
11 | | -public enum OnboardingAction { |
12 | | - case checkNameFormat(name: String) |
13 | | - case genderSelected(isSelected: GenderType) |
14 | | - case checkBirthFormat(birth: String) |
15 | | - case bornTimeSelected(bornTime: BornType) |
16 | | - case nextButtonTap |
17 | | - case completeButtonTap |
18 | | -} |
19 | | - |
20 | | -public protocol OnboardingOutputProtocol { |
21 | | - var showNameError: AnyPublisher<Bool, Never> { get } |
22 | | - var showBirthError: AnyPublisher<Bool, Never> { get } |
23 | | - var isNextButtonEnabled: AnyPublisher<Bool, Never> { get } |
24 | | -} |
25 | | - |
26 | | -public protocol OnboardingViewModelProtocol: OnboardingOutputProtocol { |
27 | | - var inputStream: PassthroughSubject<OnboardingAction, Never> { get } |
28 | | -} |
29 | | - |
30 | | -public class OnboardingViewModel: OnboardingViewModelProtocol { |
31 | | - var stor: Set<AnyCancellable> = [] |
32 | | - |
33 | | - @Published private var _isNameValid: Bool = false |
34 | | - @Published private var _isBirthDateValid: Bool = false |
35 | | - @Published private var _isBornTimeValied: Bool = false |
36 | | - |
37 | | - public var inputStream: PassthroughSubject<OnboardingAction, Never> = .init() |
38 | | - |
39 | | - public var isNextButtonEnabled: AnyPublisher<Bool, Never> { |
40 | | - Publishers.CombineLatest3($_isNameValid, $_isBirthDateValid, $_isBornTimeValied).map { |
41 | | - (nameValid, birthBalid, bornTimeValid) in |
42 | | - return nameValid && birthBalid && bornTimeValid |
| 10 | +import Lib |
| 11 | + |
| 12 | +public class OnboardingViewModel { |
| 13 | + |
| 14 | + enum Input { |
| 15 | + case checkNameFormat(name: String) |
| 16 | + case genderSelected(isSelected: GenderType) |
| 17 | + case checkBirthFormat(birth: String) |
| 18 | + case bornTimeSelected(bornTime: BornType) |
| 19 | + case nextButtonTap |
| 20 | + case completeButtonTap |
| 21 | + case timePickerTap |
43 | 22 | } |
44 | | - .eraseToAnyPublisher() |
45 | | - } |
46 | | - |
47 | | - public var showNameError: AnyPublisher<Bool, Never> { |
48 | | - $_isNameValid |
49 | | - .eraseToAnyPublisher() |
50 | | - } |
51 | | - |
52 | | - public var showBirthError: AnyPublisher<Bool, Never> { |
53 | | - $_isBirthDateValid |
54 | | - .eraseToAnyPublisher() |
55 | | - } |
56 | | - |
57 | | - private var state: State = .init() |
58 | | - |
59 | | - public init() { |
60 | | - inputStream |
61 | | - .sink { [weak self] action in |
62 | | - guard let self = self else { return } |
63 | | - switch action { |
64 | | - case .checkNameFormat(let name): |
65 | | - self._isNameValid = checkNameFormat(name: name) |
66 | | - if self._isNameValid { self.state.name = name } |
67 | | - case .genderSelected(let isSelected): |
68 | | - self.state.gender = isSelected |
69 | | - case .checkBirthFormat(let birth): |
70 | | - self._isBirthDateValid = checkBirthFormat(birth: birth) |
71 | | - if self._isBirthDateValid { self.state.birthDate = birth } |
72 | | - case .bornTimeSelected(let bornTime): |
73 | | - switch bornTime { |
74 | | - case .dontKnow(let isSelected): |
75 | | - self._isBornTimeValied = (self.state.bornTime != nil || !isSelected) |
76 | | - case .time(let time): |
77 | | - self._isBornTimeValied = true |
78 | | - self.state.bornTime = bornTime |
79 | | - } |
| 23 | + |
| 24 | + struct Output { |
| 25 | + let showNameError : PassthroughSubject<Bool, Never> = .init() |
| 26 | + let showBirthError : PassthroughSubject<Bool, Never> = .init() |
| 27 | + let isNextButtonEnabled: PassthroughSubject<Bool, Never> = .init() |
| 28 | + let navigate : PassthroughSubject<OnboardingRoute, Never> = .init() |
| 29 | + } |
| 30 | + |
| 31 | + let output : Output = Output() |
| 32 | + |
| 33 | + private var _isNameValid: Bool = false |
| 34 | + private var _isBirthDateValid: Bool = false |
| 35 | + private var _isBornTimeValied: Bool = false |
| 36 | + |
| 37 | + private var state: State = .init() |
| 38 | + |
| 39 | + func send(input : Input) { |
| 40 | + switch input { |
| 41 | + case .checkNameFormat(name: let name): |
| 42 | + self._isNameValid = checkNameFormat(name: name) |
| 43 | + if self._isNameValid { self.state.name = name } |
| 44 | + self.output.showNameError.send(self._isNameValid) |
| 45 | + self.output.isNextButtonEnabled.send(_isNameValid && _isBirthDateValid && _isBornTimeValied) |
| 46 | + case .genderSelected(isSelected: let isSelected): |
| 47 | + self.state.gender = isSelected |
| 48 | + case .checkBirthFormat(birth: let birth): |
| 49 | + self._isBirthDateValid = checkBirthFormat(birth: birth) |
| 50 | + if self._isBirthDateValid { self.state.birthDate = birth } |
| 51 | + self.output.showBirthError.send(self._isBirthDateValid) |
| 52 | + self.output.isNextButtonEnabled.send(_isNameValid && _isBirthDateValid && _isBornTimeValied) |
| 53 | + case .bornTimeSelected(bornTime: let bornTime): |
| 54 | + switch bornTime { |
| 55 | + case .dontKnow(let isSelected): |
| 56 | + self._isBornTimeValied = (self.state.bornTime != nil || !isSelected) |
| 57 | + case .time(let time): |
| 58 | + self._isBornTimeValied = true |
| 59 | + self.state.bornTime = time |
| 60 | + } |
| 61 | + self.output.isNextButtonEnabled.send(_isNameValid && _isBirthDateValid && _isBornTimeValied) |
80 | 62 | case .nextButtonTap: |
81 | | - // TODO: Modal present |
82 | | - break |
| 63 | + self.output.navigate.send(.agreement) |
83 | 64 | case .completeButtonTap: |
84 | | - // TODO: API 연결 부분 |
85 | | - break |
| 65 | + break |
| 66 | + case .timePickerTap : |
| 67 | + self.output.navigate.send(.timePicker) |
86 | 68 | } |
87 | | - } |
88 | | - .store(in: &stor) |
89 | | - } |
| 69 | + } |
| 70 | + |
| 71 | + public init() { } |
90 | 72 | } |
91 | 73 |
|
92 | 74 | extension OnboardingViewModel { |
93 | 75 | struct State { |
94 | 76 | var name: String? |
95 | 77 | var gender: GenderType? |
96 | 78 | var birthDate: String? |
97 | | - var bornTime: BornType? |
| 79 | + var bornTime: String? |
98 | 80 | } |
99 | 81 | } |
100 | 82 |
|
|
0 commit comments