Skip to content

Commit

Permalink
Merge pull request #70 from team-aliens/42-signin-feature
Browse files Browse the repository at this point in the history
merge :: 로그인 Feature
  • Loading branch information
baekteun authored Oct 21, 2022
2 parents bc66e44 + da7a4c2 commit 235dbb6
Show file tree
Hide file tree
Showing 24 changed files with 446 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public extension TargetDependency {
}

public extension TargetDependency.Project.Features {
static let SigninFeature = TargetDependency.feature(name: "SigninFeature")
static let BaseFeature = TargetDependency.feature(name: "BaseFeature")
static let RootFeature = TargetDependency.feature(name: "RootFeature")
}
Expand Down
7 changes: 7 additions & 0 deletions Projects/App/Sources/Application/DI/AppComponent.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import NeedleFoundation
import SwiftUI
import KeychainModule
import SigninFeature

public final class AppComponent: BootstrapComponent {
public func makeRootView() -> some View {
Expand All @@ -11,3 +12,9 @@ public final class AppComponent: BootstrapComponent {
KeychainImpl()
}
}

public extension AppComponent {
var signinComponent: SigninComponent {
SigninComponent(parent: self)
}
}
9 changes: 8 additions & 1 deletion Projects/App/Sources/Application/DMSApp.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import SwiftUI
import DesignSystem
import SigninFeature

@main
struct DMSApp: App {
init() {
registerProviderFactories()
}

var body: some Scene {
WindowGroup {
DesignSystemPlaygroundView()
NavigationView {
AppComponent().signinComponent.makeView()
}
}
}
}
37 changes: 37 additions & 0 deletions Projects/App/Sources/Application/NeedleGenerated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import DomainModule
import KeychainModule
import NeedleFoundation
import NetworkModule
import SigninFeature
import SwiftUI

// swiftlint:disable unused_declaration
Expand All @@ -20,11 +21,46 @@ private func parent1(_ component: NeedleFoundation.Scope) -> NeedleFoundation.Sc

#if !NEEDLE_DYNAMIC

private class SigninDependencyde06a9d0b22764487733Provider: SigninDependency {
var signinUseCase: any SigninUseCase {
return appComponent.signinUseCase
}
private let appComponent: AppComponent
init(appComponent: AppComponent) {
self.appComponent = appComponent
}
}
/// ^->AppComponent->SigninComponent
private func factory2882a056d84a613debccf47b58f8f304c97af4d5(_ component: NeedleFoundation.Scope) -> AnyObject {
return SigninDependencyde06a9d0b22764487733Provider(appComponent: parent1(component) as! AppComponent)
}

#else
extension AppComponent: Registration {
public func registerItems() {

localTable["keychain-any Keychain"] = { self.keychain as Any }
localTable["remoteAuthDataSource-any RemoteAuthDataSource"] = { self.remoteAuthDataSource as Any }
localTable["authRepository-any AuthRepository"] = { self.authRepository as Any }
localTable["signinUseCase-any SigninUseCase"] = { self.signinUseCase as Any }
localTable["verifyAuthCodeUseCase-any VerifyAuthCodeUseCase"] = { self.verifyAuthCodeUseCase as Any }
localTable["sendAuthCodeUseCase-any SendAuthCodeUseCase"] = { self.sendAuthCodeUseCase as Any }
localTable["checkEmailExistByAccountIDUseCase-any CheckEmailExistByAccountIDUseCase"] = { self.checkEmailExistByAccountIDUseCase as Any }
localTable["checkAccountIDIsExistUseCase-any CheckAccountIDIsExistUseCase"] = { self.checkAccountIDIsExistUseCase as Any }
localTable["signinComponent-SigninComponent"] = { self.signinComponent as Any }
localTable["remoteStudentsDataSource-any RemoteStudentsDataSource"] = { self.remoteStudentsDataSource as Any }
localTable["studentsRepository-any StudentsRepository"] = { self.studentsRepository as Any }
localTable["signupUseCase-any SignupUseCase"] = { self.signupUseCase as Any }
localTable["checkDuplicateAccountIDUseCase-any CheckDuplicateAccountIDUseCase"] = { self.checkDuplicateAccountIDUseCase as Any }
localTable["checkDuplicateEmailUseCase-any CheckDuplicateEmailUseCase"] = { self.checkDuplicateEmailUseCase as Any }
localTable["renewalPasswordUseCase-any RenewalPasswordUseCase"] = { self.renewalPasswordUseCase as Any }
localTable["findIDUseCase-any FindIDUseCase"] = { self.findIDUseCase as Any }
localTable["fetchMyProfileUseCase-any FetchMyProfileUseCase"] = { self.fetchMyProfileUseCase as Any }
}
}
extension SigninComponent: Registration {
public func registerItems() {
keyPathToName[\SigninDependency.signinUseCase] = "signinUseCase-any SigninUseCase"
}
}

Expand All @@ -44,6 +80,7 @@ private func registerProviderFactory(_ componentPath: String, _ factory: @escapi

private func register1() {
registerProviderFactory("^->AppComponent", factoryEmptyDependencyProvider)
registerProviderFactory("^->AppComponent->SigninComponent", factory2882a056d84a613debccf47b58f8f304c97af4d5)
}
#endif

Expand Down
3 changes: 2 additions & 1 deletion Projects/Features/RootFeature/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ let project = Project.makeModule(
name: "RootFeature",
product: .staticFramework,
dependencies: [
.Project.Features.BaseFeature
.Project.Features.BaseFeature,
.Project.Features.SigninFeature
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
10 changes: 10 additions & 0 deletions Projects/Features/SigninFeature/Project.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import ProjectDescription
import ProjectDescriptionHelpers

let project = Project.makeModule(
name: "SigninFeature",
product: .staticFramework,
dependencies: [
.Project.Features.BaseFeature
]
)
17 changes: 17 additions & 0 deletions Projects/Features/SigninFeature/Sources/SigninComponent.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import DomainModule
import NeedleFoundation
import SwiftUI

public protocol SigninDependency: Dependency {
var signinUseCase: any SigninUseCase { get }
}

public final class SigninComponent: Component<SigninDependency> {
public func makeView() -> some View {
SigninView(
viewModel: .init(
signinUseCase: dependency.signinUseCase
)
)
}
}
117 changes: 117 additions & 0 deletions Projects/Features/SigninFeature/Sources/SigninView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import SwiftUI
import DesignSystem

struct SigninView: View {
private enum FocusField {
case id
case password
}
@StateObject var viewModel: SigninViewModel
@FocusState private var focusField: FocusField?

public init(viewModel: SigninViewModel) {
_viewModel = StateObject(wrappedValue: viewModel)
}

var body: some View {
VStack {
HStack {
VStack(alignment: .leading, spacing: 8) {
Text("DMS")
.dmsFont(.title(.extraLarge), color: .PrimaryVariant.primary)
.padding(.top, 28)

Text("더 편한 기숙사 생활을 위해")
.dmsFont(.text(.medium), color: .GrayScale.gray6)
}

Spacer()
}

VStack(spacing: 72) {
DMSFloatingTextField(
"아이디",
text: $viewModel.id,
isError: viewModel.isErrorOcuured
) {
focusField = .password
}
.textContentType(.username)
.focused($focusField, equals: .id)

SecureDMSFloatingTextField("비밀번호", text: $viewModel.password) {
viewModel.signinButtonDidTap()
}
.textContentType(.password)
.focused($focusField, equals: .password)
}
.padding(.top, 68)

HStack(spacing: 16) {
HStack(spacing: 12) {
DMSRadioButton(isOn: $viewModel.isOnAutoSignin)

Text("자동로그인")
.dmsFont(.text(.small), color: .GrayScale.gray6)
}
.onTapGesture {
withAnimation {
viewModel.isOnAutoSignin.toggle()
}
}

Spacer()

NavigationLink {
Text("아이디 찾기")
} label: {
Text("아이디 찾기")
.dmsFont(.text(.extraSmall), color: .GrayScale.gray5)
}

Divider()
.foregroundColor(.GrayScale.gray5)
.frame(height: 13)

NavigationLink {
Text("비밀번호 재설정")
} label: {
Text("비밀번호 재설정")
.dmsFont(.text(.extraSmall), color: .GrayScale.gray5)
}
}
.padding(.top, 16)

Spacer()

HStack(spacing: 16) {
Text("아직 회원이 아니신가요?")
.dmsFont(.text(.extraSmall), color: .GrayScale.gray5)

DMSButton(text: "회원가입", style: .text, color: .GrayScale.gray6) {
viewModel.isNavigateSignup.toggle()
}
}

DMSWideButton(text: "로그인", color: .PrimaryVariant.primary) {
viewModel.signinButtonDidTap()
}
.disabled(!viewModel.isSigninButtonEnabled)
.padding(.top, 24)
.frame(maxWidth: .infinity)
.padding(.bottom, 40)
}
.dmsToast(isShowing: $viewModel.isErrorOcuured, message: viewModel.errorMessage, style: .error)
.frame(maxWidth: .infinity)
.padding(.horizontal, 24)
.dmsBackground()
.navigate(to: Text("회원가입"), when: $viewModel.isNavigateSignup)
.ignoresSafeArea(.keyboard, edges: .bottom)
}
}

struct SigninView_Previews: PreviewProvider {
static var previews: some View {
Text("A")
}
}
27 changes: 27 additions & 0 deletions Projects/Features/SigninFeature/Sources/SigninViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import BaseFeature
import Combine
import DomainModule

final class SigninViewModel: BaseViewModel {
@Published var id = ""
@Published var password = ""
@Published var isOnAutoSignin = true
@Published var isNavigateSignup = false
@Published var isSuccessSignin = false
var isSigninButtonEnabled: Bool {
!id.isEmpty && !password.isEmpty
}

private let signinUseCase: any SigninUseCase

public init(signinUseCase: any SigninUseCase) {
self.signinUseCase = signinUseCase
}

func signinButtonDidTap() {
guard isSigninButtonEnabled else { return }
addCancellable(signinUseCase.execute(req: .init(accountID: id, password: password))) { [weak self] _ in
self?.isSuccessSignin = true
}
}
}
Loading

0 comments on commit 235dbb6

Please sign in to comment.