From 046354faadc977c7e2397e18e1f8cf1464b2132c Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 09:06:16 +0900 Subject: [PATCH 01/33] =?UTF-8?q?=E2=9C=A8=20::=20Navigation=20bar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .swiftlint.yml | 3 - Projects/App/.swiftlint.yml | 3 + .../Chevron Left.imageset/Chevron Left.svg | 3 + .../Chevron Left.imageset/Contents.json | 21 ++++ .../Extension/View+navigationBar.swift | 100 ++++++++++++++++++ .../DesignSystem/Sources/Images/KGIcon.swift | 31 ++++++ 6 files changed, 158 insertions(+), 3 deletions(-) delete mode 100644 .swiftlint.yml create mode 100644 Projects/App/.swiftlint.yml create mode 100644 Projects/UserInterface/DesignSystem/Resources/Images/Icons.xcassets/Chevron Left.imageset/Chevron Left.svg create mode 100644 Projects/UserInterface/DesignSystem/Resources/Images/Icons.xcassets/Chevron Left.imageset/Contents.json create mode 100644 Projects/UserInterface/DesignSystem/Sources/Extension/View+navigationBar.swift create mode 100644 Projects/UserInterface/DesignSystem/Sources/Images/KGIcon.swift diff --git a/.swiftlint.yml b/.swiftlint.yml deleted file mode 100644 index 8b86bfd..0000000 --- a/.swiftlint.yml +++ /dev/null @@ -1,3 +0,0 @@ -excluded: - - "**/*/NeedleGenerated.swift" - - "Tuist" diff --git a/Projects/App/.swiftlint.yml b/Projects/App/.swiftlint.yml new file mode 100644 index 0000000..3762c83 --- /dev/null +++ b/Projects/App/.swiftlint.yml @@ -0,0 +1,3 @@ +excluded: + - "Sources/Application/NeedleGenerated.swift" + - "Tuist" diff --git a/Projects/UserInterface/DesignSystem/Resources/Images/Icons.xcassets/Chevron Left.imageset/Chevron Left.svg b/Projects/UserInterface/DesignSystem/Resources/Images/Icons.xcassets/Chevron Left.imageset/Chevron Left.svg new file mode 100644 index 0000000..54cf988 --- /dev/null +++ b/Projects/UserInterface/DesignSystem/Resources/Images/Icons.xcassets/Chevron Left.imageset/Chevron Left.svg @@ -0,0 +1,3 @@ + + + diff --git a/Projects/UserInterface/DesignSystem/Resources/Images/Icons.xcassets/Chevron Left.imageset/Contents.json b/Projects/UserInterface/DesignSystem/Resources/Images/Icons.xcassets/Chevron Left.imageset/Contents.json new file mode 100644 index 0000000..3f82637 --- /dev/null +++ b/Projects/UserInterface/DesignSystem/Resources/Images/Icons.xcassets/Chevron Left.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Chevron Left.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Projects/UserInterface/DesignSystem/Sources/Extension/View+navigationBar.swift b/Projects/UserInterface/DesignSystem/Sources/Extension/View+navigationBar.swift new file mode 100644 index 0000000..bee01cb --- /dev/null +++ b/Projects/UserInterface/DesignSystem/Sources/Extension/View+navigationBar.swift @@ -0,0 +1,100 @@ +import SwiftUI + +public typealias Icons = KGIcon.Icon + +public struct NavigationBarModifier: ViewModifier { + @Environment(\.dismiss) private var dismiss + private let navigationTitle: String + + private let hasBackButton: Bool + private let rightIcon: (icon: Icons, action: () -> Void)? + + init( + navigationTitle: String, + hasBackButton: Bool = false, + rightIcon: (Icons, () -> Void)? = nil + ) { + self.navigationTitle = navigationTitle + self.hasBackButton = hasBackButton + self.rightIcon = rightIcon + } + + public func body(content: Content) -> some View { + VStack(spacing: .zero) { + ZStack(alignment: .topLeading) { + HStack { + if hasBackButton { + Button { + dismiss() + } label: { + KGIcon(.chevronLeft) + .frame(28) + .padding(12) + } + } + + Spacer() + + if let rightIcon { + Button(action: rightIcon.action) { + KGIcon(rightIcon.icon) + .frame(28) + .padding(12) + } + } + } + .frame(height: 68) + .padding(.horizontal, 12) + + Text(navigationTitle) + .kgFont(.m2, weight: .semiBold, color: .Grays.white) + .padding(.vertical, 10) + .frame(maxWidth: .infinity) + } + .background(Color.System.background.ignoresSafeArea(edges: .top)) + + content + .frame(maxHeight: .infinity) + } + .navigationBarHidden(true) + } +} + +public extension View { + func setNavigationBar( + navigationTitle: String, + hasBackButton: Bool = false, + rightIcon: (Icons, () -> Void)? = nil + ) -> some View { + modifier( + NavigationBarModifier( + navigationTitle: navigationTitle, + hasBackButton: hasBackButton, + rightIcon: rightIcon + ) + ) + } + + func setNavigationBackButton( + navigationTitle: String = "" + ) -> some View { + modifier( + NavigationBarModifier( + navigationTitle: navigationTitle, + hasBackButton: true + ) + ) + } +} + +// SwipeGesture로 뒤로갈 수 있게 하는 extension +extension UINavigationController: ObservableObject, UIGestureRecognizerDelegate { + override open func viewDidLoad() { + super.viewDidLoad() + interactivePopGestureRecognizer?.delegate = self + } + + public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { + return viewControllers.count > 1 + } +} diff --git a/Projects/UserInterface/DesignSystem/Sources/Images/KGIcon.swift b/Projects/UserInterface/DesignSystem/Sources/Images/KGIcon.swift new file mode 100644 index 0000000..1812e6f --- /dev/null +++ b/Projects/UserInterface/DesignSystem/Sources/Images/KGIcon.swift @@ -0,0 +1,31 @@ +import SwiftUI + +public struct KGIcon: View { + public enum Icon { + case chevronLeft + } + + private var icon: Icon + private var renderingMode: SwiftUI.Image.TemplateRenderingMode + + public init( + _ icon: Icon, + renderingMode: SwiftUI.Image.TemplateRenderingMode = .original + ) { + self.icon = icon + self.renderingMode = renderingMode + } + + public var body: some View { + jobisToImage() + .resizable() + .renderingMode(renderingMode) + } + + private func jobisToImage() -> SwiftUI.Image { + switch icon { + case .chevronLeft: + DesignSystemAsset.Icons.chevronLeft.swiftUIImage + } + } +} From 9156f0b4ce32526cb1bc98b64622b22c96944f87 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 09:43:34 +0900 Subject: [PATCH 02/33] =?UTF-8?q?=E2=9C=A8=20::=20Signup=20File=20init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectDescriptionHelpers/ModulePaths.swift | 1 + .../SignupEmailAuthCodeVerifyFactory.swift | 6 ++++++ .../Interface/SignupEmailVerifyFactory.swift | 6 ++++++ .../Interface/SignupPasswordFactory.swift | 6 ++++++ .../UserInfo/SignupCheckLevelFactory.swift | 6 ++++++ .../UserInfo/SignupGenderFactory.swift | 6 ++++++ .../Interface/UserInfo/SignupNameFactory.swift | 6 ++++++ .../UserInfo/SignupStudentIDFactory.swift | 6 ++++++ Projects/Feature/SignupFeature/Project.swift | 17 +++++++++++++++++ .../SignupEmailAuthCodeVerifyComponent.swift | 14 ++++++++++++++ .../SignupEmailAuthCodeVerifyView.swift | 17 +++++++++++++++++ .../SignupEmailAuthCodeVerifyViewModel.swift | 5 +++++ .../SignupEmailVerifyComponent.swift | 14 ++++++++++++++ .../EmailVerify/SignupEmailVerifyView.swift | 17 +++++++++++++++++ .../SignupEmailVerifyViewModel.swift | 5 +++++ .../Password/SignupPasswordComponent.swift | 14 ++++++++++++++ .../Sources/Password/SignupPasswordView.swift | 17 +++++++++++++++++ .../Password/SignupPasswordViewModel.swift | 5 +++++ .../CheckLevel/SignupCheckLevelComponent.swift | 14 ++++++++++++++ .../CheckLevel/SignupCheckLevelView.swift | 17 +++++++++++++++++ .../CheckLevel/SignupCheckLevelViewModel.swift | 5 +++++ .../UserInfo/Gender/SignupGenderComponent.swift | 14 ++++++++++++++ .../UserInfo/Gender/SignupGenderView.swift | 17 +++++++++++++++++ .../UserInfo/Gender/SignupGenderViewModel.swift | 5 +++++ .../UserInfo/Name/SignupNameComponent.swift | 14 ++++++++++++++ .../Sources/UserInfo/Name/SignupNameView.swift | 17 +++++++++++++++++ .../UserInfo/Name/SignupNameViewModel.swift | 5 +++++ .../StudentID/SignupStudentIDComponent.swift | 14 ++++++++++++++ .../StudentID/SignupStudentIDView.swift | 17 +++++++++++++++++ .../StudentID/SignupStudentIDViewModel.swift | 5 +++++ .../SignupFeature/Tests/SignupFeatureTest.swift | 11 +++++++++++ 31 files changed, 323 insertions(+) create mode 100644 Projects/Feature/SignupFeature/Interface/SignupEmailAuthCodeVerifyFactory.swift create mode 100644 Projects/Feature/SignupFeature/Interface/SignupEmailVerifyFactory.swift create mode 100644 Projects/Feature/SignupFeature/Interface/SignupPasswordFactory.swift create mode 100644 Projects/Feature/SignupFeature/Interface/UserInfo/SignupCheckLevelFactory.swift create mode 100644 Projects/Feature/SignupFeature/Interface/UserInfo/SignupGenderFactory.swift create mode 100644 Projects/Feature/SignupFeature/Interface/UserInfo/SignupNameFactory.swift create mode 100644 Projects/Feature/SignupFeature/Interface/UserInfo/SignupStudentIDFactory.swift create mode 100644 Projects/Feature/SignupFeature/Project.swift create mode 100644 Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyComponent.swift create mode 100644 Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyView.swift create mode 100644 Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyViewModel.swift create mode 100644 Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyComponent.swift create mode 100644 Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyView.swift create mode 100644 Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyViewModel.swift create mode 100644 Projects/Feature/SignupFeature/Sources/Password/SignupPasswordComponent.swift create mode 100644 Projects/Feature/SignupFeature/Sources/Password/SignupPasswordView.swift create mode 100644 Projects/Feature/SignupFeature/Sources/Password/SignupPasswordViewModel.swift create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelComponent.swift create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelView.swift create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelViewModel.swift create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderComponent.swift create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderView.swift create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderViewModel.swift create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameComponent.swift create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameView.swift create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameViewModel.swift create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDComponent.swift create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDView.swift create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDViewModel.swift create mode 100644 Projects/Feature/SignupFeature/Tests/SignupFeatureTest.swift diff --git a/Plugin/DependencyPlugin/ProjectDescriptionHelpers/ModulePaths.swift b/Plugin/DependencyPlugin/ProjectDescriptionHelpers/ModulePaths.swift index ba6d75f..e179a2d 100644 --- a/Plugin/DependencyPlugin/ProjectDescriptionHelpers/ModulePaths.swift +++ b/Plugin/DependencyPlugin/ProjectDescriptionHelpers/ModulePaths.swift @@ -24,6 +24,7 @@ extension ModulePaths: MicroTargetPathConvertable { public extension ModulePaths { enum Feature: String, MicroTargetPathConvertable { + case SignupFeature case SigninFeature case SplashFeature case RootFeature diff --git a/Projects/Feature/SignupFeature/Interface/SignupEmailAuthCodeVerifyFactory.swift b/Projects/Feature/SignupFeature/Interface/SignupEmailAuthCodeVerifyFactory.swift new file mode 100644 index 0000000..12eb80d --- /dev/null +++ b/Projects/Feature/SignupFeature/Interface/SignupEmailAuthCodeVerifyFactory.swift @@ -0,0 +1,6 @@ +import SwiftUI + +public protocol SignupEmailAuthCodeVerifyFactory { + associatedtype SomeView: View + func makeView() -> SomeView +} diff --git a/Projects/Feature/SignupFeature/Interface/SignupEmailVerifyFactory.swift b/Projects/Feature/SignupFeature/Interface/SignupEmailVerifyFactory.swift new file mode 100644 index 0000000..e2f140f --- /dev/null +++ b/Projects/Feature/SignupFeature/Interface/SignupEmailVerifyFactory.swift @@ -0,0 +1,6 @@ +import SwiftUI + +public protocol SignupEmailVerifyFactory { + associatedtype SomeView: View + func makeView() -> SomeView +} diff --git a/Projects/Feature/SignupFeature/Interface/SignupPasswordFactory.swift b/Projects/Feature/SignupFeature/Interface/SignupPasswordFactory.swift new file mode 100644 index 0000000..e87090d --- /dev/null +++ b/Projects/Feature/SignupFeature/Interface/SignupPasswordFactory.swift @@ -0,0 +1,6 @@ +import SwiftUI + +public protocol SignupPasswordFactory { + associatedtype SomeView: View + func makeView() -> SomeView +} diff --git a/Projects/Feature/SignupFeature/Interface/UserInfo/SignupCheckLevelFactory.swift b/Projects/Feature/SignupFeature/Interface/UserInfo/SignupCheckLevelFactory.swift new file mode 100644 index 0000000..d05004f --- /dev/null +++ b/Projects/Feature/SignupFeature/Interface/UserInfo/SignupCheckLevelFactory.swift @@ -0,0 +1,6 @@ +import SwiftUI + +public protocol SignupCheckLevelFactory { + associatedtype SomeView: View + func makeView() -> SomeView +} diff --git a/Projects/Feature/SignupFeature/Interface/UserInfo/SignupGenderFactory.swift b/Projects/Feature/SignupFeature/Interface/UserInfo/SignupGenderFactory.swift new file mode 100644 index 0000000..a169b8f --- /dev/null +++ b/Projects/Feature/SignupFeature/Interface/UserInfo/SignupGenderFactory.swift @@ -0,0 +1,6 @@ +import SwiftUI + +public protocol SignupGenderFactory { + associatedtype SomeView: View + func makeView() -> SomeView +} diff --git a/Projects/Feature/SignupFeature/Interface/UserInfo/SignupNameFactory.swift b/Projects/Feature/SignupFeature/Interface/UserInfo/SignupNameFactory.swift new file mode 100644 index 0000000..cffaf15 --- /dev/null +++ b/Projects/Feature/SignupFeature/Interface/UserInfo/SignupNameFactory.swift @@ -0,0 +1,6 @@ +import SwiftUI + +public protocol SignupNameFactory { + associatedtype SomeView: View + func makeView() -> SomeView +} diff --git a/Projects/Feature/SignupFeature/Interface/UserInfo/SignupStudentIDFactory.swift b/Projects/Feature/SignupFeature/Interface/UserInfo/SignupStudentIDFactory.swift new file mode 100644 index 0000000..e9b1832 --- /dev/null +++ b/Projects/Feature/SignupFeature/Interface/UserInfo/SignupStudentIDFactory.swift @@ -0,0 +1,6 @@ +import SwiftUI + +public protocol SignupStudentIDFactory { + associatedtype SomeView: View + func makeView() -> SomeView +} diff --git a/Projects/Feature/SignupFeature/Project.swift b/Projects/Feature/SignupFeature/Project.swift new file mode 100644 index 0000000..ce18b56 --- /dev/null +++ b/Projects/Feature/SignupFeature/Project.swift @@ -0,0 +1,17 @@ +import DependencyPlugin +import ProjectDescription +import ProjectDescriptionHelpers + +let project = Project.module( + name: ModulePaths.Feature.SignupFeature.rawValue, + targets: [ + .interface(module: .feature(.SignupFeature)), + .implements(module: .feature(.SignupFeature), dependencies: [ + .feature(target: .SignupFeature, type: .interface), + .feature(target: .BaseFeature) + ]), + .tests(module: .feature(.SignupFeature), dependencies: [ + .feature(target: .SignupFeature) + ]) + ] +) diff --git a/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyComponent.swift b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyComponent.swift new file mode 100644 index 0000000..e597993 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyComponent.swift @@ -0,0 +1,14 @@ +import SwiftUI +import NeedleFoundation +import SignupEmailAuthCodeVerifyFeatureInterface + +public protocol SignupEmailAuthCodeVerifyDependency: Dependency { +} + +public final class SignupEmailAuthCodeVerifyComponent: Component, SignupEmailAuthCodeVerifyFactory { + public func makeView() -> some View { + SignupEmailAuthCodeVerifyView( + viewModel: .init() + ) + } +} diff --git a/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyView.swift b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyView.swift new file mode 100644 index 0000000..6036bf3 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyView.swift @@ -0,0 +1,17 @@ +import DesignSystem +import SwiftUI +import BaseFeature + +struct SignupEmailAuthCodeVerifyView: View { + @StateObject var viewModel: SignupEmailAuthCodeVerifyViewModel + + init( + viewModel: SignupEmailAuthCodeVerifyViewModel + ) { + _viewModel = StateObject(wrappedValue: viewModel) + } + + var body: some View { + Text("SignupEmailAuthCodeVerifyView") + } +} diff --git a/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyViewModel.swift b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyViewModel.swift new file mode 100644 index 0000000..cf62a60 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyViewModel.swift @@ -0,0 +1,5 @@ +import BaseFeature +import Combine + +final class SignupEmailAuthCodeVerifyViewModel: BaseViewModel { +} diff --git a/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyComponent.swift b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyComponent.swift new file mode 100644 index 0000000..30abaf1 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyComponent.swift @@ -0,0 +1,14 @@ +import SwiftUI +import NeedleFoundation +import SignupEmailVerifyFeatureInterface + +public protocol SignupEmailVerifyDependency: Dependency { +} + +public final class SignupEmailVerifyComponent: Component, SignupEmailVerifyFactory { + public func makeView() -> some View { + SignupEmailVerifyView( + viewModel: .init() + ) + } +} diff --git a/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyView.swift b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyView.swift new file mode 100644 index 0000000..d34915c --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyView.swift @@ -0,0 +1,17 @@ +import DesignSystem +import SwiftUI +import BaseFeature + +struct SignupEmailVerifyView: View { + @StateObject var viewModel: SignupEmailVerifyViewModel + + init( + viewModel: SignupEmailVerifyViewModel + ) { + _viewModel = StateObject(wrappedValue: viewModel) + } + + var body: some View { + Text("SignupEmailVerifyView") + } +} diff --git a/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyViewModel.swift b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyViewModel.swift new file mode 100644 index 0000000..e902fc1 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyViewModel.swift @@ -0,0 +1,5 @@ +import BaseFeature +import Combine + +final class SignupEmailVerifyViewModel: BaseViewModel { +} diff --git a/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordComponent.swift b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordComponent.swift new file mode 100644 index 0000000..43e7f04 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordComponent.swift @@ -0,0 +1,14 @@ +import SwiftUI +import NeedleFoundation +import SignupPasswordFeatureInterface + +public protocol SignupPasswordDependency: Dependency { +} + +public final class SignupPasswordComponent: Component, SignupPasswordFactory { + public func makeView() -> some View { + SignupPasswordView( + viewModel: .init() + ) + } +} diff --git a/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordView.swift b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordView.swift new file mode 100644 index 0000000..5b3978a --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordView.swift @@ -0,0 +1,17 @@ +import DesignSystem +import SwiftUI +import BaseFeature + +struct SignupPasswordView: View { + @StateObject var viewModel: SignupPasswordViewModel + + init( + viewModel: SignupPasswordViewModel + ) { + _viewModel = StateObject(wrappedValue: viewModel) + } + + var body: some View { + Text("SignupPasswordView") + } +} diff --git a/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordViewModel.swift b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordViewModel.swift new file mode 100644 index 0000000..3205e4c --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordViewModel.swift @@ -0,0 +1,5 @@ +import BaseFeature +import Combine + +final class SignupPasswordViewModel: BaseViewModel { +} diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelComponent.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelComponent.swift new file mode 100644 index 0000000..e16a0ef --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelComponent.swift @@ -0,0 +1,14 @@ +import SwiftUI +import NeedleFoundation +import SignupCheckLevelFeatureInterface + +public protocol SignupCheckLevelDependency: Dependency { +} + +public final class SignupCheckLevelComponent: Component, SignupCheckLevelFactory { + public func makeView() -> some View { + SignupCheckLevelView( + viewModel: .init() + ) + } +} diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelView.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelView.swift new file mode 100644 index 0000000..a22e4f7 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelView.swift @@ -0,0 +1,17 @@ +import DesignSystem +import SwiftUI +import BaseFeature + +struct SignupCheckLevelView: View { + @StateObject var viewModel: SignupCheckLevelViewModel + + init( + viewModel: SignupCheckLevelViewModel + ) { + _viewModel = StateObject(wrappedValue: viewModel) + } + + var body: some View { + Text("SignupCheckLevelView") + } +} diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelViewModel.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelViewModel.swift new file mode 100644 index 0000000..ec2fb1c --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelViewModel.swift @@ -0,0 +1,5 @@ +import BaseFeature +import Combine + +final class SignupCheckLevelViewModel: BaseViewModel { +} diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderComponent.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderComponent.swift new file mode 100644 index 0000000..2119a61 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderComponent.swift @@ -0,0 +1,14 @@ +import SwiftUI +import NeedleFoundation +import SignupGenderFeatureInterface + +public protocol SignupGenderDependency: Dependency { +} + +public final class SignupGenderComponent: Component, SignupGenderFactory { + public func makeView() -> some View { + SignupGenderView( + viewModel: .init() + ) + } +} diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderView.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderView.swift new file mode 100644 index 0000000..0688d90 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderView.swift @@ -0,0 +1,17 @@ +import DesignSystem +import SwiftUI +import BaseFeature + +struct SignupGenderView: View { + @StateObject var viewModel: SignupGenderViewModel + + init( + viewModel: SignupGenderViewModel + ) { + _viewModel = StateObject(wrappedValue: viewModel) + } + + var body: some View { + Text("SignupGenderView") + } +} diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderViewModel.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderViewModel.swift new file mode 100644 index 0000000..39d233a --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderViewModel.swift @@ -0,0 +1,5 @@ +import BaseFeature +import Combine + +final class SignupGenderViewModel: BaseViewModel { +} diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameComponent.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameComponent.swift new file mode 100644 index 0000000..e22676b --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameComponent.swift @@ -0,0 +1,14 @@ +import SwiftUI +import NeedleFoundation +import SignupNameFeatureInterface + +public protocol SignupNameDependency: Dependency { +} + +public final class SignupNameComponent: Component, SignupNameFactory { + public func makeView() -> some View { + SignupNameView( + viewModel: .init() + ) + } +} diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameView.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameView.swift new file mode 100644 index 0000000..64d13b3 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameView.swift @@ -0,0 +1,17 @@ +import DesignSystem +import SwiftUI +import BaseFeature + +struct SignupNameView: View { + @StateObject var viewModel: SignupNameViewModel + + init( + viewModel: SignupNameViewModel + ) { + _viewModel = StateObject(wrappedValue: viewModel) + } + + var body: some View { + Text("SignupNameView") + } +} diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameViewModel.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameViewModel.swift new file mode 100644 index 0000000..18d6554 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameViewModel.swift @@ -0,0 +1,5 @@ +import BaseFeature +import Combine + +final class SignupNameViewModel: BaseViewModel { +} diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDComponent.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDComponent.swift new file mode 100644 index 0000000..62e1fcd --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDComponent.swift @@ -0,0 +1,14 @@ +import SwiftUI +import NeedleFoundation +import SignupStudentIDFeatureInterface + +public protocol SignupStudentIDDependency: Dependency { +} + +public final class SignupStudentIDComponent: Component, SignupStudentIDFactory { + public func makeView() -> some View { + SignupStudentIDView( + viewModel: .init() + ) + } +} diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDView.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDView.swift new file mode 100644 index 0000000..f6b2d27 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDView.swift @@ -0,0 +1,17 @@ +import DesignSystem +import SwiftUI +import BaseFeature + +struct SignupStudentIDView: View { + @StateObject var viewModel: SignupStudentIDViewModel + + init( + viewModel: SignupStudentIDViewModel + ) { + _viewModel = StateObject(wrappedValue: viewModel) + } + + var body: some View { + Text("SignupStudentIDView") + } +} diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDViewModel.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDViewModel.swift new file mode 100644 index 0000000..7f3bc1c --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDViewModel.swift @@ -0,0 +1,5 @@ +import BaseFeature +import Combine + +final class SignupStudentIDViewModel: BaseViewModel { +} diff --git a/Projects/Feature/SignupFeature/Tests/SignupFeatureTest.swift b/Projects/Feature/SignupFeature/Tests/SignupFeatureTest.swift new file mode 100644 index 0000000..a53574c --- /dev/null +++ b/Projects/Feature/SignupFeature/Tests/SignupFeatureTest.swift @@ -0,0 +1,11 @@ +import XCTest + +final class SignupFeatureTests: XCTestCase { + override func setUpWithError() throws {} + + override func tearDownWithError() throws {} + + func testExample() { + XCTAssertEqual(1, 1) + } +} From cbf0ee05b2b8150b39db8a1cd86f58ffeae04e3c Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 09:43:58 +0900 Subject: [PATCH 03/33] =?UTF-8?q?=E2=9C=A8=20::=20App=20State=20Property?= =?UTF-8?q?=20wrapper=EB=A1=9C=20=EA=B0=90=EC=8B=B8=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Application/KillerGramApp.swift | 2 +- .../BaseFeature/Sources/AppState.swift | 24 ++++++++++++++++--- Projects/Feature/RootFeature/Project.swift | 5 +++- .../RootFeature/Sources/RootView.swift | 2 +- Projects/Feature/SigninFeature/Project.swift | 3 ++- Projects/Feature/SplashFeature/Project.swift | 4 +++- .../SplashFeature/Sources/SplashView.swift | 2 +- 7 files changed, 33 insertions(+), 9 deletions(-) diff --git a/Projects/App/Sources/Application/KillerGramApp.swift b/Projects/App/Sources/Application/KillerGramApp.swift index 2706f34..7fafa60 100644 --- a/Projects/App/Sources/Application/KillerGramApp.swift +++ b/Projects/App/Sources/Application/KillerGramApp.swift @@ -5,7 +5,7 @@ import ViewUtil @main struct KillerGramApp: App { - @StateObject var appState = AppState(sceneFlow: .splash) + @ObservedObject var appState = AppStateProvider(sceneFlow: .splash, rule: .student) init() { DesignSystemFontFamily.registerAllCustomFonts() diff --git a/Projects/Feature/BaseFeature/Sources/AppState.swift b/Projects/Feature/BaseFeature/Sources/AppState.swift index eac627c..12309d4 100644 --- a/Projects/Feature/BaseFeature/Sources/AppState.swift +++ b/Projects/Feature/BaseFeature/Sources/AppState.swift @@ -1,9 +1,27 @@ -import Foundation +import SwiftUI -public final class AppState: ObservableObject { +@propertyWrapper +public struct AppState: DynamicProperty { + @EnvironmentObject private var object: AppStateProvider + + public var wrappedValue: AppStateProvider { + object + } + + public init() { } +} + +public final class AppStateProvider: ObservableObject { @Published public var sceneFlow: SceneFlow + @Published public var rule: RuleExample - public init(sceneFlow: SceneFlow) { + public init(sceneFlow: SceneFlow, rule: RuleExample) { self.sceneFlow = sceneFlow + self.rule = rule } } + +public enum RuleExample { + case student + case manager +} diff --git a/Projects/Feature/RootFeature/Project.swift b/Projects/Feature/RootFeature/Project.swift index fdeb449..9269898 100644 --- a/Projects/Feature/RootFeature/Project.swift +++ b/Projects/Feature/RootFeature/Project.swift @@ -8,7 +8,10 @@ let project = Project.module( .interface(module: .feature(.RootFeature)), .implements(module: .feature(.RootFeature), dependencies: [ .feature(target: .RootFeature, type: .interface), - .feature(target: .BaseFeature) + .feature(target: .BaseFeature), + .feature(target: .SigninFeature, type: .interface), +// .feature(target: .MainFeature, type: .interface), + .feature(target: .SplashFeature, type: .interface) ]), .tests(module: .feature(.RootFeature), dependencies: [ .feature(target: .RootFeature) diff --git a/Projects/Feature/RootFeature/Sources/RootView.swift b/Projects/Feature/RootFeature/Sources/RootView.swift index 0b3506c..dbb5a9d 100644 --- a/Projects/Feature/RootFeature/Sources/RootView.swift +++ b/Projects/Feature/RootFeature/Sources/RootView.swift @@ -6,7 +6,7 @@ import SigninFeatureInterface import ViewUtil struct RootView: View { - @EnvironmentObject var appState: AppState + @AppState var appState private let splashFactory: any SplashFactory private let signinFactory: any SigninFactory diff --git a/Projects/Feature/SigninFeature/Project.swift b/Projects/Feature/SigninFeature/Project.swift index ffa379d..7bde5f1 100644 --- a/Projects/Feature/SigninFeature/Project.swift +++ b/Projects/Feature/SigninFeature/Project.swift @@ -8,7 +8,8 @@ let project = Project.module( .interface(module: .feature(.SigninFeature)), .implements(module: .feature(.SigninFeature), dependencies: [ .feature(target: .SigninFeature, type: .interface), - .feature(target: .BaseFeature) + .feature(target: .BaseFeature), + .feature(target: .SignupFeature, type: .interface) ]), .tests(module: .feature(.SigninFeature), dependencies: [ .feature(target: .SigninFeature) diff --git a/Projects/Feature/SplashFeature/Project.swift b/Projects/Feature/SplashFeature/Project.swift index 8a0dcda..783d636 100644 --- a/Projects/Feature/SplashFeature/Project.swift +++ b/Projects/Feature/SplashFeature/Project.swift @@ -8,7 +8,9 @@ let project = Project.module( .interface(module: .feature(.SplashFeature)), .implements(module: .feature(.SplashFeature), dependencies: [ .feature(target: .SplashFeature, type: .interface), - .feature(target: .BaseFeature) + .feature(target: .BaseFeature), + .feature(target: .SigninFeature, type: .interface), +// .feature(target: .MainFeature, type: .interface) ]), .tests(module: .feature(.SplashFeature), dependencies: [ .feature(target: .SplashFeature) diff --git a/Projects/Feature/SplashFeature/Sources/SplashView.swift b/Projects/Feature/SplashFeature/Sources/SplashView.swift index eabbef6..fdc6931 100644 --- a/Projects/Feature/SplashFeature/Sources/SplashView.swift +++ b/Projects/Feature/SplashFeature/Sources/SplashView.swift @@ -4,7 +4,7 @@ import BaseFeature struct SplashView: View { @StateObject var viewModel: SplashViewModel - @EnvironmentObject var appState: AppState + @AppState var appState init( viewModel: SplashViewModel From ca6d8b5a4234468f43d3eac3f31d7a76e133fd40 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 11:56:50 +0900 Subject: [PATCH 04/33] =?UTF-8?q?=E2=9C=A8=20::=20Signup=20View=20DI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Application/DI/AppComponent.swift | 24 +++ .../Sources/Application/NeedleGenerated.swift | 148 +++++++++++++++++- 2 files changed, 164 insertions(+), 8 deletions(-) diff --git a/Projects/App/Sources/Application/DI/AppComponent.swift b/Projects/App/Sources/Application/DI/AppComponent.swift index 20109cb..9ffdf3a 100644 --- a/Projects/App/Sources/Application/DI/AppComponent.swift +++ b/Projects/App/Sources/Application/DI/AppComponent.swift @@ -6,6 +6,8 @@ import SplashFeature import SplashFeatureInterface import SigninFeature import SigninFeatureInterface +import SignupFeature +import SignupFeatureInterface public final class AppComponent: BootstrapComponent { // private let _keychain: any Keychain @@ -36,4 +38,26 @@ public extension AppComponent { var signinFactory: any SigninFactory { SigninComponent(parent: self) } + // Signup + var signupEmailVerifyFactory: any SignupEmailVerifyFactory { + SignupEmailVerifyComponent(parent: self) + } + var signupEmailAuthCodeVerifyFactory: any SignupEmailAuthCodeVerifyFactory { + SignupEmailAuthCodeVerifyComponent(parent: self) + } + var signupPasswordFactory: any SignupPasswordFactory { + SignupPasswordComponent(parent: self) + } + var signupNameFactory: any SignupNameFactory { + SignupNameComponent(parent: self) + } + var signupStudentIDFactory: any SignupStudentIDFactory { + SignupStudentIDComponent(parent: self) + } + var signupGenderFactory: any SignupGenderFactory { + SignupGenderComponent(parent: self) + } + var signupCheckLevelFactory: any SignupCheckLevelFactory { + SignupCheckLevelComponent(parent: self) + } } diff --git a/Projects/App/Sources/Application/NeedleGenerated.swift b/Projects/App/Sources/Application/NeedleGenerated.swift index d1dac6a..0a97543 100644 --- a/Projects/App/Sources/Application/NeedleGenerated.swift +++ b/Projects/App/Sources/Application/NeedleGenerated.swift @@ -5,6 +5,8 @@ import RootFeature import RootFeatureInterface import SigninFeature import SigninFeatureInterface +import SignupFeature +import SignupFeatureInterface import SplashFeature import SplashFeatureInterface import SwiftUI @@ -33,6 +35,85 @@ private class SplashDependencye0cb7136f2ec3edfd60aProvider: SplashDependency { private func factoryace9f05f51d68f4c0677e3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { return SplashDependencye0cb7136f2ec3edfd60aProvider() } +private class SignupPasswordDependency778bf5389a70d7df6152Provider: SignupPasswordDependency { + + + init() { + + } +} +/// ^->AppComponent->SignupPasswordComponent +private func factorye93d1d56840ff97c674ae3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { + return SignupPasswordDependency778bf5389a70d7df6152Provider() +} +private class SignupEmailAuthCodeVerifyDependencyaf9da1ebf0e9e5f1b708Provider: SignupEmailAuthCodeVerifyDependency { + + + init() { + + } +} +/// ^->AppComponent->SignupEmailAuthCodeVerifyComponent +private func factoryb06be35aa893adde971be3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { + return SignupEmailAuthCodeVerifyDependencyaf9da1ebf0e9e5f1b708Provider() +} +private class SignupStudentIDDependencyc62f548e51245f5bf42dProvider: SignupStudentIDDependency { + + + init() { + + } +} +/// ^->AppComponent->SignupStudentIDComponent +private func factorycca12bec445b4f4f6de7e3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { + return SignupStudentIDDependencyc62f548e51245f5bf42dProvider() +} +private class SignupGenderDependency65e2a6565372eb41f4acProvider: SignupGenderDependency { + + + init() { + + } +} +/// ^->AppComponent->SignupGenderComponent +private func factory997eaa831d16af15eee5e3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { + return SignupGenderDependency65e2a6565372eb41f4acProvider() +} +private class SignupCheckLevelDependencye4ec84c7d38354a454aeProvider: SignupCheckLevelDependency { + + + init() { + + } +} +/// ^->AppComponent->SignupCheckLevelComponent +private func factory5b23127e837152346fdae3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { + return SignupCheckLevelDependencye4ec84c7d38354a454aeProvider() +} +private class SignupNameDependency860534ba64c054146b7bProvider: SignupNameDependency { + + + init() { + + } +} +/// ^->AppComponent->SignupNameComponent +private func factory71e8fa7f4327b1e25ed0e3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { + return SignupNameDependency860534ba64c054146b7bProvider() +} +private class SignupEmailVerifyDependencyf9d372ac752ee19b78caProvider: SignupEmailVerifyDependency { + var signupEmailAuthCodeVerifyFactory: any SignupEmailAuthCodeVerifyFactory { + return appComponent.signupEmailAuthCodeVerifyFactory + } + private let appComponent: AppComponent + init(appComponent: AppComponent) { + self.appComponent = appComponent + } +} +/// ^->AppComponent->SignupEmailVerifyComponent +private func factory3b1904c76335d70151ebf47b58f8f304c97af4d5(_ component: NeedleFoundation.Scope) -> AnyObject { + return SignupEmailVerifyDependencyf9d372ac752ee19b78caProvider(appComponent: parent1(component) as! AppComponent) +} private class RootDependency3944cc797a4a88956fb5Provider: RootDependency { var splashFactory: any SplashFactory { return appComponent.splashFactory @@ -50,15 +131,17 @@ private func factory264bfc4d4cb6b0629b40f47b58f8f304c97af4d5(_ component: Needle return RootDependency3944cc797a4a88956fb5Provider(appComponent: parent1(component) as! AppComponent) } private class SigninDependencyde06a9d0b22764487733Provider: SigninDependency { - - - init() { - + var signupEmailVerifyFactory: any SignupEmailVerifyFactory { + return appComponent.signupEmailVerifyFactory + } + private let appComponent: AppComponent + init(appComponent: AppComponent) { + self.appComponent = appComponent } } /// ^->AppComponent->SigninComponent -private func factory2882a056d84a613debcce3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { - return SigninDependencyde06a9d0b22764487733Provider() +private func factory2882a056d84a613debccf47b58f8f304c97af4d5(_ component: NeedleFoundation.Scope) -> AnyObject { + return SigninDependencyde06a9d0b22764487733Provider(appComponent: parent1(component) as! AppComponent) } #else @@ -67,6 +150,13 @@ extension AppComponent: Registration { localTable["splashFactory-any SplashFactory"] = { [unowned self] in self.splashFactory as Any } localTable["signinFactory-any SigninFactory"] = { [unowned self] in self.signinFactory as Any } + localTable["signupEmailVerifyFactory-any SignupEmailVerifyFactory"] = { [unowned self] in self.signupEmailVerifyFactory as Any } + localTable["signupEmailAuthCodeVerifyFactory-any SignupEmailAuthCodeVerifyFactory"] = { [unowned self] in self.signupEmailAuthCodeVerifyFactory as Any } + localTable["signupPasswordFactory-any SignupPasswordFactory"] = { [unowned self] in self.signupPasswordFactory as Any } + localTable["signupNameFactory-any SignupNameFactory"] = { [unowned self] in self.signupNameFactory as Any } + localTable["signupStudentIDFactory-any SignupStudentIDFactory"] = { [unowned self] in self.signupStudentIDFactory as Any } + localTable["signupGenderFactory-any SignupGenderFactory"] = { [unowned self] in self.signupGenderFactory as Any } + localTable["signupCheckLevelFactory-any SignupCheckLevelFactory"] = { [unowned self] in self.signupCheckLevelFactory as Any } } } extension SplashComponent: Registration { @@ -74,6 +164,41 @@ extension SplashComponent: Registration { } } +extension SignupPasswordComponent: Registration { + public func registerItems() { + + } +} +extension SignupEmailAuthCodeVerifyComponent: Registration { + public func registerItems() { + + } +} +extension SignupStudentIDComponent: Registration { + public func registerItems() { + + } +} +extension SignupGenderComponent: Registration { + public func registerItems() { + + } +} +extension SignupCheckLevelComponent: Registration { + public func registerItems() { + + } +} +extension SignupNameComponent: Registration { + public func registerItems() { + + } +} +extension SignupEmailVerifyComponent: Registration { + public func registerItems() { + keyPathToName[\SignupEmailVerifyDependency.signupEmailAuthCodeVerifyFactory] = "signupEmailAuthCodeVerifyFactory-any SignupEmailAuthCodeVerifyFactory" + } +} extension RootComponent: Registration { public func registerItems() { keyPathToName[\RootDependency.splashFactory] = "splashFactory-any SplashFactory" @@ -82,7 +207,7 @@ extension RootComponent: Registration { } extension SigninComponent: Registration { public func registerItems() { - + keyPathToName[\SigninDependency.signupEmailVerifyFactory] = "signupEmailVerifyFactory-any SignupEmailVerifyFactory" } } @@ -103,8 +228,15 @@ private func registerProviderFactory(_ componentPath: String, _ factory: @escapi @inline(never) private func register1() { registerProviderFactory("^->AppComponent", factoryEmptyDependencyProvider) registerProviderFactory("^->AppComponent->SplashComponent", factoryace9f05f51d68f4c0677e3b0c44298fc1c149afb) + registerProviderFactory("^->AppComponent->SignupPasswordComponent", factorye93d1d56840ff97c674ae3b0c44298fc1c149afb) + registerProviderFactory("^->AppComponent->SignupEmailAuthCodeVerifyComponent", factoryb06be35aa893adde971be3b0c44298fc1c149afb) + registerProviderFactory("^->AppComponent->SignupStudentIDComponent", factorycca12bec445b4f4f6de7e3b0c44298fc1c149afb) + registerProviderFactory("^->AppComponent->SignupGenderComponent", factory997eaa831d16af15eee5e3b0c44298fc1c149afb) + registerProviderFactory("^->AppComponent->SignupCheckLevelComponent", factory5b23127e837152346fdae3b0c44298fc1c149afb) + registerProviderFactory("^->AppComponent->SignupNameComponent", factory71e8fa7f4327b1e25ed0e3b0c44298fc1c149afb) + registerProviderFactory("^->AppComponent->SignupEmailVerifyComponent", factory3b1904c76335d70151ebf47b58f8f304c97af4d5) registerProviderFactory("^->AppComponent->RootComponent", factory264bfc4d4cb6b0629b40f47b58f8f304c97af4d5) - registerProviderFactory("^->AppComponent->SigninComponent", factory2882a056d84a613debcce3b0c44298fc1c149afb) + registerProviderFactory("^->AppComponent->SigninComponent", factory2882a056d84a613debccf47b58f8f304c97af4d5) } #endif From 36403cf0d135afecf68a0ada92fd6819f0521cb6 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 11:57:34 +0900 Subject: [PATCH 05/33] =?UTF-8?q?=E2=9C=A8=20::=20navigate=20func=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ViewUtil/Sources/View+navigate.swift | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 Projects/Shared/ViewUtil/Sources/View+navigate.swift diff --git a/Projects/Shared/ViewUtil/Sources/View+navigate.swift b/Projects/Shared/ViewUtil/Sources/View+navigate.swift new file mode 100644 index 0000000..1ca6b8b --- /dev/null +++ b/Projects/Shared/ViewUtil/Sources/View+navigate.swift @@ -0,0 +1,40 @@ +import SwiftUI + +public extension View { + func navigate( + to view: NewView, + when binding: Binding + ) -> some View { + self.background { + NavigationLink(isActive: binding) { + DeferView { + view + } + } label: { + EmptyView() + } + } + } +} + +public struct DeferView: View { + let content: () -> Content + + public init( + @ViewBuilder _ content: @escaping () -> Content + ) { + self.content = content + } + + public var body: some View { + content() + .onAppear { + UIApplication.shared.sendAction( + #selector(UIResponder.resignFirstResponder), + to: nil, + from: nil, + for: nil + ) + } + } +} From 687c0e09e164c5764dfe311bf5d195d775d18481 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 11:58:40 +0900 Subject: [PATCH 06/33] =?UTF-8?q?=E2=9C=A8=20::=20font=20height=20setting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/TextField/KGTextField.swift | 16 +++++++++------- .../Sources/Typograpy/KGFont.swift | 9 +++++++++ .../Sources/Typograpy/KGFontStyle.swift | 18 +++++++++--------- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/Projects/UserInterface/DesignSystem/Sources/TextField/KGTextField.swift b/Projects/UserInterface/DesignSystem/Sources/TextField/KGTextField.swift index afcdcb3..5d6f281 100644 --- a/Projects/UserInterface/DesignSystem/Sources/TextField/KGTextField.swift +++ b/Projects/UserInterface/DesignSystem/Sources/TextField/KGTextField.swift @@ -3,11 +3,11 @@ import SwiftUI public struct KGTextField: View { // @Environment(\.isEnabled) private var isEnabled: Bool var title: String - var label: String + var placeholder: String @Binding var text: String var isError: Bool - var description: String var errorMessage: String + var description: String var onCommit: () -> Void @FocusState var isFocused: Bool private var isErrorAndNotEmpty: Bool { @@ -15,15 +15,15 @@ public struct KGTextField: View { } public init( - _ label: String = "", + _ placeholder: String = "", text: Binding, title: String = "", isError: Bool = false, - description: String = "", errorMessage: String = "", + description: String = "", onCommit: @escaping () -> Void = {} ) { - self.label = label + self.placeholder = placeholder _text = text self.title = title self.isError = isError @@ -40,7 +40,7 @@ public struct KGTextField: View { } ZStack(alignment: .leading) { - Text(label) + Text(placeholder) .kgFont(.m3, weight: .regular, color: .Grays.gray800) .opacity(text.isEmpty ? 1 : 0) @@ -49,7 +49,8 @@ public struct KGTextField: View { .focused($isFocused) .onSubmit(onCommit) } - .padding(16) + .padding(.horizontal, 16) + .frame(height: 56) .background(Color.Grays.gray1000) .clipCornerRadius(8) .overlay { @@ -67,6 +68,7 @@ public struct KGTextField: View { } .padding(.vertical, 8) .padding(.horizontal, 24) + .animation(.easeIn(duration: 0.2), value: isError) .animation(.easeIn(duration: 0.2), value: isErrorAndNotEmpty) .animation(.easeIn(duration: 0.2), value: isFocused) } diff --git a/Projects/UserInterface/DesignSystem/Sources/Typograpy/KGFont.swift b/Projects/UserInterface/DesignSystem/Sources/Typograpy/KGFont.swift index 4a16111..415b66d 100644 --- a/Projects/UserInterface/DesignSystem/Sources/Typograpy/KGFont.swift +++ b/Projects/UserInterface/DesignSystem/Sources/Typograpy/KGFont.swift @@ -3,10 +3,19 @@ import SwiftUI public struct KGFont: ViewModifier { public let style: KGFontStyle public var weight: KGFontWeight + private let lineHeight: CGFloat + + init(style: KGFontStyle, weight: KGFontWeight) { + self.style = style + self.weight = weight + self.lineHeight = weight.pretendardFont.font(size: style.size).lineHeight + } public func body(content: Content) -> some View { content .font(weight.pretendardFont.swiftUIFont(size: style.size)) + .lineSpacing(lineHeight * style.lineHeight - lineHeight) + .padding(.vertical, (lineHeight * style.lineHeight - lineHeight) / 2) } } diff --git a/Projects/UserInterface/DesignSystem/Sources/Typograpy/KGFontStyle.swift b/Projects/UserInterface/DesignSystem/Sources/Typograpy/KGFontStyle.swift index 27b0365..03eecbf 100644 --- a/Projects/UserInterface/DesignSystem/Sources/Typograpy/KGFontStyle.swift +++ b/Projects/UserInterface/DesignSystem/Sources/Typograpy/KGFontStyle.swift @@ -1,9 +1,5 @@ import SwiftUI -protocol KGFontable { - var font: Font { get } -} - public enum KGFontWeight { case semiBold case regular @@ -48,11 +44,15 @@ public enum KGFontStyle: Hashable { 14 } } -} -// MARK: - FontableSize -extension KGFontable where Self: RawRepresentable, Self.RawValue == CGFloat { - var size: CGFloat { - self.rawValue + var lineHeight: CGFloat { + switch self { + case .h1, .h2: + 1.20 + case .h3: + 1.30 + case .m1, .m2, .m3, .label: + 1.50 + } } } From 07591c79d01d128c6cbd56f8d6d40e4c532d022d Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 11:58:56 +0900 Subject: [PATCH 07/33] =?UTF-8?q?=E2=9C=A8=20::=20kg=20Background=20func?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DesignSystem/Sources/Extension/View+kgBackground.swift | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Projects/UserInterface/DesignSystem/Sources/Extension/View+kgBackground.swift diff --git a/Projects/UserInterface/DesignSystem/Sources/Extension/View+kgBackground.swift b/Projects/UserInterface/DesignSystem/Sources/Extension/View+kgBackground.swift new file mode 100644 index 0000000..b11f381 --- /dev/null +++ b/Projects/UserInterface/DesignSystem/Sources/Extension/View+kgBackground.swift @@ -0,0 +1,7 @@ +import SwiftUI + +public extension View { + func kgBackground() -> some View { + self.background(Color.System.background.ignoresSafeArea()) + } +} From 0857d6e2e7ff08ccc821bda84619ff874d91b2db Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 11:59:07 +0900 Subject: [PATCH 08/33] =?UTF-8?q?=E2=9C=A8=20::=20Button=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 --- .../Sources/Button/KGButton.swift | 6 +- .../Sources/Button/KGButtonStyle.swift | 66 +++++++------------ 2 files changed, 24 insertions(+), 48 deletions(-) diff --git a/Projects/UserInterface/DesignSystem/Sources/Button/KGButton.swift b/Projects/UserInterface/DesignSystem/Sources/Button/KGButton.swift index 04a3a93..66dda84 100644 --- a/Projects/UserInterface/DesignSystem/Sources/Button/KGButton.swift +++ b/Projects/UserInterface/DesignSystem/Sources/Button/KGButton.swift @@ -2,18 +2,15 @@ import SwiftUI public struct KGButton: View { let text: String - let style: KGButtonStyle.Style let isEditing: Bool let action: () -> Void public init( text: String, - style: KGButtonStyle.Style = .green, isEditing: Bool = false, action: @escaping () -> Void = {} ) { self.text = text - self.style = style self.isEditing = isEditing self.action = action } @@ -23,8 +20,9 @@ public struct KGButton: View { Text(text) .multilineTextAlignment(.center) } - .kgStyle(style, isEditing: isEditing) + .kgStyle(isEditing: isEditing) .padding(.vertical, isEditing ? 0 : 16) .padding(.horizontal, isEditing ? 0 : 24) + .animation(.easeIn(duration: 0.2), value: isEditing) } } diff --git a/Projects/UserInterface/DesignSystem/Sources/Button/KGButtonStyle.swift b/Projects/UserInterface/DesignSystem/Sources/Button/KGButtonStyle.swift index 9a1b591..ca8465a 100644 --- a/Projects/UserInterface/DesignSystem/Sources/Button/KGButtonStyle.swift +++ b/Projects/UserInterface/DesignSystem/Sources/Button/KGButtonStyle.swift @@ -2,22 +2,16 @@ import SwiftUI // MARK: - Usage extension Button { - func kgStyle(_ style: KGButtonStyle.Style, isEditing: Bool) -> some View { - self.buttonStyle(KGButtonStyle(style: style, isEditing: isEditing)) + func kgStyle(isEditing: Bool) -> some View { + self.buttonStyle(KGButtonStyle(isEditing: isEditing)) } } public struct KGButtonStyle: ButtonStyle { - public enum Style { - case green - case black - } - - let style: Style let isEditing: Bool public func makeBody(configuration: Configuration) -> some View { - AnyView(KGButton(configuration: configuration, style: style, isEditing: isEditing)) + AnyView(KGButton(configuration: configuration, isEditing: isEditing)) } } @@ -25,7 +19,6 @@ public struct KGButtonStyle: ButtonStyle { extension KGButtonStyle { struct KGButton: View { let configuration: ButtonStyle.Configuration - let style: Style let isEditing: Bool @Environment(\.isEnabled) private var isEnabled: Bool @@ -34,47 +27,32 @@ extension KGButtonStyle { .kgFont( .m3, weight: .semiBold, - color: configuration.isPressed ? style.pressedForeground : style.foreground + color: isEnabled ? + configuration.isPressed ? + pressedForeground : + enableForeground : + disabledForeground ) .padding(.vertical, 16) .frame(maxWidth: .infinity) - .background(configuration.isPressed ? style.pressedBackground : style.background) + .background( + isEnabled ? + configuration.isPressed ? + pressedBackground : + enableBackground : + disabledBackground + ) .clipCornerRadius(isEditing ? 0 : 8) } } } // Color Setting -private extension KGButtonStyle.Style { - var background: Color { - switch self { - case .green: - Color.Greens.main - case .black: - Color.Grays.gray1000 - } - } - - var foreground: Color { - switch self { - case .green: - Color.Greens.secondary - case .black: - Color.Grays.gray700 - } - } - - var pressedBackground: Color { - switch self { - default: - Color.Greens.secondary - } - } - - var pressedForeground: Color { - switch self { - default: - Color.Grays.gray100 - } - } +private extension KGButtonStyle { + static var enableBackground: Color { .Greens.main } + static var enableForeground: Color { .Greens.secondary } + static var pressedBackground: Color { .Greens.secondary } + static var pressedForeground: Color { .Grays.gray100 } + static var disabledBackground: Color { .Grays.gray1000 } + static var disabledForeground: Color { .Grays.gray700 } } From 71ff66656d7532b76be5500cd4ae320eebca6a4c Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 11:59:20 +0900 Subject: [PATCH 09/33] =?UTF-8?q?=E2=9C=A8=20::=20navigation=20Bar=20Syste?= =?UTF-8?q?m?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Extension/View+navigationBar.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Projects/UserInterface/DesignSystem/Sources/Extension/View+navigationBar.swift b/Projects/UserInterface/DesignSystem/Sources/Extension/View+navigationBar.swift index bee01cb..e0ca7b4 100644 --- a/Projects/UserInterface/DesignSystem/Sources/Extension/View+navigationBar.swift +++ b/Projects/UserInterface/DesignSystem/Sources/Extension/View+navigationBar.swift @@ -43,12 +43,11 @@ public struct NavigationBarModifier: ViewModifier { } } } - .frame(height: 68) + .frame(height: 64) .padding(.horizontal, 12) Text(navigationTitle) .kgFont(.m2, weight: .semiBold, color: .Grays.white) - .padding(.vertical, 10) .frame(maxWidth: .infinity) } .background(Color.System.background.ignoresSafeArea(edges: .top)) @@ -61,7 +60,7 @@ public struct NavigationBarModifier: ViewModifier { } public extension View { - func setNavigationBar( + func navigationBar( navigationTitle: String, hasBackButton: Bool = false, rightIcon: (Icons, () -> Void)? = nil @@ -75,7 +74,7 @@ public extension View { ) } - func setNavigationBackButton( + func navigationBackButton( navigationTitle: String = "" ) -> some View { modifier( From 6a73e88f175f79bdfdb04d68bd210d7ce4e35cc4 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 12:00:04 +0900 Subject: [PATCH 10/33] =?UTF-8?q?=E2=9C=A8=20::=20Root=20view=20Navigation?= =?UTF-8?q?View=20=EB=A1=9C=20=EA=B0=90=EC=8C=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RootFeature/Sources/RootView.swift | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Projects/Feature/RootFeature/Sources/RootView.swift b/Projects/Feature/RootFeature/Sources/RootView.swift index dbb5a9d..cca4fb2 100644 --- a/Projects/Feature/RootFeature/Sources/RootView.swift +++ b/Projects/Feature/RootFeature/Sources/RootView.swift @@ -19,23 +19,25 @@ struct RootView: View { } var body: some View { - ZStack { - switch appState.sceneFlow { - case .auth: - signinFactory.makeView().eraseToAnyView() - .environmentObject(appState) + NavigationView { + ZStack { + switch appState.sceneFlow { + case .auth: + signinFactory.makeView().eraseToAnyView() + .environmentObject(appState) - case .main: - EmptyView() - .environmentObject(appState) + case .main: + EmptyView() + .environmentObject(appState) - case .splash: - splashFactory.makeView().eraseToAnyView() - .environmentObject(appState) + case .splash: + splashFactory.makeView().eraseToAnyView() + .environmentObject(appState) + } } + .background(Color.System.background.ignoresSafeArea()) + .animation(.easeInOut, value: appState.sceneFlow) + .transition(.opacity.animation(.easeInOut)) } - .background(Color.System.background.ignoresSafeArea()) - .animation(.easeInOut, value: appState.sceneFlow) - .transition(.opacity.animation(.easeInOut)) } } From 06a7ef1c5189f5231846ddcd901003cedefc5f8b Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 12:01:07 +0900 Subject: [PATCH 11/33] =?UTF-8?q?=E2=9C=A8=20::=20hideKeyboard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BaseFeature/Sources/HideKeyboard.swift | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Projects/Feature/BaseFeature/Sources/HideKeyboard.swift diff --git a/Projects/Feature/BaseFeature/Sources/HideKeyboard.swift b/Projects/Feature/BaseFeature/Sources/HideKeyboard.swift new file mode 100644 index 0000000..6280557 --- /dev/null +++ b/Projects/Feature/BaseFeature/Sources/HideKeyboard.swift @@ -0,0 +1,30 @@ +import SwiftUI +import UIKit + +public extension View { + func hideKeyboardWhenTap() -> some View { + onAppear(perform: UIApplication.shared.hideKeyboard) + } +} + +public extension UIApplication { + func hideKeyboard() { + guard + let scene = connectedScenes.first as? UIWindowScene, + let window = scene.windows.first + else { return } + let tapRecognizer = UITapGestureRecognizer(target: window, action: #selector(UIView.endEditing)) + tapRecognizer.cancelsTouchesInView = false + tapRecognizer.delegate = self + window.addGestureRecognizer(tapRecognizer) + } +} + +extension UIApplication: UIGestureRecognizerDelegate { + public func gestureRecognizer( + _ gestureRecognizer: UIGestureRecognizer, + shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer + ) -> Bool { + return false + } +} From 13a9fff00c8a83eaf0f79022fff36259b3cc2b79 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 12:03:08 +0900 Subject: [PATCH 12/33] =?UTF-8?q?=E2=9C=A8=20::=20Signin=20to=20Signup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SigninFeature/Sources/SigninComponent.swift | 5 ++++- .../SigninFeature/Sources/SigninView.swift | 15 ++++++++++++--- .../SigninFeature/Sources/SigninViewModel.swift | 6 ++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Projects/Feature/SigninFeature/Sources/SigninComponent.swift b/Projects/Feature/SigninFeature/Sources/SigninComponent.swift index 513c831..93828b4 100644 --- a/Projects/Feature/SigninFeature/Sources/SigninComponent.swift +++ b/Projects/Feature/SigninFeature/Sources/SigninComponent.swift @@ -1,14 +1,17 @@ import SwiftUI import NeedleFoundation import SigninFeatureInterface +import SignupFeatureInterface public protocol SigninDependency: Dependency { + var signupEmailVerifyFactory: any SignupEmailVerifyFactory { get } } public final class SigninComponent: Component, SigninFactory { public func makeView() -> some View { SigninView( - viewModel: .init() + viewModel: .init(), + signupEmailVerifyFactory: dependency.signupEmailVerifyFactory ) } } diff --git a/Projects/Feature/SigninFeature/Sources/SigninView.swift b/Projects/Feature/SigninFeature/Sources/SigninView.swift index 852de77..61caa70 100644 --- a/Projects/Feature/SigninFeature/Sources/SigninView.swift +++ b/Projects/Feature/SigninFeature/Sources/SigninView.swift @@ -1,6 +1,8 @@ import DesignSystem import SwiftUI import BaseFeature +import ViewUtil +import SignupFeatureInterface struct SigninView: View { private enum FocusField { @@ -10,10 +12,14 @@ struct SigninView: View { @FocusState private var focusField: FocusField? @StateObject var viewModel: SigninViewModel + private let signupEmailVerifyFactory: any SignupEmailVerifyFactory + init( - viewModel: SigninViewModel + viewModel: SigninViewModel, + signupEmailVerifyFactory: any SignupEmailVerifyFactory ) { _viewModel = StateObject(wrappedValue: viewModel) + self.signupEmailVerifyFactory = signupEmailVerifyFactory } var body: some View { @@ -49,8 +55,10 @@ struct SigninView: View { ) HStack(spacing: 16) { - Text("회원가입") - .kgFont(.label, weight: .regular, color: .Grays.gray700) + Button(action: viewModel.signupButtonDidTap) { + Text("회원가입") + .kgFont(.label, weight: .regular, color: .Grays.gray700) + } Color.Grays.gray700 .frame(width: 1, height: 16) @@ -62,5 +70,6 @@ struct SigninView: View { Spacer() } + .navigate(to: signupEmailVerifyFactory.makeView().eraseToAnyView(), when: $viewModel.isNavigatedToSignup) } } diff --git a/Projects/Feature/SigninFeature/Sources/SigninViewModel.swift b/Projects/Feature/SigninFeature/Sources/SigninViewModel.swift index 2afb062..ca3ec76 100644 --- a/Projects/Feature/SigninFeature/Sources/SigninViewModel.swift +++ b/Projects/Feature/SigninFeature/Sources/SigninViewModel.swift @@ -5,7 +5,13 @@ final class SigninViewModel: BaseViewModel { @Published var email: String = "" @Published var password: String = "" + @Published var isNavigatedToSignup: Bool = false + func signinButtonDidTap() { print("Signin") } + + func signupButtonDidTap() { + self.isNavigatedToSignup = true + } } From 48f41d40d9b6ad79ffafa5a9db5a873ecb491839 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 12:03:26 +0900 Subject: [PATCH 13/33] =?UTF-8?q?=E2=9C=A8=20::=20SignupNavigation=20Title?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/NavigationTitleView.swift | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Projects/Feature/SignupFeature/Sources/Components/NavigationTitleView.swift diff --git a/Projects/Feature/SignupFeature/Sources/Components/NavigationTitleView.swift b/Projects/Feature/SignupFeature/Sources/Components/NavigationTitleView.swift new file mode 100644 index 0000000..6d6d621 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/Components/NavigationTitleView.swift @@ -0,0 +1,20 @@ +import SwiftUI +import DesignSystem + +struct NavigationTitleView: View { + let title: String + let description: String + + var body: some View { + VStack(alignment: .leading, spacing: 8) { + Text(title) + .kgFont(.h3, weight: .semiBold, color: .white) + + Text(description) + .kgFont(.m3, weight: .regular, color: .Grays.gray600) + } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.vertical, 20) + .padding(.horizontal, 24) + } +} From 5fef594154215c63e909d03d2e5211903bc65ba6 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 12:04:06 +0900 Subject: [PATCH 14/33] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20SignupFeatureIn?= =?UTF-8?q?terface=20Dependency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Password/SignupPasswordComponent.swift | 2 +- .../Sources/UserInfo/CheckLevel/SignupCheckLevelComponent.swift | 2 +- .../Sources/UserInfo/Gender/SignupGenderComponent.swift | 2 +- .../Sources/UserInfo/Name/SignupNameComponent.swift | 2 +- .../Sources/UserInfo/StudentID/SignupStudentIDComponent.swift | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordComponent.swift b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordComponent.swift index 43e7f04..26287d0 100644 --- a/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordComponent.swift +++ b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordComponent.swift @@ -1,6 +1,6 @@ import SwiftUI import NeedleFoundation -import SignupPasswordFeatureInterface +import SignupFeatureInterface public protocol SignupPasswordDependency: Dependency { } diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelComponent.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelComponent.swift index e16a0ef..f677aec 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelComponent.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelComponent.swift @@ -1,6 +1,6 @@ import SwiftUI import NeedleFoundation -import SignupCheckLevelFeatureInterface +import SignupFeatureInterface public protocol SignupCheckLevelDependency: Dependency { } diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderComponent.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderComponent.swift index 2119a61..0e97d2e 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderComponent.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderComponent.swift @@ -1,6 +1,6 @@ import SwiftUI import NeedleFoundation -import SignupGenderFeatureInterface +import SignupFeatureInterface public protocol SignupGenderDependency: Dependency { } diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameComponent.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameComponent.swift index e22676b..b395b93 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameComponent.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameComponent.swift @@ -1,6 +1,6 @@ import SwiftUI import NeedleFoundation -import SignupNameFeatureInterface +import SignupFeatureInterface public protocol SignupNameDependency: Dependency { } diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDComponent.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDComponent.swift index 62e1fcd..5d28f38 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDComponent.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDComponent.swift @@ -1,6 +1,6 @@ import SwiftUI import NeedleFoundation -import SignupStudentIDFeatureInterface +import SignupFeatureInterface public protocol SignupStudentIDDependency: Dependency { } From 117f02d5a826af0a58ca6c0b1c9df0ee8961fb69 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Wed, 24 Apr 2024 12:04:37 +0900 Subject: [PATCH 15/33] =?UTF-8?q?=E2=9C=A8=20::=20SignupEmailVerify=20Publ?= =?UTF-8?q?ishing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SignupEmailAuthCodeVerifyComponent.swift | 5 ++- .../SignupEmailVerifyComponent.swift | 6 ++- .../EmailVerify/SignupEmailVerifyView.swift | 40 ++++++++++++++++++- .../SignupEmailVerifyViewModel.swift | 7 ++++ 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyComponent.swift b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyComponent.swift index e597993..8415dbc 100644 --- a/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyComponent.swift +++ b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyComponent.swift @@ -1,11 +1,12 @@ import SwiftUI import NeedleFoundation -import SignupEmailAuthCodeVerifyFeatureInterface +import SignupFeatureInterface public protocol SignupEmailAuthCodeVerifyDependency: Dependency { } -public final class SignupEmailAuthCodeVerifyComponent: Component, SignupEmailAuthCodeVerifyFactory { +public final class SignupEmailAuthCodeVerifyComponent: Component, + SignupEmailAuthCodeVerifyFactory { public func makeView() -> some View { SignupEmailAuthCodeVerifyView( viewModel: .init() diff --git a/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyComponent.swift b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyComponent.swift index 30abaf1..2144fce 100644 --- a/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyComponent.swift +++ b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyComponent.swift @@ -1,14 +1,16 @@ import SwiftUI import NeedleFoundation -import SignupEmailVerifyFeatureInterface +import SignupFeatureInterface public protocol SignupEmailVerifyDependency: Dependency { + var signupEmailAuthCodeVerifyFactory: any SignupEmailAuthCodeVerifyFactory { get } } public final class SignupEmailVerifyComponent: Component, SignupEmailVerifyFactory { public func makeView() -> some View { SignupEmailVerifyView( - viewModel: .init() + viewModel: .init(), + signupEmailAuthCodeVerifyFactory: dependency.signupEmailAuthCodeVerifyFactory ) } } diff --git a/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyView.swift b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyView.swift index d34915c..f051c05 100644 --- a/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyView.swift +++ b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyView.swift @@ -1,17 +1,53 @@ import DesignSystem import SwiftUI import BaseFeature +import ViewUtil +import SignupFeatureInterface struct SignupEmailVerifyView: View { + private enum FocusField { + case email + } + @FocusState private var focusField: FocusField? @StateObject var viewModel: SignupEmailVerifyViewModel + private let signupEmailAuthCodeVerifyFactory: any SignupEmailAuthCodeVerifyFactory init( - viewModel: SignupEmailVerifyViewModel + viewModel: SignupEmailVerifyViewModel, + signupEmailAuthCodeVerifyFactory: any SignupEmailAuthCodeVerifyFactory ) { _viewModel = StateObject(wrappedValue: viewModel) + self.signupEmailAuthCodeVerifyFactory = signupEmailAuthCodeVerifyFactory } var body: some View { - Text("SignupEmailVerifyView") + VStack(spacing: 0) { + NavigationTitleView( + title: "이메일을 입력해 주세요", + description: "이메일로 인증번호를 전송해 드릴게요" + ) + + KGTextField( + "이메일을 입력해주세요", + text: $viewModel.email, + title: "이메일", + isError: viewModel.isErrorOccurred, + errorMessage: viewModel.errorMessage, + onCommit: viewModel.nextButtonDidTap + ) + .focused($focusField, equals: .email) + + Spacer() + + KGButton(text: "다음", isEditing: focusField != nil, action: viewModel.nextButtonDidTap) + .disabled(viewModel.email.isEmpty) + } + .navigationBackButton() + .kgBackground() + .hideKeyboardWhenTap() + .navigate( + to: signupEmailAuthCodeVerifyFactory.makeView().eraseToAnyView(), + when: $viewModel.isNavigatedToEmailAuthCodeVerify + ) } } diff --git a/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyViewModel.swift b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyViewModel.swift index e902fc1..eda6279 100644 --- a/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyViewModel.swift +++ b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyViewModel.swift @@ -2,4 +2,11 @@ import BaseFeature import Combine final class SignupEmailVerifyViewModel: BaseViewModel { + @Published var email: String = "" + + @Published var isNavigatedToEmailAuthCodeVerify: Bool = false + + func nextButtonDidTap() { + self.isNavigatedToEmailAuthCodeVerify = true + } } From a71cf7dfd1dd760c3587b7e5ae1b72f6d963d3b3 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 09:53:55 +0900 Subject: [PATCH 16/33] =?UTF-8?q?=E2=9C=A8=20::=20Signup=20DI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Application/NeedleGenerated.swift | 54 ++++++++++--------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/Projects/App/Sources/Application/NeedleGenerated.swift b/Projects/App/Sources/Application/NeedleGenerated.swift index 0a97543..965f872 100644 --- a/Projects/App/Sources/Application/NeedleGenerated.swift +++ b/Projects/App/Sources/Application/NeedleGenerated.swift @@ -36,26 +36,30 @@ private func factoryace9f05f51d68f4c0677e3b0c44298fc1c149afb(_ component: Needle return SplashDependencye0cb7136f2ec3edfd60aProvider() } private class SignupPasswordDependency778bf5389a70d7df6152Provider: SignupPasswordDependency { - - - init() { - + var signupNameFactory: any SignupNameFactory { + return appComponent.signupNameFactory + } + private let appComponent: AppComponent + init(appComponent: AppComponent) { + self.appComponent = appComponent } } /// ^->AppComponent->SignupPasswordComponent -private func factorye93d1d56840ff97c674ae3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { - return SignupPasswordDependency778bf5389a70d7df6152Provider() +private func factorye93d1d56840ff97c674af47b58f8f304c97af4d5(_ component: NeedleFoundation.Scope) -> AnyObject { + return SignupPasswordDependency778bf5389a70d7df6152Provider(appComponent: parent1(component) as! AppComponent) } private class SignupEmailAuthCodeVerifyDependencyaf9da1ebf0e9e5f1b708Provider: SignupEmailAuthCodeVerifyDependency { - - - init() { - + var signupPasswordFactory: any SignupPasswordFactory { + return appComponent.signupPasswordFactory + } + private let appComponent: AppComponent + init(appComponent: AppComponent) { + self.appComponent = appComponent } } /// ^->AppComponent->SignupEmailAuthCodeVerifyComponent -private func factoryb06be35aa893adde971be3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { - return SignupEmailAuthCodeVerifyDependencyaf9da1ebf0e9e5f1b708Provider() +private func factoryb06be35aa893adde971bf47b58f8f304c97af4d5(_ component: NeedleFoundation.Scope) -> AnyObject { + return SignupEmailAuthCodeVerifyDependencyaf9da1ebf0e9e5f1b708Provider(appComponent: parent1(component) as! AppComponent) } private class SignupStudentIDDependencyc62f548e51245f5bf42dProvider: SignupStudentIDDependency { @@ -91,15 +95,17 @@ private func factory5b23127e837152346fdae3b0c44298fc1c149afb(_ component: Needle return SignupCheckLevelDependencye4ec84c7d38354a454aeProvider() } private class SignupNameDependency860534ba64c054146b7bProvider: SignupNameDependency { - - - init() { - + var signupStudentIDFactory: any SignupStudentIDFactory { + return appComponent.signupStudentIDFactory + } + private let appComponent: AppComponent + init(appComponent: AppComponent) { + self.appComponent = appComponent } } /// ^->AppComponent->SignupNameComponent -private func factory71e8fa7f4327b1e25ed0e3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { - return SignupNameDependency860534ba64c054146b7bProvider() +private func factory71e8fa7f4327b1e25ed0f47b58f8f304c97af4d5(_ component: NeedleFoundation.Scope) -> AnyObject { + return SignupNameDependency860534ba64c054146b7bProvider(appComponent: parent1(component) as! AppComponent) } private class SignupEmailVerifyDependencyf9d372ac752ee19b78caProvider: SignupEmailVerifyDependency { var signupEmailAuthCodeVerifyFactory: any SignupEmailAuthCodeVerifyFactory { @@ -166,12 +172,12 @@ extension SplashComponent: Registration { } extension SignupPasswordComponent: Registration { public func registerItems() { - + keyPathToName[\SignupPasswordDependency.signupNameFactory] = "signupNameFactory-any SignupNameFactory" } } extension SignupEmailAuthCodeVerifyComponent: Registration { public func registerItems() { - + keyPathToName[\SignupEmailAuthCodeVerifyDependency.signupPasswordFactory] = "signupPasswordFactory-any SignupPasswordFactory" } } extension SignupStudentIDComponent: Registration { @@ -191,7 +197,7 @@ extension SignupCheckLevelComponent: Registration { } extension SignupNameComponent: Registration { public func registerItems() { - + keyPathToName[\SignupNameDependency.signupStudentIDFactory] = "signupStudentIDFactory-any SignupStudentIDFactory" } } extension SignupEmailVerifyComponent: Registration { @@ -228,12 +234,12 @@ private func registerProviderFactory(_ componentPath: String, _ factory: @escapi @inline(never) private func register1() { registerProviderFactory("^->AppComponent", factoryEmptyDependencyProvider) registerProviderFactory("^->AppComponent->SplashComponent", factoryace9f05f51d68f4c0677e3b0c44298fc1c149afb) - registerProviderFactory("^->AppComponent->SignupPasswordComponent", factorye93d1d56840ff97c674ae3b0c44298fc1c149afb) - registerProviderFactory("^->AppComponent->SignupEmailAuthCodeVerifyComponent", factoryb06be35aa893adde971be3b0c44298fc1c149afb) + registerProviderFactory("^->AppComponent->SignupPasswordComponent", factorye93d1d56840ff97c674af47b58f8f304c97af4d5) + registerProviderFactory("^->AppComponent->SignupEmailAuthCodeVerifyComponent", factoryb06be35aa893adde971bf47b58f8f304c97af4d5) registerProviderFactory("^->AppComponent->SignupStudentIDComponent", factorycca12bec445b4f4f6de7e3b0c44298fc1c149afb) registerProviderFactory("^->AppComponent->SignupGenderComponent", factory997eaa831d16af15eee5e3b0c44298fc1c149afb) registerProviderFactory("^->AppComponent->SignupCheckLevelComponent", factory5b23127e837152346fdae3b0c44298fc1c149afb) - registerProviderFactory("^->AppComponent->SignupNameComponent", factory71e8fa7f4327b1e25ed0e3b0c44298fc1c149afb) + registerProviderFactory("^->AppComponent->SignupNameComponent", factory71e8fa7f4327b1e25ed0f47b58f8f304c97af4d5) registerProviderFactory("^->AppComponent->SignupEmailVerifyComponent", factory3b1904c76335d70151ebf47b58f8f304c97af4d5) registerProviderFactory("^->AppComponent->RootComponent", factory264bfc4d4cb6b0629b40f47b58f8f304c97af4d5) registerProviderFactory("^->AppComponent->SigninComponent", factory2882a056d84a613debccf47b58f8f304c97af4d5) From 184014bcabe689ef50fc1a90887dfb84dd65332f Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 09:54:55 +0900 Subject: [PATCH 17/33] =?UTF-8?q?=E2=9C=A8=20::=20TextField=20Extension?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extension/TextFieldExtension.swift | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Projects/UserInterface/DesignSystem/Sources/Extension/TextFieldExtension.swift diff --git a/Projects/UserInterface/DesignSystem/Sources/Extension/TextFieldExtension.swift b/Projects/UserInterface/DesignSystem/Sources/Extension/TextFieldExtension.swift new file mode 100644 index 0000000..27ebb1b --- /dev/null +++ b/Projects/UserInterface/DesignSystem/Sources/Extension/TextFieldExtension.swift @@ -0,0 +1,21 @@ +import SwiftUI +import Combine + +public extension View { + func filterNumericInput(_ input: Binding) -> some View { + self.onReceive(Just(input.wrappedValue)) { newValue in + let filtered = newValue.filter { "0123456789".contains($0) } + if filtered != newValue { + input.wrappedValue = filtered + } + } + } + + func limitInputCount(_ input: Binding, limitCount: Int) -> some View { + self.onReceive(Just(input.wrappedValue)) { _ in + if limitCount < input.wrappedValue.count { + input.wrappedValue = String(input.wrappedValue.prefix(limitCount)) + } + } + } +} From 530d7dfc5763bf5871a1c77de3724c0ec38c9ffd Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:26:20 +0900 Subject: [PATCH 18/33] =?UTF-8?q?=E2=9C=A8=20::=20Textfield=20Secure=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/LevelCheckCellView.swift | 19 +++++++++++++++++++ .../Extension/View+navigationBar.swift | 2 +- .../Sources/TextField/KGTextField.swift | 19 ++++++++++++++----- 3 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/Components/LevelCheckCellView.swift diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/Components/LevelCheckCellView.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/Components/LevelCheckCellView.swift new file mode 100644 index 0000000..f0445cb --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/Components/LevelCheckCellView.swift @@ -0,0 +1,19 @@ +// +// LevelCheckCellView.swift +// SignupFeature +// +// Created by 홍승재 on 4/25/24. +// Copyright © 2024 com.gram. All rights reserved. +// + +import SwiftUI + +struct LevelCheckCellView: View { + var body: some View { + Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + } +} + +#Preview { + LevelCheckCellView() +} diff --git a/Projects/UserInterface/DesignSystem/Sources/Extension/View+navigationBar.swift b/Projects/UserInterface/DesignSystem/Sources/Extension/View+navigationBar.swift index e0ca7b4..79e5075 100644 --- a/Projects/UserInterface/DesignSystem/Sources/Extension/View+navigationBar.swift +++ b/Projects/UserInterface/DesignSystem/Sources/Extension/View+navigationBar.swift @@ -61,7 +61,7 @@ public struct NavigationBarModifier: ViewModifier { public extension View { func navigationBar( - navigationTitle: String, + navigationTitle: String = "", hasBackButton: Bool = false, rightIcon: (Icons, () -> Void)? = nil ) -> some View { diff --git a/Projects/UserInterface/DesignSystem/Sources/TextField/KGTextField.swift b/Projects/UserInterface/DesignSystem/Sources/TextField/KGTextField.swift index 5d6f281..0e862a6 100644 --- a/Projects/UserInterface/DesignSystem/Sources/TextField/KGTextField.swift +++ b/Projects/UserInterface/DesignSystem/Sources/TextField/KGTextField.swift @@ -8,6 +8,7 @@ public struct KGTextField: View { var isError: Bool var errorMessage: String var description: String + var isSecure: Bool var onCommit: () -> Void @FocusState var isFocused: Bool private var isErrorAndNotEmpty: Bool { @@ -21,6 +22,7 @@ public struct KGTextField: View { isError: Bool = false, errorMessage: String = "", description: String = "", + isSecure: Bool = false, onCommit: @escaping () -> Void = {} ) { self.placeholder = placeholder @@ -29,6 +31,7 @@ public struct KGTextField: View { self.isError = isError self.description = description self.errorMessage = errorMessage + self.isSecure = isSecure self.onCommit = onCommit } @@ -44,10 +47,16 @@ public struct KGTextField: View { .kgFont(.m3, weight: .regular, color: .Grays.gray800) .opacity(text.isEmpty ? 1 : 0) - TextField("", text: $text) - .kgFont(.m3, weight: .regular, color: .Grays.white) - .focused($isFocused) - .onSubmit(onCommit) + Group { + if isSecure { + SecureField("", text: $text) + } else { + TextField("", text: $text) + } + } + .kgFont(.m3, weight: .regular, color: .Grays.white) + .focused($isFocused) + .onSubmit(onCommit) } .padding(.horizontal, 16) .frame(height: 56) @@ -56,7 +65,7 @@ public struct KGTextField: View { .overlay { RoundedRectangle(cornerRadius: 8) .strokeBorder( - isErrorAndNotEmpty ? Color.System.red : .clear, + isErrorAndNotEmpty ? Color.System.red : isFocused ? .Greens.main : .clear, lineWidth: 1 ) } From 113edd0efb316728269b123818526904d8d2f0fe Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:26:43 +0900 Subject: [PATCH 19/33] =?UTF-8?q?=E2=9C=A8=20::=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20TextField=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Demo/Sources/View/ButtonDemoView.swift | 3 +- .../Demo/Sources/View/TextFieldDemoView.swift | 7 ++ .../TextField/VerifyCodeTextField.swift | 72 +++++++++++++++++++ 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 Projects/UserInterface/DesignSystem/Sources/TextField/VerifyCodeTextField.swift diff --git a/Projects/UserInterface/DesignSystem/Demo/Sources/View/ButtonDemoView.swift b/Projects/UserInterface/DesignSystem/Demo/Sources/View/ButtonDemoView.swift index 016252f..cc60e34 100644 --- a/Projects/UserInterface/DesignSystem/Demo/Sources/View/ButtonDemoView.swift +++ b/Projects/UserInterface/DesignSystem/Demo/Sources/View/ButtonDemoView.swift @@ -4,8 +4,7 @@ import DesignSystem struct ButtonDemoView: View { var body: some View { VStack { - KGButton(text: "버튼", style: .black) - KGButton(text: "버튼", style: .green) + KGButton(text: "버튼") } } } diff --git a/Projects/UserInterface/DesignSystem/Demo/Sources/View/TextFieldDemoView.swift b/Projects/UserInterface/DesignSystem/Demo/Sources/View/TextFieldDemoView.swift index 2dba1ca..f840d80 100644 --- a/Projects/UserInterface/DesignSystem/Demo/Sources/View/TextFieldDemoView.swift +++ b/Projects/UserInterface/DesignSystem/Demo/Sources/View/TextFieldDemoView.swift @@ -3,6 +3,7 @@ import DesignSystem struct TextFieldDemoView: View { @State var text1: String = "" + @State var text2: String = "" @State var isError1: Bool = false var body: some View { VStack { @@ -15,6 +16,12 @@ struct TextFieldDemoView: View { errorMessage: "에러입니다" ) + VerifyCodeTextField( + $text2, + isError: isError1, + errorMessage: "에러입니다" + ) + Toggle("", isOn: $isError1) } } diff --git a/Projects/UserInterface/DesignSystem/Sources/TextField/VerifyCodeTextField.swift b/Projects/UserInterface/DesignSystem/Sources/TextField/VerifyCodeTextField.swift new file mode 100644 index 0000000..041d045 --- /dev/null +++ b/Projects/UserInterface/DesignSystem/Sources/TextField/VerifyCodeTextField.swift @@ -0,0 +1,72 @@ +import SwiftUI + +public struct VerifyCodeTextField: View { + @Binding var text: String + var isError: Bool + var errorMessage: String + var onCommit: () -> Void + private var isErrorAndNotEmpty: Bool { + isError && !errorMessage.isEmpty + } + @FocusState var isFocused: Bool + + public init( + _ text: Binding, + isError: Bool = false, + errorMessage: String = "", + onCommit: @escaping () -> Void = {} + ) { + _text = text + self.isError = isError + self.errorMessage = errorMessage + self.onCommit = onCommit + } + + public var body: some View { + VStack(alignment: .leading, spacing: 4) { + ZStack(alignment: .leading) { + HStack(spacing: 0) { + ForEach(0..<4) { index in + let str = text.count - 1 < index ? "" : text.map { String($0) }[index] + Text(str) + .kgFont(.h1, weight: .semiBold, color: .Grays.white) + .frame(width: 72, height: 80) + .background(Color.Grays.gray1000) + .clipCornerRadius(8) + .overlay { + RoundedRectangle(cornerRadius: 8) + .strokeBorder( + isErrorAndNotEmpty ? Color.System.red : .clear, + lineWidth: 1 + ) + } + + if index != 3 { + Spacer() + } + } + } + + TextField("", text: $text) + .opacity(0.0000001) + .keyboardType(.numberPad) + .limitInputCount($text, limitCount: 4) + .filterNumericInput($text) + .focused($isFocused) + .onSubmit(onCommit) + } + .onTapGesture { + self.isFocused = true + } + + if isErrorAndNotEmpty { + Text(errorMessage) + .kgFont(.label, weight: .regular, color: .System.red) + } + } + .padding(.vertical, 8) + .padding(.horizontal, 24) + .animation(.easeIn(duration: 0.2), value: isError) + .animation(.easeIn(duration: 0.2), value: isErrorAndNotEmpty) + } +} From dd8fe71bb2c2e0a377e7ce6b4c76353ea36a5366 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:27:17 +0900 Subject: [PATCH 20/33] =?UTF-8?q?=E2=9C=A8=20::=20underline=20Text?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ViewUtil/Sources/View+underlineText.swift | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Projects/Shared/ViewUtil/Sources/View+underlineText.swift diff --git a/Projects/Shared/ViewUtil/Sources/View+underlineText.swift b/Projects/Shared/ViewUtil/Sources/View+underlineText.swift new file mode 100644 index 0000000..de68b02 --- /dev/null +++ b/Projects/Shared/ViewUtil/Sources/View+underlineText.swift @@ -0,0 +1,27 @@ +import SwiftUI + +struct UnderlineTextModifier: ViewModifier { + let color: Color + + func body(content: Content) -> some View { + if #available(iOS 16.0, *) { + content + .underline(color: color) + } else { + content + .overlay( + Rectangle() + .fill(color) + .frame(height: 1) + .padding(.top, 3), + alignment: .bottom + ) + } + } +} + +public extension View { + func underlineText(color: Color) -> some View { + self.modifier(UnderlineTextModifier(color: color)) + } +} From 1ccbfbf00c0a28708764f8af93f459728542a2d7 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:27:42 +0900 Subject: [PATCH 21/33] =?UTF-8?q?=E2=9C=A8=20::=20Bottom=20Button=20Extens?= =?UTF-8?q?ion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Components/BottomButton.swift | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 Projects/Feature/SignupFeature/Sources/Components/BottomButton.swift diff --git a/Projects/Feature/SignupFeature/Sources/Components/BottomButton.swift b/Projects/Feature/SignupFeature/Sources/Components/BottomButton.swift new file mode 100644 index 0000000..2a86fa2 --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/Components/BottomButton.swift @@ -0,0 +1,48 @@ +import SwiftUI +import DesignSystem + +struct BottomButton: ViewModifier { + let text: String + let isEditing: Bool + let isDisabled: Bool + let action: () -> Void + + init( + text: String, + isEditing: Bool, + isDisabled: Bool, + action: @escaping () -> Void = {} + ) { + self.text = text + self.isEditing = isEditing + self.isDisabled = isDisabled + self.action = action + } + + func body(content: Content) -> some View { + ZStack(alignment: .bottom) { + content + + KGButton(text: text, isEditing: isEditing, action: action) + .disabled(isDisabled) + } + } +} + +public extension View { + func bottomButton( + text: String, + isEditing: Bool = false, + isDisabled: Bool = false, + action: @escaping () -> Void = {} + ) -> some View { + modifier( + BottomButton( + text: text, + isEditing: isEditing, + isDisabled: isDisabled, + action: action + ) + ) + } +} From fdf2ae9afdb61a52610920dcd643158bd73312b5 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:28:09 +0900 Subject: [PATCH 22/33] =?UTF-8?q?=E2=9C=A8=20::=20TextField=20Type=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/EmailVerify/SignupEmailVerifyView.swift | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyView.swift b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyView.swift index f051c05..d246056 100644 --- a/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyView.swift +++ b/Projects/Feature/SignupFeature/Sources/EmailVerify/SignupEmailVerifyView.swift @@ -12,6 +12,7 @@ struct SignupEmailVerifyView: View { @StateObject var viewModel: SignupEmailVerifyViewModel private let signupEmailAuthCodeVerifyFactory: any SignupEmailAuthCodeVerifyFactory + init( viewModel: SignupEmailVerifyViewModel, signupEmailAuthCodeVerifyFactory: any SignupEmailAuthCodeVerifyFactory @@ -35,13 +36,18 @@ struct SignupEmailVerifyView: View { errorMessage: viewModel.errorMessage, onCommit: viewModel.nextButtonDidTap ) + .textContentType(.emailAddress) + .keyboardType(.emailAddress) .focused($focusField, equals: .email) Spacer() - - KGButton(text: "다음", isEditing: focusField != nil, action: viewModel.nextButtonDidTap) - .disabled(viewModel.email.isEmpty) } + .bottomButton( + text: "다음", + isEditing: focusField != nil, + isDisabled: viewModel.email.isEmpty, + action: viewModel.nextButtonDidTap + ) .navigationBackButton() .kgBackground() .hideKeyboardWhenTap() From 3cfc8c685fe182b83f64e1f88a84105e942a08da Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:28:20 +0900 Subject: [PATCH 23/33] =?UTF-8?q?=E2=9C=A8=20::=20Email=20Auth=20Code=20Ve?= =?UTF-8?q?rify=20View=20Publishing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SignupEmailAuthCodeVerifyComponent.swift | 4 +- .../SignupEmailAuthCodeVerifyView.swift | 55 ++++++++++++++++++- .../SignupEmailAuthCodeVerifyViewModel.swift | 8 +++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyComponent.swift b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyComponent.swift index 8415dbc..4ac5e83 100644 --- a/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyComponent.swift +++ b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyComponent.swift @@ -3,13 +3,15 @@ import NeedleFoundation import SignupFeatureInterface public protocol SignupEmailAuthCodeVerifyDependency: Dependency { + var signupPasswordFactory: any SignupPasswordFactory { get } } public final class SignupEmailAuthCodeVerifyComponent: Component, SignupEmailAuthCodeVerifyFactory { public func makeView() -> some View { SignupEmailAuthCodeVerifyView( - viewModel: .init() + viewModel: .init(), + signupPasswordFactory: dependency.signupPasswordFactory ) } } diff --git a/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyView.swift b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyView.swift index 6036bf3..33ee125 100644 --- a/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyView.swift +++ b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyView.swift @@ -1,17 +1,68 @@ import DesignSystem import SwiftUI import BaseFeature +import ViewUtil +import SignupFeatureInterface struct SignupEmailAuthCodeVerifyView: View { + private enum FocusField { + case authCode + } + @FocusState private var focusField: FocusField? @StateObject var viewModel: SignupEmailAuthCodeVerifyViewModel + private let signupPasswordFactory: any SignupPasswordFactory + init( - viewModel: SignupEmailAuthCodeVerifyViewModel + viewModel: SignupEmailAuthCodeVerifyViewModel, + signupPasswordFactory: any SignupPasswordFactory ) { _viewModel = StateObject(wrappedValue: viewModel) + self.signupPasswordFactory = signupPasswordFactory } var body: some View { - Text("SignupEmailAuthCodeVerifyView") + VStack(spacing: 0) { + NavigationTitleView( + title: "인증번호를 입력해 주세요", + description: "입력해주신 이메일로 인증번호를 전송해 드렸어요" + ) + + VerifyCodeTextField( + $viewModel.authCode, + isError: viewModel.isErrorOccurred, + errorMessage: viewModel.errorMessage, + onCommit: viewModel.nextButtonDidTap + ) + .focused($focusField, equals: .authCode) + + HStack { + Text("5:00") + .kgFont(.label, weight: .regular, color: .Greens.main) + + Spacer() + + Text("인증번호 재전송") + .kgFont(.label, weight: .regular, color: .Grays.gray400) + .underlineText(color: .Grays.gray400) + } + .padding(.vertical, 16) + .padding(.horizontal, 24) + + Spacer() + } + .bottomButton( + text: "다음", + isEditing: focusField != nil, + isDisabled: viewModel.authCode.count < 4, + action: viewModel.nextButtonDidTap + ) + .navigationBackButton() + .kgBackground() + .hideKeyboardWhenTap() + .navigate( + to: signupPasswordFactory.makeView().eraseToAnyView(), + when: $viewModel.isNavigatedToPassword + ) } } diff --git a/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyViewModel.swift b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyViewModel.swift index cf62a60..355656a 100644 --- a/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyViewModel.swift +++ b/Projects/Feature/SignupFeature/Sources/EmailAuthCodeVerify/SignupEmailAuthCodeVerifyViewModel.swift @@ -1,5 +1,13 @@ import BaseFeature +import Foundation import Combine final class SignupEmailAuthCodeVerifyViewModel: BaseViewModel { + @Published var authCode: String = "" + + @Published var isNavigatedToPassword: Bool = false + + func nextButtonDidTap() { + self.isNavigatedToPassword = true + } } From c3fc06945efc7d79282c30c47051c81f21c5c15d Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:28:35 +0900 Subject: [PATCH 24/33] =?UTF-8?q?=E2=9C=A8=20::=20Check=20Level=20Publishi?= =?UTF-8?q?ng?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/LevelCheckCellView.swift | 73 ++++++++++++++++--- .../CheckLevel/SignupCheckLevelView.swift | 35 ++++++++- .../SignupCheckLevelViewModel.swift | 6 ++ 3 files changed, 102 insertions(+), 12 deletions(-) diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/Components/LevelCheckCellView.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/Components/LevelCheckCellView.swift index f0445cb..653a775 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/Components/LevelCheckCellView.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/Components/LevelCheckCellView.swift @@ -1,19 +1,70 @@ -// -// LevelCheckCellView.swift -// SignupFeature -// -// Created by 홍승재 on 4/25/24. -// Copyright © 2024 com.gram. All rights reserved. -// - import SwiftUI +import DesignSystem + +enum PhysicalLevel { + case high + case middle + case low +} struct LevelCheckCellView: View { + @Binding var selectedLevel: PhysicalLevel + let level: PhysicalLevel + + init(_ level: PhysicalLevel, selectedLevel: Binding) { + _selectedLevel = selectedLevel + self.level = level + } + var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + Button { + self.selectedLevel = level + } label: { + HStack(spacing: 8) { + Text(level.text) + .kgFont(.m1, weight: .semiBold, color: .Grays.white) + + Text(level.description) + .kgFont(.m3, weight: .regular, color: .Grays.gray500) + .lineLimit(1) + + Spacer() + } + .padding(.vertical, 20) + .padding(.horizontal, 16) + .background(Color.Grays.gray1100) + .clipCornerRadius(8) + .overlay { + RoundedRectangle(cornerRadius: 8) + .strokeBorder( + self.selectedLevel == level ? Color.Greens.main : .clear, + lineWidth: 1 + ) + } + } } } -#Preview { - LevelCheckCellView() +extension PhysicalLevel { + var text: String { + switch self { + case .high: + "상" + case .middle: + "중" + case .low: + "하" + } + } + + var description: String { + switch self { + case .high: + "운동을 평소에 즐겨하며 잘 하는 편이에요" + case .middle: + "운동을 즐기진 않지만 못하지는 않아요" + case .low: + "운동을 별로 좋아하지 않아요" + } + } } diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelView.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelView.swift index a22e4f7..36308c6 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelView.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelView.swift @@ -1,8 +1,11 @@ import DesignSystem import SwiftUI import BaseFeature +import SignupFeatureInterface +import ViewUtil struct SignupCheckLevelView: View { + @AppState var appState @StateObject var viewModel: SignupCheckLevelViewModel init( @@ -12,6 +15,36 @@ struct SignupCheckLevelView: View { } var body: some View { - Text("SignupCheckLevelView") + VStack(spacing: 0) { + SignupProgressView(step: .checkLevel) + + NavigationTitleView( + title: "운동 실력을 알려주세요", + description: "평소 운동을 좋아하고 잘하시는지 알려주세요" + ) + + VStack(spacing: 24) { + LevelCheckCellView(.high, selectedLevel: $viewModel.selectedLevel) + + LevelCheckCellView(.middle, selectedLevel: $viewModel.selectedLevel) + + LevelCheckCellView(.low, selectedLevel: $viewModel.selectedLevel) + } + .padding(.vertical, 8) + .padding(.horizontal, 24) + + Spacer() + } + .bottomButton( + text: "다음", +// isDisabled: viewModel.studentID.isEmpty, + action: viewModel.nextButtonDidTap + ) + .navigationBackButton(navigationTitle: "정보 입력") + .kgBackground() + .hideKeyboardWhenTap() + .onChange(of: viewModel.isSuccessToSignup) { _ in + self.appState.sceneFlow = .main + } } } diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelViewModel.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelViewModel.swift index ec2fb1c..303f9a3 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelViewModel.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelViewModel.swift @@ -2,4 +2,10 @@ import BaseFeature import Combine final class SignupCheckLevelViewModel: BaseViewModel { + @Published var selectedLevel: PhysicalLevel = .high + @Published var isSuccessToSignup: Bool = false + + func nextButtonDidTap() { + self.isSuccessToSignup = true + } } From 34a78ed078378c0acaf8e88c0d42157c72d75104 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:28:46 +0900 Subject: [PATCH 25/33] =?UTF-8?q?=E2=9C=A8=20::=20Signup=20Name=20Publishi?= =?UTF-8?q?ng?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UserInfo/Name/SignupNameComponent.swift | 4 +- .../UserInfo/Name/SignupNameView.swift | 46 ++++++++++++++++++- .../UserInfo/Name/SignupNameViewModel.swift | 7 +++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameComponent.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameComponent.swift index b395b93..bb1f68e 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameComponent.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameComponent.swift @@ -3,12 +3,14 @@ import NeedleFoundation import SignupFeatureInterface public protocol SignupNameDependency: Dependency { + var signupStudentIDFactory: any SignupStudentIDFactory { get } } public final class SignupNameComponent: Component, SignupNameFactory { public func makeView() -> some View { SignupNameView( - viewModel: .init() + viewModel: .init(), + signupStudentIDFactory: dependency.signupStudentIDFactory ) } } diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameView.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameView.swift index 64d13b3..4884ab0 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameView.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameView.swift @@ -1,17 +1,59 @@ import DesignSystem import SwiftUI import BaseFeature +import SignupFeatureInterface +import ViewUtil struct SignupNameView: View { + private enum FocusField { + case name + } + @FocusState private var focusField: FocusField? @StateObject var viewModel: SignupNameViewModel + private let signupStudentIDFactory: any SignupStudentIDFactory init( - viewModel: SignupNameViewModel + viewModel: SignupNameViewModel, + signupStudentIDFactory: any SignupStudentIDFactory ) { _viewModel = StateObject(wrappedValue: viewModel) + self.signupStudentIDFactory = signupStudentIDFactory } var body: some View { - Text("SignupNameView") + VStack(spacing: 0) { + SignupProgressView(step: .name) + + NavigationTitleView( + title: "이름을 입력해 주세요", + description: "원활한 서비스를 위해 이름을 입력해주세요" + ) + + KGTextField( + "이름을 입력해 주세요", + text: $viewModel.name, + title: "이름", + isError: viewModel.isErrorOccurred, + errorMessage: viewModel.errorMessage, + onCommit: viewModel.nextButtonDidTap + ) + .textContentType(.name) + .focused($focusField, equals: .name) + + Spacer() + } + .bottomButton( + text: "다음", + isEditing: focusField != nil, + isDisabled: viewModel.name.isEmpty, + action: viewModel.nextButtonDidTap + ) + .navigationBackButton(navigationTitle: "정보 입력") + .kgBackground() + .hideKeyboardWhenTap() + .navigate( + to: signupStudentIDFactory.makeView().eraseToAnyView(), + when: $viewModel.isNavigatedToStudentID + ) } } diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameViewModel.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameViewModel.swift index 18d6554..978ddef 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameViewModel.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Name/SignupNameViewModel.swift @@ -2,4 +2,11 @@ import BaseFeature import Combine final class SignupNameViewModel: BaseViewModel { + @Published var name: String = "" + + @Published var isNavigatedToStudentID: Bool = false + + func nextButtonDidTap() { + self.isNavigatedToStudentID = true + } } From f1b68c22bdec785efaad89f2f90c71f5c1ff8fc8 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:29:00 +0900 Subject: [PATCH 26/33] =?UTF-8?q?=E2=9C=A8=20::=20Signup=20StudentID=20Pub?= =?UTF-8?q?lishing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StudentID/SignupStudentIDComponent.swift | 4 +- .../StudentID/SignupStudentIDView.swift | 49 ++++++++++++++++++- .../StudentID/SignupStudentIDViewModel.swift | 7 +++ 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDComponent.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDComponent.swift index 5d28f38..004b8f0 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDComponent.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDComponent.swift @@ -3,12 +3,14 @@ import NeedleFoundation import SignupFeatureInterface public protocol SignupStudentIDDependency: Dependency { + var signupGenderFactory: any SignupGenderFactory { get } } public final class SignupStudentIDComponent: Component, SignupStudentIDFactory { public func makeView() -> some View { SignupStudentIDView( - viewModel: .init() + viewModel: .init(), + signupGenderFactory: dependency.signupGenderFactory ) } } diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDView.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDView.swift index f6b2d27..98cb253 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDView.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDView.swift @@ -1,17 +1,62 @@ import DesignSystem import SwiftUI import BaseFeature +import SignupFeatureInterface +import ViewUtil struct SignupStudentIDView: View { + private enum FocusField { + case studentID + } + @FocusState private var focusField: FocusField? @StateObject var viewModel: SignupStudentIDViewModel + private let signupGenderFactory: any SignupGenderFactory + init( - viewModel: SignupStudentIDViewModel + viewModel: SignupStudentIDViewModel, + signupGenderFactory: any SignupGenderFactory ) { _viewModel = StateObject(wrappedValue: viewModel) + self.signupGenderFactory = signupGenderFactory } var body: some View { - Text("SignupStudentIDView") + VStack(spacing: 0) { + SignupProgressView(step: .studentID) + + NavigationTitleView( + title: "학번을 입력해주세요", + description: "원활한 서비스를 위해 학번을 입력해주세요" + ) + + KGTextField( + "학번을 입력해 주세요 ex) 2417", + text: $viewModel.studentID, + title: "학번", + isError: viewModel.isErrorOccurred, + errorMessage: viewModel.errorMessage, + onCommit: viewModel.nextButtonDidTap + ) + .keyboardType(.numberPad) + .limitInputCount($viewModel.studentID, limitCount: 4) + .filterNumericInput($viewModel.studentID) + .focused($focusField, equals: .studentID) + + Spacer() + } + .bottomButton( + text: "다음", + isEditing: focusField != nil, + isDisabled: viewModel.studentID.isEmpty, + action: viewModel.nextButtonDidTap + ) + .navigationBackButton(navigationTitle: "정보 입력") + .kgBackground() + .hideKeyboardWhenTap() + .navigate( + to: signupGenderFactory.makeView().eraseToAnyView(), + when: $viewModel.isNavigatedToGender + ) } } diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDViewModel.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDViewModel.swift index 7f3bc1c..b69ba66 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDViewModel.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/StudentID/SignupStudentIDViewModel.swift @@ -2,4 +2,11 @@ import BaseFeature import Combine final class SignupStudentIDViewModel: BaseViewModel { + @Published var studentID: String = "" + + @Published var isNavigatedToGender: Bool = false + + func nextButtonDidTap() { + self.isNavigatedToGender = true + } } From 73aa598e9f4c091cbcc345cb7f557c34c2fb85fc Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:29:09 +0900 Subject: [PATCH 27/33] =?UTF-8?q?=E2=9C=A8=20::=20Signup=20Gender=20Publis?= =?UTF-8?q?hing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Gender/SignupGenderComponent.swift | 4 ++- .../UserInfo/Gender/SignupGenderView.swift | 31 +++++++++++++++++-- .../Gender/SignupGenderViewModel.swift | 7 +++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderComponent.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderComponent.swift index 0e97d2e..7be04c9 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderComponent.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderComponent.swift @@ -3,12 +3,14 @@ import NeedleFoundation import SignupFeatureInterface public protocol SignupGenderDependency: Dependency { + var signupCheckLevelFactory: any SignupCheckLevelFactory { get } } public final class SignupGenderComponent: Component, SignupGenderFactory { public func makeView() -> some View { SignupGenderView( - viewModel: .init() + viewModel: .init(), + signupCheckLevelFactory: dependency.signupCheckLevelFactory ) } } diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderView.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderView.swift index 0688d90..22e1a31 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderView.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderView.swift @@ -1,17 +1,44 @@ import DesignSystem import SwiftUI import BaseFeature +import SignupFeatureInterface +import ViewUtil struct SignupGenderView: View { @StateObject var viewModel: SignupGenderViewModel + private let signupCheckLevelFactory: any SignupCheckLevelFactory + init( - viewModel: SignupGenderViewModel + viewModel: SignupGenderViewModel, + signupCheckLevelFactory: any SignupCheckLevelFactory ) { _viewModel = StateObject(wrappedValue: viewModel) + self.signupCheckLevelFactory = signupCheckLevelFactory } var body: some View { - Text("SignupGenderView") + VStack(spacing: 0) { + SignupProgressView(step: .gender) + + NavigationTitleView( + title: "성별을 알려주세요", + description: "원활한 서비스를 위해 성별을 알려주세요" + ) + + Spacer() + } + .bottomButton( + text: "다음", +// isDisabled: viewModel.studentID.isEmpty, + action: viewModel.nextButtonDidTap + ) + .navigationBackButton(navigationTitle: "정보 입력") + .kgBackground() + .hideKeyboardWhenTap() + .navigate( + to: signupCheckLevelFactory.makeView().eraseToAnyView(), + when: $viewModel.isNavigatedToLevelCheck + ) } } diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderViewModel.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderViewModel.swift index 39d233a..3203975 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderViewModel.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Gender/SignupGenderViewModel.swift @@ -2,4 +2,11 @@ import BaseFeature import Combine final class SignupGenderViewModel: BaseViewModel { +// @Published var studentID: String = "" + + @Published var isNavigatedToLevelCheck: Bool = false + + func nextButtonDidTap() { + self.isNavigatedToLevelCheck = true + } } From caed4addaeee006c9fdee1a5d139925fa85a07b7 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:29:18 +0900 Subject: [PATCH 28/33] =?UTF-8?q?=E2=9C=A8=20::=20Signup=20Password=20Publ?= =?UTF-8?q?ishing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Password/SignupPasswordComponent.swift | 4 +- .../Sources/Password/SignupPasswordView.swift | 60 ++++++++++++++++++- .../Password/SignupPasswordViewModel.swift | 8 +++ 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordComponent.swift b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordComponent.swift index 26287d0..f60ec80 100644 --- a/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordComponent.swift +++ b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordComponent.swift @@ -3,12 +3,14 @@ import NeedleFoundation import SignupFeatureInterface public protocol SignupPasswordDependency: Dependency { + var signupNameFactory: any SignupNameFactory { get } } public final class SignupPasswordComponent: Component, SignupPasswordFactory { public func makeView() -> some View { SignupPasswordView( - viewModel: .init() + viewModel: .init(), + signupNameFactory: dependency.signupNameFactory ) } } diff --git a/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordView.swift b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordView.swift index 5b3978a..a7f14b6 100644 --- a/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordView.swift +++ b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordView.swift @@ -1,17 +1,73 @@ import DesignSystem import SwiftUI import BaseFeature +import SignupFeatureInterface +import ViewUtil struct SignupPasswordView: View { + private enum FocusField { + case password + case checkPassword + } + @FocusState private var focusField: FocusField? @StateObject var viewModel: SignupPasswordViewModel + private let signupNameFactory: any SignupNameFactory + init( - viewModel: SignupPasswordViewModel + viewModel: SignupPasswordViewModel, + signupNameFactory: any SignupNameFactory ) { _viewModel = StateObject(wrappedValue: viewModel) + self.signupNameFactory = signupNameFactory } var body: some View { - Text("SignupPasswordView") + VStack(spacing: 0) { + NavigationTitleView( + title: "비밀번호를 입력해 주세요", + description: "비밀번호는 영어와 숫자를 조합해 만들어 주세요" + ) + + KGTextField( + "비밀번호(8~12자)를 입력해 주세요", + text: $viewModel.password, + title: "비밀번호", + isError: viewModel.isErrorOccurred, + errorMessage: viewModel.errorMessage, + isSecure: true + ) { + self.focusField = .checkPassword + } + .textContentType(.password) + .focused($focusField, equals: .password) + + KGTextField( + "비밀번호 다시 입력해 주세요", + text: $viewModel.checkPassword, + title: "비밀번호 확인", + isError: viewModel.isErrorOccurred, + errorMessage: viewModel.errorMessage, + isSecure: true, + onCommit: viewModel.nextButtonDidTap + ) + .textContentType(.password) + .focused($focusField, equals: .checkPassword) + + Spacer() + } + .bottomButton( + text: "다음", + isEditing: focusField != nil, + isDisabled: viewModel.password.isEmpty || viewModel.checkPassword.isEmpty, + action: viewModel.nextButtonDidTap + ) + .navigationBar() + .kgBackground() + .hideKeyboardWhenTap() + .navigate( + to: signupNameFactory.makeView().eraseToAnyView(), + when: $viewModel.isNavigatedToName + ) } } diff --git a/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordViewModel.swift b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordViewModel.swift index 3205e4c..679997a 100644 --- a/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordViewModel.swift +++ b/Projects/Feature/SignupFeature/Sources/Password/SignupPasswordViewModel.swift @@ -2,4 +2,12 @@ import BaseFeature import Combine final class SignupPasswordViewModel: BaseViewModel { + @Published var password: String = "" + @Published var checkPassword: String = "" + + @Published var isNavigatedToName: Bool = false + + func nextButtonDidTap() { + self.isNavigatedToName = true + } } From b40735b39f708bbe28d810bae0713baea18fd1dc Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:29:30 +0900 Subject: [PATCH 29/33] =?UTF-8?q?=E2=9C=A8=20::=20Signup=20Progress=20View?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/SignupProgressView.swift | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Projects/Feature/SignupFeature/Sources/UserInfo/Components/SignupProgressView.swift diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/Components/SignupProgressView.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/Components/SignupProgressView.swift new file mode 100644 index 0000000..a1a93dc --- /dev/null +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/Components/SignupProgressView.swift @@ -0,0 +1,47 @@ +import SwiftUI +import DesignSystem + +enum SignupStep: Int, CaseIterable { + case name = 1 + case studentID = 2 + case gender = 3 + case checkLevel = 4 +} + +struct SignupProgressView: View { + private let step: SignupStep + + init(step: SignupStep) { + self.step = step + } + + var body: some View { + HStack(spacing: 0) { + ForEach(SignupStep.allCases, id: \.self) { step in + Circle() + .fill(self.step.rawValue >= step.rawValue ? Color.Greens.main : Color.Grays.gray900) + .frame(12) + + if step != .checkLevel { + Spacer() + } + } + } + .padding(.horizontal, 24) + .background { + HStack(spacing: 0) { + Color.Greens.secondary + .frame(width: 31, height: 12) + ForEach(1...3, id: \.self) { index in + (index < self.step.rawValue ? Color.Greens.secondary : Color.Grays.gray1000) + .frame(height: 12) + .frame(maxWidth: .infinity) + } + + Color.Grays.gray1000 + .frame(width: 31, height: 12) + } + } + .padding(.vertical, 16) + } +} From ce4f84f9f93877b8840561a8440429f693c70bf4 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:29:37 +0900 Subject: [PATCH 30/33] =?UTF-8?q?=E2=9C=A8=20::=20Signup=20DI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Application/NeedleGenerated.swift | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/Projects/App/Sources/Application/NeedleGenerated.swift b/Projects/App/Sources/Application/NeedleGenerated.swift index 965f872..9dfcff5 100644 --- a/Projects/App/Sources/Application/NeedleGenerated.swift +++ b/Projects/App/Sources/Application/NeedleGenerated.swift @@ -62,26 +62,30 @@ private func factoryb06be35aa893adde971bf47b58f8f304c97af4d5(_ component: Needle return SignupEmailAuthCodeVerifyDependencyaf9da1ebf0e9e5f1b708Provider(appComponent: parent1(component) as! AppComponent) } private class SignupStudentIDDependencyc62f548e51245f5bf42dProvider: SignupStudentIDDependency { - - - init() { - + var signupGenderFactory: any SignupGenderFactory { + return appComponent.signupGenderFactory + } + private let appComponent: AppComponent + init(appComponent: AppComponent) { + self.appComponent = appComponent } } /// ^->AppComponent->SignupStudentIDComponent -private func factorycca12bec445b4f4f6de7e3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { - return SignupStudentIDDependencyc62f548e51245f5bf42dProvider() +private func factorycca12bec445b4f4f6de7f47b58f8f304c97af4d5(_ component: NeedleFoundation.Scope) -> AnyObject { + return SignupStudentIDDependencyc62f548e51245f5bf42dProvider(appComponent: parent1(component) as! AppComponent) } private class SignupGenderDependency65e2a6565372eb41f4acProvider: SignupGenderDependency { - - - init() { - + var signupCheckLevelFactory: any SignupCheckLevelFactory { + return appComponent.signupCheckLevelFactory + } + private let appComponent: AppComponent + init(appComponent: AppComponent) { + self.appComponent = appComponent } } /// ^->AppComponent->SignupGenderComponent -private func factory997eaa831d16af15eee5e3b0c44298fc1c149afb(_ component: NeedleFoundation.Scope) -> AnyObject { - return SignupGenderDependency65e2a6565372eb41f4acProvider() +private func factory997eaa831d16af15eee5f47b58f8f304c97af4d5(_ component: NeedleFoundation.Scope) -> AnyObject { + return SignupGenderDependency65e2a6565372eb41f4acProvider(appComponent: parent1(component) as! AppComponent) } private class SignupCheckLevelDependencye4ec84c7d38354a454aeProvider: SignupCheckLevelDependency { @@ -182,12 +186,12 @@ extension SignupEmailAuthCodeVerifyComponent: Registration { } extension SignupStudentIDComponent: Registration { public func registerItems() { - + keyPathToName[\SignupStudentIDDependency.signupGenderFactory] = "signupGenderFactory-any SignupGenderFactory" } } extension SignupGenderComponent: Registration { public func registerItems() { - + keyPathToName[\SignupGenderDependency.signupCheckLevelFactory] = "signupCheckLevelFactory-any SignupCheckLevelFactory" } } extension SignupCheckLevelComponent: Registration { @@ -236,8 +240,8 @@ private func registerProviderFactory(_ componentPath: String, _ factory: @escapi registerProviderFactory("^->AppComponent->SplashComponent", factoryace9f05f51d68f4c0677e3b0c44298fc1c149afb) registerProviderFactory("^->AppComponent->SignupPasswordComponent", factorye93d1d56840ff97c674af47b58f8f304c97af4d5) registerProviderFactory("^->AppComponent->SignupEmailAuthCodeVerifyComponent", factoryb06be35aa893adde971bf47b58f8f304c97af4d5) - registerProviderFactory("^->AppComponent->SignupStudentIDComponent", factorycca12bec445b4f4f6de7e3b0c44298fc1c149afb) - registerProviderFactory("^->AppComponent->SignupGenderComponent", factory997eaa831d16af15eee5e3b0c44298fc1c149afb) + registerProviderFactory("^->AppComponent->SignupStudentIDComponent", factorycca12bec445b4f4f6de7f47b58f8f304c97af4d5) + registerProviderFactory("^->AppComponent->SignupGenderComponent", factory997eaa831d16af15eee5f47b58f8f304c97af4d5) registerProviderFactory("^->AppComponent->SignupCheckLevelComponent", factory5b23127e837152346fdae3b0c44298fc1c149afb) registerProviderFactory("^->AppComponent->SignupNameComponent", factory71e8fa7f4327b1e25ed0f47b58f8f304c97af4d5) registerProviderFactory("^->AppComponent->SignupEmailVerifyComponent", factory3b1904c76335d70151ebf47b58f8f304c97af4d5) From 27979754d57b988e9addead5044fbff8b56652f3 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 10:59:18 +0900 Subject: [PATCH 31/33] =?UTF-8?q?=F0=9F=93=9D=20::=20bottom=20Button=20?= =?UTF-8?q?=EC=84=A4=EB=AA=85=20=EC=A3=BC=EC=84=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SignupFeature/Sources/Components/BottomButton.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Projects/Feature/SignupFeature/Sources/Components/BottomButton.swift b/Projects/Feature/SignupFeature/Sources/Components/BottomButton.swift index 2a86fa2..6551884 100644 --- a/Projects/Feature/SignupFeature/Sources/Components/BottomButton.swift +++ b/Projects/Feature/SignupFeature/Sources/Components/BottomButton.swift @@ -1,6 +1,9 @@ import SwiftUI import DesignSystem +/// Vstack으로 할 경우 버튼이 잘리는 문제가 발생 +/// ZStack을 사용해 SuperView의 상단으로 띄움 + struct BottomButton: ViewModifier { let text: String let isEditing: Bool From f9c2fa31a7edf756932507b52e48a5f7e8bf765e Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 11:31:03 +0900 Subject: [PATCH 32/33] =?UTF-8?q?=E2=9C=A8=20::=20LevelCheckCellView=20to?= =?UTF-8?q?=20DesignSystem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UserInfo/CheckLevel/SignupCheckLevelViewModel.swift | 1 + .../DesignSystem/Sources/View/CheckLevelCellView.swift} | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) rename Projects/{Feature/SignupFeature/Sources/UserInfo/CheckLevel/Components/LevelCheckCellView.swift => UserInterface/DesignSystem/Sources/View/CheckLevelCellView.swift} (89%) diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelViewModel.swift b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelViewModel.swift index 303f9a3..440ff20 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelViewModel.swift +++ b/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/SignupCheckLevelViewModel.swift @@ -1,5 +1,6 @@ import BaseFeature import Combine +import DesignSystem final class SignupCheckLevelViewModel: BaseViewModel { @Published var selectedLevel: PhysicalLevel = .high diff --git a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/Components/LevelCheckCellView.swift b/Projects/UserInterface/DesignSystem/Sources/View/CheckLevelCellView.swift similarity index 89% rename from Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/Components/LevelCheckCellView.swift rename to Projects/UserInterface/DesignSystem/Sources/View/CheckLevelCellView.swift index 653a775..a1c5029 100644 --- a/Projects/Feature/SignupFeature/Sources/UserInfo/CheckLevel/Components/LevelCheckCellView.swift +++ b/Projects/UserInterface/DesignSystem/Sources/View/CheckLevelCellView.swift @@ -1,22 +1,21 @@ import SwiftUI -import DesignSystem -enum PhysicalLevel { +public enum PhysicalLevel { case high case middle case low } -struct LevelCheckCellView: View { +public struct LevelCheckCellView: View { @Binding var selectedLevel: PhysicalLevel let level: PhysicalLevel - init(_ level: PhysicalLevel, selectedLevel: Binding) { + public init(_ level: PhysicalLevel, selectedLevel: Binding) { _selectedLevel = selectedLevel self.level = level } - var body: some View { + public var body: some View { Button { self.selectedLevel = level } label: { From 84dfaa2d95d451ad4e95e25d95c47760536038e7 Mon Sep 17 00:00:00 2001 From: HongSJae Date: Thu, 25 Apr 2024 14:47:45 +0900 Subject: [PATCH 33/33] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20=EC=97=94?= =?UTF-8?q?=ED=84=B0=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DesignSystem/Sources/TextField/KGTextField.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Projects/UserInterface/DesignSystem/Sources/TextField/KGTextField.swift b/Projects/UserInterface/DesignSystem/Sources/TextField/KGTextField.swift index 0e862a6..cea365c 100644 --- a/Projects/UserInterface/DesignSystem/Sources/TextField/KGTextField.swift +++ b/Projects/UserInterface/DesignSystem/Sources/TextField/KGTextField.swift @@ -72,7 +72,11 @@ public struct KGTextField: View { if !description.isEmpty || isErrorAndNotEmpty { Text(isErrorAndNotEmpty ? errorMessage : description) - .kgFont(.label, weight: .regular, color: isErrorAndNotEmpty ? .System.red : .Grays.gray800) + .kgFont( + .label, + weight: .regular, + color: isErrorAndNotEmpty ? .System.red : .Grays.gray800 + ) } } .padding(.vertical, 8)