Skip to content

Commit

Permalink
merge :: 비밀번호 변경 Feature
Browse files Browse the repository at this point in the history
Merge pull request #140 from team-aliens/126-change-password-feature
  • Loading branch information
kimdaehee0824 authored Nov 28, 2022
2 parents dd30e53 + 0aa73ad commit 1e3518c
Show file tree
Hide file tree
Showing 11 changed files with 356 additions and 5 deletions.
6 changes: 6 additions & 0 deletions Projects/App/Sources/Application/DI/AppComponent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,10 @@ public extension AppComponent {
var rewardPointDetailComponent: RewardPointDetailComponent {
RewardPointDetailComponent(parent: self)
}
var checkPasswordComponent: CheckPasswordComponent {
CheckPasswordComponent(parent: self)
}
var modifyPasswordComponent: ModifyPasswordComponent {
ModifyPasswordComponent(parent: self)
}
}
48 changes: 48 additions & 0 deletions Projects/App/Sources/Application/NeedleGenerated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ private class MyPageDependency48d84b530313b3ee40feProvider: MyPageDependency {
var rewardPointDetailComponent: RewardPointDetailComponent {
return appComponent.rewardPointDetailComponent
}
var checkPasswordComponent: CheckPasswordComponent {
return appComponent.checkPasswordComponent
}
private let appComponent: AppComponent
init(appComponent: AppComponent) {
self.appComponent = appComponent
Expand All @@ -204,6 +207,19 @@ private class MyPageDependency48d84b530313b3ee40feProvider: MyPageDependency {
private func factory0f6f456ebf157d02dfb3f47b58f8f304c97af4d5(_ component: NeedleFoundation.Scope) -> AnyObject {
return MyPageDependency48d84b530313b3ee40feProvider(appComponent: parent1(component) as! AppComponent)
}
private class ModifyPasswordDependency8e8e0713c7893c69f342Provider: ModifyPasswordDependency {
var changePasswordUseCase: any ChangePasswordUseCase {
return appComponent.changePasswordUseCase
}
private let appComponent: AppComponent
init(appComponent: AppComponent) {
self.appComponent = appComponent
}
}
/// ^->AppComponent->ModifyPasswordComponent
private func factoryf1815b12945a9aa456a2f47b58f8f304c97af4d5(_ component: NeedleFoundation.Scope) -> AnyObject {
return ModifyPasswordDependency8e8e0713c7893c69f342Provider(appComponent: parent1(component) as! AppComponent)
}
private class RewardPointDetailDependency623f1251c3863ea3b233Provider: RewardPointDetailDependency {
var fetchPointListUseCase: any FetchPointListUseCase {
return appComponent.fetchPointListUseCase
Expand Down Expand Up @@ -233,6 +249,22 @@ private class ChangeProfileDependency18055275199967076a28Provider: ChangeProfile
private func factory239204ef0c47c0c68c97f47b58f8f304c97af4d5(_ component: NeedleFoundation.Scope) -> AnyObject {
return ChangeProfileDependency18055275199967076a28Provider(appComponent: parent1(component) as! AppComponent)
}
private class CheckPasswordDependencyd8ff624643356835c570Provider: CheckPasswordDependency {
var compareCurrentPasswordUseCase: any CompareCurrentPasswordUseCase {
return appComponent.compareCurrentPasswordUseCase
}
var modifyPasswordComponent: ModifyPasswordComponent {
return appComponent.modifyPasswordComponent
}
private let appComponent: AppComponent
init(appComponent: AppComponent) {
self.appComponent = appComponent
}
}
/// ^->AppComponent->CheckPasswordComponent
private func factorycb24ea072925f86bef40f47b58f8f304c97af4d5(_ component: NeedleFoundation.Scope) -> AnyObject {
return CheckPasswordDependencyd8ff624643356835c570Provider(appComponent: parent1(component) as! AppComponent)
}
private class RootDependency3944cc797a4a88956fb5Provider: RootDependency {
var signinComponent: SigninComponent {
return appComponent.signinComponent
Expand Down Expand Up @@ -423,6 +455,8 @@ extension AppComponent: Registration {
localTable["changeProfileComponent-ChangeProfileComponent"] = { self.changeProfileComponent as Any }
localTable["noticeDetailComponent-NoticeDetailComponent"] = { self.noticeDetailComponent as Any }
localTable["rewardPointDetailComponent-RewardPointDetailComponent"] = { self.rewardPointDetailComponent as Any }
localTable["checkPasswordComponent-CheckPasswordComponent"] = { self.checkPasswordComponent as Any }
localTable["modifyPasswordComponent-ModifyPasswordComponent"] = { self.modifyPasswordComponent as Any }
localTable["remoteNoticeDataSource-any RemoteNoticeDataSource"] = { self.remoteNoticeDataSource as Any }
localTable["noticeRepository-any NoticeRepository"] = { self.noticeRepository as Any }
localTable["fetchWhetherNewNoticeUseCase-any FetchWhetherNewNoticeUseCase"] = { self.fetchWhetherNewNoticeUseCase as Any }
Expand Down Expand Up @@ -521,6 +555,12 @@ extension MyPageComponent: Registration {
keyPathToName[\MyPageDependency.fetchMyProfileUseCase] = "fetchMyProfileUseCase-any FetchMyProfileUseCase"
keyPathToName[\MyPageDependency.changeProfileComponent] = "changeProfileComponent-ChangeProfileComponent"
keyPathToName[\MyPageDependency.rewardPointDetailComponent] = "rewardPointDetailComponent-RewardPointDetailComponent"
keyPathToName[\MyPageDependency.checkPasswordComponent] = "checkPasswordComponent-CheckPasswordComponent"
}
}
extension ModifyPasswordComponent: Registration {
public func registerItems() {
keyPathToName[\ModifyPasswordDependency.changePasswordUseCase] = "changePasswordUseCase-any ChangePasswordUseCase"
}
}
extension RewardPointDetailComponent: Registration {
Expand All @@ -534,6 +574,12 @@ extension ChangeProfileComponent: Registration {
keyPathToName[\ChangeProfileDependency.uploadFileUseCase] = "uploadFileUseCase-any UploadFileUseCase"
}
}
extension CheckPasswordComponent: Registration {
public func registerItems() {
keyPathToName[\CheckPasswordDependency.compareCurrentPasswordUseCase] = "compareCurrentPasswordUseCase-any CompareCurrentPasswordUseCase"
keyPathToName[\CheckPasswordDependency.modifyPasswordComponent] = "modifyPasswordComponent-ModifyPasswordComponent"
}
}
extension RootComponent: Registration {
public func registerItems() {
keyPathToName[\RootDependency.signinComponent] = "signinComponent-SigninComponent"
Expand Down Expand Up @@ -620,8 +666,10 @@ private func registerProviderFactory(_ componentPath: String, _ factory: @escapi
registerProviderFactory("^->AppComponent->SignupProfileImageComponent", factory6792674212c15df7e9cff47b58f8f304c97af4d5)
registerProviderFactory("^->AppComponent->MainTabComponent", factory1ab5a747ddf21e1393f9f47b58f8f304c97af4d5)
registerProviderFactory("^->AppComponent->MyPageComponent", factory0f6f456ebf157d02dfb3f47b58f8f304c97af4d5)
registerProviderFactory("^->AppComponent->ModifyPasswordComponent", factoryf1815b12945a9aa456a2f47b58f8f304c97af4d5)
registerProviderFactory("^->AppComponent->RewardPointDetailComponent", factory87993268d9e212be8b1af47b58f8f304c97af4d5)
registerProviderFactory("^->AppComponent->ChangeProfileComponent", factory239204ef0c47c0c68c97f47b58f8f304c97af4d5)
registerProviderFactory("^->AppComponent->CheckPasswordComponent", factorycb24ea072925f86bef40f47b58f8f304c97af4d5)
registerProviderFactory("^->AppComponent->RootComponent", factory264bfc4d4cb6b0629b40f47b58f8f304c97af4d5)
registerProviderFactory("^->AppComponent->SigninComponent", factory2882a056d84a613debccf47b58f8f304c97af4d5)
registerProviderFactory("^->AppComponent->HomeComponent", factory67229cdf0f755562b2b1f47b58f8f304c97af4d5)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import DomainModule
import SwiftUI
import NeedleFoundation

public protocol CheckPasswordDependency: Dependency {
var compareCurrentPasswordUseCase: any CompareCurrentPasswordUseCase { get }
var modifyPasswordComponent: ModifyPasswordComponent { get }
}

public final class CheckPasswordComponent: Component<CheckPasswordDependency> {
public func makeView() -> some View {
CheckPasswordView(
viewModel: .init(
compareCurrentPasswordUseCase: self.dependency.compareCurrentPasswordUseCase
),
modifyPasswordComponent: self.dependency.modifyPasswordComponent
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import DesignSystem
import Utility
import SwiftUI

struct CheckPasswordView: View {

@StateObject var viewModel: CheckPasswordViewModel
let modifyPasswordComponent: ModifyPasswordComponent
@Environment(\.dismiss) var dismiss

init(
viewModel: CheckPasswordViewModel,
modifyPasswordComponent: ModifyPasswordComponent
) {
_viewModel = StateObject(wrappedValue: viewModel)
self.modifyPasswordComponent = modifyPasswordComponent
}

var body: some View {
VStack(spacing: 4) {
DMSHeaderTitleView(subTitle: "기존 비밀번호")
.padding(.top, 24)

SecureDMSFloatingTextField(
"비밀번호",
text: $viewModel.password,
isError: viewModel.isPasswordRegexError,
errorMessage: "유효하지 않은 비밀번호입니다."
) {
viewModel.checkPasswordButtonDidTap()

}
.padding(.top, 56)

Spacer()

DMSWideButton(text: "다음", color: .PrimaryVariant.primary) {
viewModel.checkPasswordButtonDidTap()
}
.disabled(!viewModel.isCheckPasswordEnabled)
.padding(.bottom, 40)
}
.hideKeyboardWhenTap()
.dmsBackButton(dismiss: dismiss)
.padding(.horizontal, 24)
.dmsBackground()
.dmsToast(isShowing: $viewModel.isShowingToast, message: viewModel.errorMessage, style: .error)
.ignoresSafeArea(.keyboard, edges: .bottom)
.navigate(
to: modifyPasswordComponent.makeView(
currentPassword: viewModel.password
),
when: $viewModel.isSuccessCheckPassword
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import BaseFeature
import Combine
import DomainModule

final class CheckPasswordViewModel: BaseViewModel {
@Published var password = "" {
didSet { resettingError() }
}
@Published var isPasswordRegexError = false
@Published var isSuccessCheckPassword = false
@Published var isShowingToast = false

var isCheckPasswordEnabled: Bool {
!password.isEmpty
}

private let compareCurrentPasswordUseCase: any CompareCurrentPasswordUseCase

public init(
compareCurrentPasswordUseCase: any CompareCurrentPasswordUseCase
) {
self.compareCurrentPasswordUseCase = compareCurrentPasswordUseCase
}

func checkPasswordButtonDidTap() {
guard isCheckPasswordEnabled else {
return
}

let passwordExpression = "^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+=-]).{8,20}$"
guard password ~= passwordExpression else {
isPasswordRegexError = true
return
}

addCancellable(
compareCurrentPasswordUseCase.execute(password: password)
) { [weak self] _ in
self?.isSuccessCheckPassword = true
} onReceiveError: { [weak self] _ in
self?.isShowingToast = true
}
}

func resettingError() {
isPasswordRegexError = false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import DomainModule
import SwiftUI
import NeedleFoundation

public protocol ModifyPasswordDependency: Dependency {
var changePasswordUseCase: any ChangePasswordUseCase { get }
}

public final class ModifyPasswordComponent: Component<ModifyPasswordDependency> {
public func makeView(currentPassword: String) -> some View {
ModifyPasswordView(
viewModel: .init(
changePasswordUseCase: self.dependency.changePasswordUseCase,
currentPassword: currentPassword
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import DesignSystem
import Utility
import SwiftUI

struct ModifyPasswordView: View {
private enum FocusField {
case password
case passwordCheck
}

@FocusState private var focusField: FocusField?
@StateObject var viewModel: ModifyPasswordViewModel
@Environment(\.dismiss) var dismiss

init(
viewModel: ModifyPasswordViewModel
) {
_viewModel = StateObject(wrappedValue: viewModel)
}

var body: some View {
VStack(spacing: 4) {
DMSHeaderTitleView(subTitle: "새 비밀번호 설정")
.padding(.top, 24)

HStack {
Text("비밀번호는 영문, 숫자, 기호를 포함한 8~20자이어야 합니다.")
.dmsFont(.etc(.caption), color: .GrayScale.gray5)

Spacer()
}

VStack(spacing: 60) {
SecureDMSFloatingTextField(
"새 비밀번호 입력",
text: $viewModel.password,
isError: viewModel.isPasswordRegexError,
errorMessage: "비밀번호가 형식이 올바르지 않습니다."
) {
focusField = .passwordCheck
}
.focused($focusField, equals: .password)

SecureDMSFloatingTextField(
"새 비밀번호 확인 ",
text: $viewModel.passwordCheck,
isError: viewModel.isPasswordMismatchedError,
errorMessage: "비밀번호가 위와 일치하지 않습니다."
) {
viewModel.changePasswordButtonDidTap()
}
.focused($focusField, equals: .passwordCheck)
}
.padding(.top, 56)

Spacer()

DMSWideButton(text: "다음", color: .PrimaryVariant.primary) {
viewModel.changePasswordButtonDidTap()
}
.disabled(!viewModel.iChangePasswordEnabled)
.padding(.bottom, 40)
}
.hideKeyboardWhenTap()
.onAppear {
focusField = .password
}
.dmsBackButton(dismiss: dismiss)
.padding(.horizontal, 24)
.dmsBackground()
.dmsToast(isShowing: $viewModel.isShowingToast, message: viewModel.errorMessage, style: .error)
.ignoresSafeArea(.keyboard, edges: .bottom)
.onChange(of: viewModel.isSuccessRenewalPassword) { newValue in
if newValue {
NavigationUtil.popToRootView()
}
}
}
}
Loading

0 comments on commit 1e3518c

Please sign in to comment.