From 0c78cfd97a603ea9a33b75e82c397dd455c4a195 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Thu, 12 Sep 2024 16:06:40 +0900 Subject: [PATCH 1/5] =?UTF-8?q?[IDLE-000]=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=AC=EC=84=A4=EC=A0=95=20API=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/DataSource/API/AuthAPI.swift | 40 +++++--- .../Login/CenterSetNewPasswordViewModel.swift | 92 +++++++++---------- 2 files changed, 68 insertions(+), 64 deletions(-) diff --git a/project/Projects/Data/DataSource/API/AuthAPI.swift b/project/Projects/Data/DataSource/API/AuthAPI.swift index 1ada1c42..c7b16bc7 100644 --- a/project/Projects/Data/DataSource/API/AuthAPI.swift +++ b/project/Projects/Data/DataSource/API/AuthAPI.swift @@ -27,6 +27,8 @@ public enum AuthAPI { case deregisterCenterAccount(reason: String, password: String) case signoutCenterAccount + case makeNewPassword(phoneNumber: String, newPassword: String) + // Worker case registerWorkerAccount(data: Data) case workerLogin(phoneNumber: String, verificationNumber: String) @@ -69,6 +71,10 @@ extension AuthAPI: BaseAPI { return .post + case .makeNewPassword: + return .patch + + case .registerWorkerAccount: return .post case .workerLogin: @@ -83,17 +89,17 @@ extension AuthAPI: BaseAPI { public var path: String { switch self { case .startPhoneNumberAuth: - "common/send" + "/common/send" case .checkAuthNumber: - "common/confirm" + "/common/confirm" case .reissueToken: - "common/refresh" + "/common/refresh" case .authenticateBusinessNumber(let businessNumber): - "center/authentication/\(businessNumber)" + "/center/authentication/\(businessNumber)" case .checkIdDuplication(id: let id): - "center/validation/\(id)" + "/center/validation/\(id)" case .centerJoinStatus: "/center/join/status" @@ -102,23 +108,26 @@ extension AuthAPI: BaseAPI { case .registerCenterAccount: - "center/join" + "/center/join" case .centerLogin: - "center/login" + "/center/login" case .signoutCenterAccount: - "center/logout" + "/center/logout" case .deregisterCenterAccount: - "center/withdraw" + "/center/withdraw" + + case .makeNewPassword: + "/center/password/new" case .registerWorkerAccount: - "carer/join" + "/carer/join" case .workerLogin: - "carer/login" + "/carer/login" case .signoutWorkerAccount: - "carer/logout" + "/carer/logout" case .deregisterWorkerAccount: - "carer/withdraw" + "/carer/withdraw" } } @@ -136,6 +145,9 @@ extension AuthAPI: BaseAPI { case .deregisterCenterAccount(let reason, let password): params["reason"] = reason params["password"] = password + case .makeNewPassword(let phoneNumber, let newPassword): + params["phoneNumber"] = phoneNumber + params["newPassword"] = newPassword case .reissueToken(let refreshToken): params["refreshToken"] = refreshToken case .workerLogin(let phoneNumber, let verificationNumber): @@ -172,6 +184,8 @@ extension AuthAPI: BaseAPI { return .requestParameters(parameters: bodyParameters ?? [:], encoding: parameterEncoding) case .deregisterCenterAccount: return .requestParameters(parameters: bodyParameters ?? [:], encoding: parameterEncoding) + case .makeNewPassword: + return .requestParameters(parameters: bodyParameters ?? [:], encoding: parameterEncoding) case .reissueToken: return .requestParameters(parameters: bodyParameters ?? [:], encoding: parameterEncoding) case .registerWorkerAccount(let data): diff --git a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterSetNewPasswordViewModel.swift b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterSetNewPasswordViewModel.swift index 60213e6c..81a67f0c 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterSetNewPasswordViewModel.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterSetNewPasswordViewModel.swift @@ -27,65 +27,55 @@ public class CenterSetNewPasswordViewModel: BaseViewModel, ViewModelType { public init( authUseCase: AuthUseCase, inputValidationUseCase: AuthInputValidationUseCase) { - self.authUseCase = authUseCase - self.inputValidationUseCase = inputValidationUseCase + self.authUseCase = authUseCase + self.inputValidationUseCase = inputValidationUseCase super.init() - setObservable() - } - - deinit { - printIfDebug("deinit \(Self.self)") - } - - func setObservable() { - - // ๋น„๋ฐ€๋ฒˆํ˜ธ - AuthInOutStreamManager.passwordInOut( - input: input, - output: output, - useCase: inputValidationUseCase) { [weak self] validPassword in - // ๐Ÿš€ ์ƒํƒœ์ถ”์  ๐Ÿš€ - self?.validPassword = validPassword - } - - // ํœด๋Œ€์ „ํ™” ์ธ์ฆ - AuthInOutStreamManager.validatePhoneNumberInOut( + // ๋น„๋ฐ€๋ฒˆํ˜ธ + AuthInOutStreamManager.passwordInOut( + input: input, + output: output, + useCase: inputValidationUseCase) { [weak self] validPassword in + // ๐Ÿš€ ์ƒํƒœ์ถ”์  ๐Ÿš€ + self?.validPassword = validPassword + } + + // ํœด๋Œ€์ „ํ™” ์ธ์ฆ + AuthInOutStreamManager.validatePhoneNumberInOut( input: input, output: output, useCase: inputValidationUseCase, disposeBag: disposeBag - ) { _ in } - - changePasswordInOut() - } - - private func changePasswordInOut() { - - let changePasswordResult = input.changePasswordButtonClicked - .flatMap { [weak self] _ in - - printIfDebug("๋ณ€๊ฒฝ ์š”์ฒญ ๋น„๋ฐ€๋ฒˆํ˜ธ \(self?.validPassword ?? "")") - - // TODO: ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ API ์—ฐ๋™ - // ์ด๋ฒคํŠธ ์ „์†ก - return Single.just(Result.success(())) - } - .share() - - output.changePasswordValidation = changePasswordResult - .map { result in - switch result { - case .success: - printIfDebug("๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ์„ฑ๊ณต") - return true - case .failure(let error): - printIfDebug("๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ์‹คํŒจ") - return false + ) { _ in } + + let changePasswordResult = input.changePasswordButtonClicked + .flatMap { [weak self] _ in + + printIfDebug("๋ณ€๊ฒฝ ์š”์ฒญ ๋น„๋ฐ€๋ฒˆํ˜ธ \(self?.validPassword ?? "")") + + // TODO: ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ API ์—ฐ๋™ + // ์ด๋ฒคํŠธ ์ „์†ก + return Single.just(Result.success(())) } - } - .asDriver(onErrorJustReturn: false) + .share() + + output.changePasswordValidation = changePasswordResult + .map { result in + switch result { + case .success: + printIfDebug("๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ์„ฑ๊ณต") + return true + case .failure(let error): + printIfDebug("๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ์‹คํŒจ") + return false + } + } + .asDriver(onErrorJustReturn: false) + } + + deinit { + printIfDebug("deinit \(Self.self)") } } From 868c05a7b0c16fcec759fb871fca5fc63cf84754 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Thu, 12 Sep 2024 16:11:08 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[IDLE-000]=20UseCase=20/=20Repository?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Auth/DefaultAuthRepository.swift | 6 ++++ .../Auth/DefaultAuthUseCase.swift | 4 +++ .../Auth/AuthRepository.swift | 5 ++-- .../UseCaseInterface/Auth/AuthUseCase.swift | 30 ++++++++----------- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/project/Projects/Data/ConcreteRepository/Auth/DefaultAuthRepository.swift b/project/Projects/Data/ConcreteRepository/Auth/DefaultAuthRepository.swift index 1ffb6834..06517424 100644 --- a/project/Projects/Data/ConcreteRepository/Auth/DefaultAuthRepository.swift +++ b/project/Projects/Data/ConcreteRepository/Auth/DefaultAuthRepository.swift @@ -80,6 +80,12 @@ public extension DefaultAuthRepository { .request(api: .requestCenterJoin, with: .withToken) .mapToVoid() } + + func setNewPassword(phoneNumber: String, password: String) -> Single { + networkService + .request(api: .makeNewPassword(phoneNumber: phoneNumber, newPassword: password), with: .withToken) + .mapToVoid() + } } // MARK: Worker auth diff --git a/project/Projects/Domain/ConcreteUseCase/Auth/DefaultAuthUseCase.swift b/project/Projects/Domain/ConcreteUseCase/Auth/DefaultAuthUseCase.swift index c09d1710..d3a8f94f 100644 --- a/project/Projects/Domain/ConcreteUseCase/Auth/DefaultAuthUseCase.swift +++ b/project/Projects/Domain/ConcreteUseCase/Auth/DefaultAuthUseCase.swift @@ -82,4 +82,8 @@ public class DefaultAuthUseCase: AuthUseCase { public func checkCenterJoinStatus() -> Single> { convert(task: authRepository.getCenterJoinStatus()) } + + public func setNewPassword(phoneNumber: String, password: String) -> Single> { + convert(task: authRepository.setNewPassword(phoneNumber: phoneNumber, password: password)) + } } diff --git a/project/Projects/Domain/RepositoryInterface/Auth/AuthRepository.swift b/project/Projects/Domain/RepositoryInterface/Auth/AuthRepository.swift index f3297653..cf433a21 100644 --- a/project/Projects/Domain/RepositoryInterface/Auth/AuthRepository.swift +++ b/project/Projects/Domain/RepositoryInterface/Auth/AuthRepository.swift @@ -15,8 +15,9 @@ public protocol AuthRepository: RepositoryBase { func requestCenterLogin(id: String, password: String) -> Single func signoutCenterAccount() -> Single func deregisterCenterAccount(reasons: [DeregisterReasonVO], password: String) -> Single - func getCenterJoinStatus() -> RxSwift.Single - func requestCenterJoin() -> RxSwift.Single + func getCenterJoinStatus() -> Single + func requestCenterJoin() -> Single + func setNewPassword(phoneNumber: String, password: String) -> Single // MARK: Worker diff --git a/project/Projects/Domain/UseCaseInterface/Auth/AuthUseCase.swift b/project/Projects/Domain/UseCaseInterface/Auth/AuthUseCase.swift index e9bb6ecb..78e31333 100644 --- a/project/Projects/Domain/UseCaseInterface/Auth/AuthUseCase.swift +++ b/project/Projects/Domain/UseCaseInterface/Auth/AuthUseCase.swift @@ -9,20 +9,9 @@ import Foundation import RxSwift import Entity -/// ์š”๊ตฌ์‚ฌํ•ญ -/// - #1. ์„ผํ„ฐ ํšŒ์›๊ฐ€์ž… ์‹คํ–‰ -/// - #2. ์„ผํ„ฐ ๋กœ๊ทธ์ธ ์‹คํ–‰ -/// - #3. ์ƒŒํ„ฐ ํšŒ์› ํƒˆํ‡ด -/// - #4. ์ƒŒํ„ฐ ํšŒ์› ๋กœ๊ทธ์•„์›ƒ -/// -/// - #5. ์š”์–‘๋ณดํ˜ธ์‚ฌ ํšŒ์›๊ฐ€์ž… ์‹คํ–‰ -/// - #6. ์š”์–‘๋ณดํ˜ธ์‚ฌ ๋กœ๊ทธ์ธ ์‹คํ–‰ -/// - #7. ์š”์–‘๋ณดํ˜ธ์‚ฌ ํšŒ์›ํƒˆํ‡ด ์‹คํ–‰ -/// - #8. ์š”์–‘๋ณดํ˜ธ์‚ฌ ๋กœ๊ทธ์•„์›ƒ - public protocol AuthUseCase: UseCaseBase { - // #1. + /// ์„ผํ„ฐ ํšŒ์›๊ฐ€์ž… ์‹คํ–‰ /// - parameters: /// - registerState: CenterRegisterState @@ -30,7 +19,7 @@ public protocol AuthUseCase: UseCaseBase { registerState: CenterRegisterState ) -> Single> - // #2. + /// ์„ผํ„ฐ ๋กœ๊ทธ์ธ ์‹คํ–‰ /// - parameters: /// - id: String @@ -40,18 +29,23 @@ public protocol AuthUseCase: UseCaseBase { password: String ) -> Single> - // #5 + /// ์„ผํ„ฐ ์ธ์ฆ์—ฌ๋ถ€ ํ™•์ธ + func checkCenterJoinStatus() -> Single> + + + /// ์„ผํ„ฐ ๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ • + func setNewPassword(phoneNumber: String, password: String) -> Single> + + /// ์š”์–‘ ๋ณดํ˜ธ์‚ฌ ํšŒ์›๊ฐ€์ž… ์‹คํ–‰ func registerWorkerAccount( registerState: WorkerRegisterState ) -> Single> - // #6 + + /// ์š”์–‘ ๋ณดํ˜ธ์‚ฌ ๋กœ๊ทธ์ธ ์‹คํ–‰ func loginWorkerAccount( phoneNumber: String, authNumber: String ) -> Single> - - /// ์„ผํ„ฐ ์ธ์ฆ์—ฌ๋ถ€ ํ™•์ธ - func checkCenterJoinStatus() -> Single> } From 63fa2246594cf348103b88d85c360cbe6d0d6715 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Thu, 12 Sep 2024 16:47:26 +0900 Subject: [PATCH 3/5] =?UTF-8?q?[IDLE-000]=20=EC=9A=94=EC=96=91=EB=B3=B4?= =?UTF-8?q?=ED=98=B8=EC=82=AC=20=EB=B2=88=ED=98=B8=EC=9D=B8=EC=A6=9D=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Worker/WorkerRegisterCoordinator.swift | 37 +++++++++++-------- .../ValidatePhoneNumberViewController.swift | 2 + .../Worker/WorkerRegisterViewController.swift | 19 ++++------ .../AuthInOutStreamManager+PhoneNumber.swift | 5 ++- .../Login/CenterSetNewPasswordViewModel.swift | 22 +++++++---- .../Register/CenterRegisterViewModel.swift | 4 ++ .../Register/WorkerRegisterViewModel.swift | 36 +++++++++--------- 7 files changed, 72 insertions(+), 53 deletions(-) diff --git a/project/Projects/Presentation/Feature/Auth/Sources/Coordinator/Worker/WorkerRegisterCoordinator.swift b/project/Projects/Presentation/Feature/Auth/Sources/Coordinator/Worker/WorkerRegisterCoordinator.swift index eacd0eeb..3ec1061d 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/Coordinator/Worker/WorkerRegisterCoordinator.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/Coordinator/Worker/WorkerRegisterCoordinator.swift @@ -38,24 +38,19 @@ public class WorkerRegisterCoordinator: ChildCoordinator { public weak var viewControllerRef: UIViewController? weak var pageViewController: UIPageViewController? + + let inputValidationUseCase: AuthInputValidationUseCase + let authUseCase: AuthUseCase + // MARK: Stage var stageViewControllers: [UIViewController] = [] private var currentStage: WorkerRegisterStage! public init(dependency: Dependency) { + self.inputValidationUseCase = dependency.inputValidationUseCase + self.authUseCase = dependency.authUseCase self.navigationController = dependency.navigationController - - let vm = WorkerRegisterViewModel( - inputValidationUseCase: dependency.inputValidationUseCase, - authUseCase: dependency.authUseCase - ) - - self.stageViewControllers = [ - ValidatePhoneNumberViewController(coordinator: self, viewModel: vm), - EntetPersonalInfoViewController(coordinator: self, viewModel: vm), - EnterAddressViewController(coordinator: self, viewModel: vm), - ] } deinit { @@ -70,18 +65,30 @@ public class WorkerRegisterCoordinator: ChildCoordinator { options: nil ) + let vm = WorkerRegisterViewModel( + inputValidationUseCase: inputValidationUseCase, + authUseCase: authUseCase + ) + + self.stageViewControllers = [ + ValidatePhoneNumberViewController(coordinator: self, viewModel: vm), + EntetPersonalInfoViewController(coordinator: self, viewModel: vm), + EnterAddressViewController(coordinator: self, viewModel: vm), + ] + self.pageViewController = pageViewController - let viewController = WorkerRegisterViewController( + let vc = WorkerRegisterViewController( pageCount: stageViewControllers.count, pageViewController: pageViewController ) + vc.bind(viewModel: vm) - viewController.coordinator = self + vc.coordinator = self - viewControllerRef = viewController + viewControllerRef = vc - navigationController.pushViewController(viewController, animated: true) + navigationController.pushViewController(vc, animated: true) excuteStage(.info, moveTo: .next) } diff --git a/project/Projects/Presentation/Feature/Auth/Sources/View/Common/Register/ValidatePhoneNumberViewController.swift b/project/Projects/Presentation/Feature/Auth/Sources/View/Common/Register/ValidatePhoneNumberViewController.swift index f88f75ef..7bdb3abf 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/View/Common/Register/ValidatePhoneNumberViewController.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/View/Common/Register/ValidatePhoneNumberViewController.swift @@ -207,6 +207,8 @@ where guard let viewModel = self.viewModel as? T else { return } + + // MARK: Input let input = viewModel.input diff --git a/project/Projects/Presentation/Feature/Auth/Sources/View/Worker/WorkerRegisterViewController.swift b/project/Projects/Presentation/Feature/Auth/Sources/View/Worker/WorkerRegisterViewController.swift index 62ce45ff..745c67c6 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/View/Worker/WorkerRegisterViewController.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/View/Worker/WorkerRegisterViewController.swift @@ -12,7 +12,7 @@ import RxSwift import PresentationCore import BaseFeature -class WorkerRegisterViewController: DisposableViewController { +class WorkerRegisterViewController: BaseViewController { var coordinator: WorkerRegisterCoordinator? @@ -21,10 +21,8 @@ class WorkerRegisterViewController: DisposableViewController { let pageCount: Int // View - let navigationBar: NavigationBarType1 = { - let bar = NavigationBarType1( - navigationTitle: "์š”์–‘๋ณดํ˜ธ์‚ฌ ํšŒ์›๊ฐ€์ž…" - ) + let navigationBar: IdleNavigationBar = { + let bar = IdleNavigationBar(titleText: "์š”์–‘๋ณดํ˜ธ์‚ฌ ํšŒ์›๊ฐ€์ž…") return bar }() @@ -37,8 +35,6 @@ class WorkerRegisterViewController: DisposableViewController { return view }() - private let disposeBag = DisposeBag() - init( pageCount: Int, pageViewController: UIPageViewController @@ -76,9 +72,9 @@ class WorkerRegisterViewController: DisposableViewController { NSLayoutConstraint.activate([ - navigationBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20), - navigationBar.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 12), - navigationBar.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -12), + navigationBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + navigationBar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + navigationBar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), statusBar.topAnchor.constraint(equalTo: navigationBar.bottomAnchor, constant: 7), statusBar.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), @@ -93,7 +89,7 @@ class WorkerRegisterViewController: DisposableViewController { func setObservable() { navigationBar - .eventPublisher + .backButton.rx.tap .subscribe { [weak self] _ in self?.coordinator?.prev() } @@ -109,7 +105,6 @@ class WorkerRegisterViewController: DisposableViewController { .disposed(by: disposeBag) } - func cleanUp() { coordinator?.stageViewControllers = [] diff --git a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/AuthInOutStreamManager/AuthInOutStreamManager+PhoneNumber.swift b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/AuthInOutStreamManager/AuthInOutStreamManager+PhoneNumber.swift index eb40ab57..666cc220 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/AuthInOutStreamManager/AuthInOutStreamManager+PhoneNumber.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/AuthInOutStreamManager/AuthInOutStreamManager+PhoneNumber.swift @@ -55,6 +55,7 @@ public extension AuthInOutStreamManager { #endif return useCase.requestPhoneNumberAuthentication(phoneNumber: formatted) } + .share() output .phoneNumberValidation = phoneNumberAuthRequestResult @@ -180,7 +181,9 @@ public extension AuthInOutStreamManager { } failureAlert - .subscribe(input.alert) + .subscribe(onNext: { [input] alertVO in + input.alert.onNext(alertVO) + }) .disposed(by: disposeBag) } } diff --git a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterSetNewPasswordViewModel.swift b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterSetNewPasswordViewModel.swift index 81a67f0c..6cd473b7 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterSetNewPasswordViewModel.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterSetNewPasswordViewModel.swift @@ -23,6 +23,7 @@ public class CenterSetNewPasswordViewModel: BaseViewModel, ViewModelType { // State private var validPassword: String? + private var authenticatedPhoneNumebr: String? public init( authUseCase: AuthUseCase, @@ -46,17 +47,24 @@ public class CenterSetNewPasswordViewModel: BaseViewModel, ViewModelType { input: input, output: output, useCase: inputValidationUseCase, - disposeBag: disposeBag - ) { _ in } + disposeBag: disposeBag) { [weak self] phoneNumber in + // ๐Ÿš€ ์ƒํƒœ์ถ”์  ๐Ÿš€ + self?.authenticatedPhoneNumebr = phoneNumber + } let changePasswordResult = input.changePasswordButtonClicked - .flatMap { [weak self] _ in + .compactMap({ [weak self] _ -> (String, String)? in + + guard let phoneNumber = self?.validPassword, let validPassword = self?.validPassword else { + return nil + } - printIfDebug("๋ณ€๊ฒฝ ์š”์ฒญ ๋น„๋ฐ€๋ฒˆํ˜ธ \(self?.validPassword ?? "")") + return (phoneNumber, validPassword) + }) + .flatMap { [authUseCase] (phoneNumber, validPassword) in - // TODO: ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ API ์—ฐ๋™ - // ์ด๋ฒคํŠธ ์ „์†ก - return Single.just(Result.success(())) + authUseCase + .setNewPassword(phoneNumber: phoneNumber, password: validPassword) } .share() diff --git a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Register/CenterRegisterViewModel.swift b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Register/CenterRegisterViewModel.swift index 2cd49294..a1b8b0ac 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Register/CenterRegisterViewModel.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Register/CenterRegisterViewModel.swift @@ -70,6 +70,10 @@ public class CenterRegisterViewModel: BaseViewModel, ViewModelType { // ๐Ÿš€ ์ƒํƒœ์ถ”์  ๐Ÿš€ self?.stateObject.password = validPassword } + + input.alert + .bind(to: self.alert) + .disposed(by: disposeBag) } deinit { diff --git a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Worker/Register/WorkerRegisterViewModel.swift b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Worker/Register/WorkerRegisterViewModel.swift index a13f16f8..f2fcac44 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Worker/Register/WorkerRegisterViewModel.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Worker/Register/WorkerRegisterViewModel.swift @@ -92,34 +92,22 @@ public class WorkerRegisterViewModel: BaseViewModel, ViewModelType { }) .disposed(by: disposeBag) - registerInOut() - } - - private func validateBirthYear(_ year: Int) -> Bool { - let currentYear: Int = Calendar.current.component(.year, from: Date()) - return (1900.. Bool { + let currentYear: Int = Calendar.current.component(.year, from: Date()) + return (1900.. Date: Thu, 12 Sep 2024 18:00:51 +0900 Subject: [PATCH 4/5] =?UTF-8?q?[IDLE-000]=20=EC=84=BC=ED=84=B0=EA=B0=80?= =?UTF-8?q?=EC=9E=85=EC=8B=9C=20=EC=95=84=EC=9D=B4=EB=94=94=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=EA=B2=80=EC=A6=9D=20=EB=B0=A9=EB=B2=95=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Auth/DefaultAuthRepository.swift | 2 +- .../CenterSetNewPasswordCoordinator.swift | 30 ++++++++++--- .../CenterSetNewPasswordController.swift | 4 +- .../ValidateNewPasswordViewController.swift | 37 +++------------ .../SetIdPasswordViewController.swift | 12 ++++- .../ValidatePhoneNumberViewController.swift | 20 +++------ .../Login/CenterSetNewPasswordViewModel.swift | 45 +++++++++++++------ .../Register/CenterRegisterViewModel.swift | 1 + .../RegisterCenterInfoVM.swift | 2 +- .../InitialScreen/InitialScreenVM.swift | 3 ++ ...PhoneNumberValidationForDeregisterVM.swift | 1 + 11 files changed, 90 insertions(+), 67 deletions(-) diff --git a/project/Projects/Data/ConcreteRepository/Auth/DefaultAuthRepository.swift b/project/Projects/Data/ConcreteRepository/Auth/DefaultAuthRepository.swift index 06517424..e0440f27 100644 --- a/project/Projects/Data/ConcreteRepository/Auth/DefaultAuthRepository.swift +++ b/project/Projects/Data/ConcreteRepository/Auth/DefaultAuthRepository.swift @@ -83,7 +83,7 @@ public extension DefaultAuthRepository { func setNewPassword(phoneNumber: String, password: String) -> Single { networkService - .request(api: .makeNewPassword(phoneNumber: phoneNumber, newPassword: password), with: .withToken) + .request(api: .makeNewPassword(phoneNumber: phoneNumber, newPassword: password), with: .plain) .mapToVoid() } } diff --git a/project/Projects/Presentation/Feature/Auth/Sources/Coordinator/Center/CenterSetNewPasswordCoordinator.swift b/project/Projects/Presentation/Feature/Auth/Sources/Coordinator/Center/CenterSetNewPasswordCoordinator.swift index 4eafa6b2..42385c06 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/Coordinator/Center/CenterSetNewPasswordCoordinator.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/Coordinator/Center/CenterSetNewPasswordCoordinator.swift @@ -8,6 +8,8 @@ import UIKit import PresentationCore import UseCaseInterface +import BaseFeature +import DSKit enum SetNewPasswordStage: Int { @@ -56,14 +58,16 @@ public class CenterSetNewPasswordCoordinator: ChildCoordinator { public func start() { let vm = CenterSetNewPasswordViewModel( + coordinator: self, authUseCase: authUseCase, inputValidationUseCase: inputValidationUseCase ) // stageViewControllerss์— ์ž๊ธฐ์ž์‹ ๊ณผ ViewModelํ• ๋‹น + self.stageViewControllers = [ ValidatePhoneNumberViewController(coordinator: self, viewModel: vm), - ValidateNewPasswordViewController(coordinator: self, viewModel: vm) + ValidateNewPasswordViewController(viewModel: vm) ] let pageViewController = UIPageViewController( @@ -74,21 +78,38 @@ public class CenterSetNewPasswordCoordinator: ChildCoordinator { self.pageViewController = pageViewController - let viewController = CenterSetNewPasswordController( + let vc = CenterSetNewPasswordController( pageViewController: pageViewController, pageCount: stageViewControllers.count ) - viewController.coordinator = self + vc.bind(viewModel: vm) + vc.coordinator = self - navigationController.pushViewController(viewController, animated: true) + navigationController.pushViewController(vc, animated: true) excuteStage(.phoneNumber, moveTo: .next) } public func coordinatorDidFinish() { stageViewControllers = [] + popViewController() parent?.removeChildCoordinator(self) } + + public func coordinatorDidFinishWithSnackBar(ro: IdleSnackBarRO) { + let belowIndex = navigationController.children.count-2 + + if belowIndex >= 0 { + let belowVC = navigationController.children[belowIndex] + + if let baseVC = belowVC as? BaseViewController { + + baseVC.viewModel?.addSnackBar(ro: ro) + } + } + + coordinatorDidFinish() + } } extension CenterSetNewPasswordCoordinator { @@ -114,7 +135,6 @@ extension CenterSetNewPasswordCoordinator { currentStage = stage switch stage { case .findPasswordFinished, .finish: - popViewController() coordinatorDidFinish() default: let vc = stageViewControllers[stage.rawValue-1] diff --git a/project/Projects/Presentation/Feature/Auth/Sources/View/Center/Login/CenterSetNewPasswordController.swift b/project/Projects/Presentation/Feature/Auth/Sources/View/Center/Login/CenterSetNewPasswordController.swift index c9451cf7..c4e768fd 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/View/Center/Login/CenterSetNewPasswordController.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/View/Center/Login/CenterSetNewPasswordController.swift @@ -12,7 +12,7 @@ import RxCocoa import PresentationCore import BaseFeature -class CenterSetNewPasswordController: DisposableViewController { +class CenterSetNewPasswordController: BaseViewController { // Init var pageViewController: UIPageViewController @@ -21,8 +21,6 @@ class CenterSetNewPasswordController: DisposableViewController { var coordinator: CenterSetNewPasswordCoordinator? - let disposeBag = DisposeBag() - public init(pageViewController: UIPageViewController, pageCount: Int) { self.pageViewController = pageViewController self.pageCount = pageCount diff --git a/project/Projects/Presentation/Feature/Auth/Sources/View/Center/Login/ValidateNewPasswordViewController.swift b/project/Projects/Presentation/Feature/Auth/Sources/View/Center/Login/ValidateNewPasswordViewController.swift index 723acd36..31b2957c 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/View/Center/Login/ValidateNewPasswordViewController.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/View/Center/Login/ValidateNewPasswordViewController.swift @@ -16,15 +16,12 @@ public protocol ChangePasswordSuccessInputable { var changePasswordButtonClicked: PublishRelay { get } } -public protocol ChangePasswordSuccessOutputable { - var changePasswordValidation: Driver? { get set } -} -class ValidateNewPasswordViewController: BaseViewController +class ValidateNewPasswordViewController: UIViewController where T.Input: SetPasswordInputable & ChangePasswordSuccessInputable, - T.Output: SetPasswordOutputable & ChangePasswordSuccessOutputable, T: BaseViewModel { + T.Output: SetPasswordOutputable { - var coordinator: Coordinator? + let viewModel: T // View private let processTitle: IdleLabel = { @@ -89,14 +86,12 @@ where T.Input: SetPasswordInputable & ChangePasswordSuccessInputable, return button }() - public init(coordinator: Coordinator, viewModel: T) { - - self.coordinator = coordinator - + let disposeBag = DisposeBag() + + public init(viewModel: T) { + self.viewModel = viewModel super.init(nibName: nil, bundle: nil) - super.bind(viewModel: viewModel) - setAppearance() setAutoLayout() initialUISettuing() @@ -174,8 +169,6 @@ where T.Input: SetPasswordInputable & ChangePasswordSuccessInputable, func setObservable() { - guard let viewModel = self.viewModel as? T else { return } - // MARK: Input let input = viewModel.input @@ -223,22 +216,6 @@ where T.Input: SetPasswordInputable & ChangePasswordSuccessInputable, } }) .disposed(by: disposeBag) - - output - .changePasswordValidation? - .drive (onNext: { [weak self] isSuccess in - - if isSuccess { - // ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ์„ฑ๊ณต - self?.coordinator?.next() - - } else { - // ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ์‹คํŒจ - self?.ctaButton.setEnabled(true) - } - }) - .disposed(by: disposeBag) - } private func onPasswordMatched() { diff --git a/project/Projects/Presentation/Feature/Auth/Sources/View/Center/Register/SetIdPasswordViewController.swift b/project/Projects/Presentation/Feature/Auth/Sources/View/Center/Register/SetIdPasswordViewController.swift index 418dcaab..9db1317e 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/View/Center/Register/SetIdPasswordViewController.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/View/Center/Register/SetIdPasswordViewController.swift @@ -288,7 +288,17 @@ where T.Input: SetIdInputable & SetPasswordInputable & CTAButtonEnableInputable, let idDuplicationValidation = output .idDuplicationValidation? .map { [weak self] isSuccess in - self?.idField.idleTextField.setEnabled(isSuccess) + + self?.idField.idleTextField.setEnabled(true) + + if !isSuccess { + self?.idField.idleTextField.textField.textString = "" + self?.showAlert(vo: .init( + title: "์‚ฌ์šฉ๋ถˆ๊ฐ€ํ•œ ์•„์ด๋””", + message: "๋‹ค๋ฅธ ์•„์ด๋””๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”.") + ) + } + return isSuccess } .asObservable() ?? .empty() diff --git a/project/Projects/Presentation/Feature/Auth/Sources/View/Common/Register/ValidatePhoneNumberViewController.swift b/project/Projects/Presentation/Feature/Auth/Sources/View/Common/Register/ValidatePhoneNumberViewController.swift index 7bdb3abf..cb73b575 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/View/Common/Register/ValidatePhoneNumberViewController.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/View/Common/Register/ValidatePhoneNumberViewController.swift @@ -32,16 +32,14 @@ public protocol AuthPhoneNumberOutputable { // ์š”์–‘๋ณดํ˜ธ์‚ฌ ๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ•œ ๊ฒฝ์šฐ(์š”์–‘๋ณดํ˜ธ์‚ฌ ํ•œ์ • ๋กœ์ง) var loginValidation: Driver? { get set } } -public extension AuthPhoneNumberOutputable { - var loginValidation: Driver? { get { nil } set { } } -} -class ValidatePhoneNumberViewController: BaseViewController +class ValidatePhoneNumberViewController: UIViewController where T.Input: AuthPhoneNumberInputable, - T.Output: AuthPhoneNumberOutputable, T: BaseViewModel { + T.Output: AuthPhoneNumberOutputable { var coordinator: Coordinator? + let viewModel: T // View private let processTitle: ResizableUILabel = { @@ -114,16 +112,17 @@ where return button }() + let disposeBag = DisposeBag() + public init( coordinator: Coordinator? = nil, viewModel: T ) { self.coordinator = coordinator + self.viewModel = viewModel super.init(nibName: nil, bundle: nil) - super.bind(viewModel: viewModel) - setAppearance() setAutoLayout() initialUISettuing() @@ -203,12 +202,7 @@ where ctaButton.setEnabled(false) } - private func setObservable() { - - guard let viewModel = self.viewModel as? T else { return } - - - + public func setObservable() { // MARK: Input let input = viewModel.input diff --git a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterSetNewPasswordViewModel.swift b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterSetNewPasswordViewModel.swift index 6cd473b7..5209bbf1 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterSetNewPasswordViewModel.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterSetNewPasswordViewModel.swift @@ -17,6 +17,7 @@ public class CenterSetNewPasswordViewModel: BaseViewModel, ViewModelType { // Init let authUseCase: AuthUseCase let inputValidationUseCase: AuthInputValidationUseCase + weak var coordinator: CenterSetNewPasswordCoordinator? public var input: Input = .init() public var output: Output = .init() @@ -26,8 +27,10 @@ public class CenterSetNewPasswordViewModel: BaseViewModel, ViewModelType { private var authenticatedPhoneNumebr: String? public init( + coordinator: CenterSetNewPasswordCoordinator, authUseCase: AuthUseCase, inputValidationUseCase: AuthInputValidationUseCase) { + self.coordinator = coordinator self.authUseCase = authUseCase self.inputValidationUseCase = inputValidationUseCase @@ -55,7 +58,7 @@ public class CenterSetNewPasswordViewModel: BaseViewModel, ViewModelType { let changePasswordResult = input.changePasswordButtonClicked .compactMap({ [weak self] _ -> (String, String)? in - guard let phoneNumber = self?.validPassword, let validPassword = self?.validPassword else { + guard let phoneNumber = self?.authenticatedPhoneNumebr, let validPassword = self?.validPassword else { return nil } @@ -67,19 +70,37 @@ public class CenterSetNewPasswordViewModel: BaseViewModel, ViewModelType { .setNewPassword(phoneNumber: phoneNumber, password: validPassword) } .share() - - output.changePasswordValidation = changePasswordResult - .map { result in + + changePasswordResult + .subscribe(onNext: { + [weak self] result in + + guard let self else { return } + switch result { case .success: - printIfDebug("๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ์„ฑ๊ณต") - return true + self.coordinator? + .coordinatorDidFinishWithSnackBar( + ro: .init( + titleText: "๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ์„ฑ๊ณต" + ) + ) case .failure(let error): - printIfDebug("๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ์‹คํŒจ") - return false + self.alert.onNext( + .init( + title: "๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ์‹คํŒจ", + message: error.message + ) + ) } - } - .asDriver(onErrorJustReturn: false) + }) + .disposed(by: disposeBag) + + input.alert + .subscribe(onNext: { [weak self] alertVO in + self?.alert.onNext(alertVO) + }) + .disposed(by: disposeBag) } deinit { @@ -118,8 +139,7 @@ public extension CenterSetNewPasswordViewModel { // Password public var passwordValidation: Driver? - // Change password - public var changePasswordValidation: Driver? + public var loginValidation: Driver? } } @@ -131,4 +151,3 @@ extension CenterSetNewPasswordViewModel.Input: SetPasswordInputable { } extension CenterSetNewPasswordViewModel.Output: SetPasswordOutputable { } extension CenterSetNewPasswordViewModel.Input: ChangePasswordSuccessInputable { } -extension CenterSetNewPasswordViewModel.Output: ChangePasswordSuccessOutputable { } diff --git a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Register/CenterRegisterViewModel.swift b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Register/CenterRegisterViewModel.swift index a1b8b0ac..1ec0e451 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Register/CenterRegisterViewModel.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Register/CenterRegisterViewModel.swift @@ -138,6 +138,7 @@ extension CenterRegisterViewModel { // Register success public var registerValidation: Driver? + public var loginValidation: Driver? } } diff --git a/project/Projects/Presentation/Feature/Center/Sources/ViewModel/RegisterCenterInfo/RegisterCenterInfoVM.swift b/project/Projects/Presentation/Feature/Center/Sources/ViewModel/RegisterCenterInfo/RegisterCenterInfoVM.swift index bd56d343..6a5db52c 100644 --- a/project/Projects/Presentation/Feature/Center/Sources/ViewModel/RegisterCenterInfo/RegisterCenterInfoVM.swift +++ b/project/Projects/Presentation/Feature/Center/Sources/ViewModel/RegisterCenterInfo/RegisterCenterInfoVM.swift @@ -122,7 +122,7 @@ public class RegisterCenterInfoVM: BaseViewModel, RegisterCenterInfoViewModelabl guard let self else { return } // ํ”„๋ฆฌ๋ทฐํ™”๋ฉด์œผ๋กœ ์ด๋™ - coordinator.showPreviewScreen(stateObject: stateObject) + self.coordinator?.showPreviewScreen(stateObject: stateObject) }) .disposed(by: disposeBag) diff --git a/project/Projects/Presentation/Feature/Root/Sources/Screen/Common/InitialScreen/InitialScreenVM.swift b/project/Projects/Presentation/Feature/Root/Sources/Screen/Common/InitialScreen/InitialScreenVM.swift index 432716b9..3daad6b3 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/Screen/Common/InitialScreen/InitialScreenVM.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Screen/Common/InitialScreen/InitialScreenVM.swift @@ -171,6 +171,9 @@ public class InitialScreenVM: BaseViewModel { case .approved: return info case .pending, .new: + + self.coordinator?.centerAuth() + return nil } } diff --git a/project/Projects/Presentation/Feature/Root/Sources/Screen/Worker/PhoneNumberValidationForDeregisterVM.swift b/project/Projects/Presentation/Feature/Root/Sources/Screen/Worker/PhoneNumberValidationForDeregisterVM.swift index 0895a291..f82d6e46 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/Screen/Worker/PhoneNumberValidationForDeregisterVM.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Screen/Worker/PhoneNumberValidationForDeregisterVM.swift @@ -41,6 +41,7 @@ class PhoneNumberValidationForDeregisterVM: BaseViewModel, PhoneNumberValidation var canSubmitAuthNumber: RxCocoa.Driver? var phoneNumberValidation: RxCocoa.Driver? var authNumberValidation: RxCocoa.Driver? + var loginValidation: RxCocoa.Driver? init( coordinator: PhoneNumberValidationForDeregisterCoordinator?, From a4119106e72fb186b9c6a4800ec4d7c6446dc559 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Thu, 12 Sep 2024 22:26:13 +0900 Subject: [PATCH 5/5] =?UTF-8?q?[IDLE-000]=20=EC=8A=A4=EB=82=B5=EB=B0=94=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ์ด๋ฏธ์ง€๋ทฐ๊ฐ€ ๋“ฑ์žฅ์‹œ ๋ ˆ์ด์•„์›ƒ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ ์šฉ๋˜์ง€ ์•Š๋Š” ๋ฒ„๊ทธ ๋ฐœ์ƒ, ๋”ฐ๋ผ์„œ ์˜คํ† ๋ ˆ์ด์•„์›ƒ ์ œ์•ฝ์„ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. --- .../DSKit/Sources/CommonUI/SnackBar/IdleSnackBar.swift | 4 ++++ .../View/ViewController/Base/BaseViewController.swift | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/project/Projects/Presentation/DSKit/Sources/CommonUI/SnackBar/IdleSnackBar.swift b/project/Projects/Presentation/DSKit/Sources/CommonUI/SnackBar/IdleSnackBar.swift index 169dc732..e56e81c3 100644 --- a/project/Projects/Presentation/DSKit/Sources/CommonUI/SnackBar/IdleSnackBar.swift +++ b/project/Projects/Presentation/DSKit/Sources/CommonUI/SnackBar/IdleSnackBar.swift @@ -70,6 +70,10 @@ public class IdleSnackBar: UIView { } NSLayoutConstraint.activate([ + + titleIcon.widthAnchor.constraint(equalToConstant: 24), + titleIcon.heightAnchor.constraint(equalToConstant: 24), + mainStack.topAnchor.constraint(equalTo: self.layoutMarginsGuide.topAnchor), mainStack.leftAnchor.constraint(equalTo: self.layoutMarginsGuide.leftAnchor), mainStack.rightAnchor.constraint(equalTo: self.layoutMarginsGuide.rightAnchor), diff --git a/project/Projects/Presentation/Feature/Base/Sources/View/ViewController/Base/BaseViewController.swift b/project/Projects/Presentation/Feature/Base/Sources/View/ViewController/Base/BaseViewController.swift index d4ae4a2f..da7d3c69 100644 --- a/project/Projects/Presentation/Feature/Base/Sources/View/ViewController/Base/BaseViewController.swift +++ b/project/Projects/Presentation/Feature/Base/Sources/View/ViewController/Base/BaseViewController.swift @@ -149,7 +149,7 @@ extension BaseViewController { // ์Šค๋‚ต๋ฐ”๋ฅผ ํ•˜๋‹จ์— ๊ฐ์ถ˜๋‹ค snackBar.transform = .init(translationX: 0, y: snackBarHeight+horizontalPadding) - snackBar.alpha = 0.5 + snackBar.alpha = 0.25 // ๋ทฐ๊ณ„์ธต์— ์ถ”๊ฐ€ view.addSubview(snackBar) @@ -163,7 +163,9 @@ extension BaseViewController { UIView.animate(withDuration: 0.2, delay: snackBarShowingDuration, options: .curveEaseIn) { snackBar.transform = .init(translationX: 0, y: snackBarHeight+horizontalPadding) - snackBar.alpha = 0.5 + snackBar.alpha = 0.25 + } completion: { _ in + snackBar.removeFromSuperview() } } }