Skip to content

Commit

Permalink
Merge pull request #320 from GSM-MSG/317-authentication-input-page-ui
Browse files Browse the repository at this point in the history
 ๐Ÿ”€ :: [#317] ์ธ์ฆ์ œ ์ž…๋ ฅ ํŽ˜์ด์ง€ ํผ๋ธ”๋ฆฌ์‹ฑ
  • Loading branch information
shwaaaa authored Feb 26, 2024
2 parents e28eb98 + faba8f0 commit ff52325
Show file tree
Hide file tree
Showing 18 changed files with 387 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ public extension TargetDependency {
}

public extension TargetDependency.Feature {
static let InputAuthenticationFeatureInterface = TargetDependency.project(
target: ModulePaths.Feature.InputAuthenticationFeature.targetName(type: .interface),
path: .relativeToFeature(ModulePaths.Feature.InputAuthenticationFeature.rawValue)
)
static let InputAuthenticationFeature = TargetDependency.project(
target: ModulePaths.Feature.InputAuthenticationFeature.targetName(type: .sources),
path: .relativeToFeature(ModulePaths.Feature.InputAuthenticationFeature.rawValue)
)
static let InputTeacherInfoFeatureInterface = TargetDependency.project(
target: ModulePaths.Feature.InputTeacherInfoFeature.targetName(type: .interface),
path: .relativeToFeature(ModulePaths.Feature.InputTeacherInfoFeature.rawValue)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public enum ModulePaths {

public extension ModulePaths {
enum Feature: String {
case InputAuthenticationFeature
case InputTeacherInfoFeature
case InputPrizeInfoFeature
case MyPageFeature
Expand Down
1 change: 1 addition & 0 deletions Projects/App/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ let targets: [Target] = [
.Feature.InputLanguageInfoFeature,
.Feature.InputProjectInfoFeature,
.Feature.InputTeacherInfoFeature,
.Feature.InputAuthenticationFeature,
.Feature.MainFeature,
.Feature.SplashFeature,
.Feature.TechStackAppendFeature,
Expand Down
1 change: 1 addition & 0 deletions Projects/App/Sources/Application/NeedleGenerated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import FileDomainInterface
import FilterFeature
import FilterFeatureInterface
import Foundation
import InputAuthenticationFeatureInterface
import InputCertificateInfoFeature
import InputCertificateInfoFeatureInterface
import InputInformationFeature
Expand Down
72 changes: 72 additions & 0 deletions Projects/Core/DesignSystem/Sources/TextField/SMSTextEditor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import SwiftUI
import ViewUtil

public struct SMSTextEditor: View {
@Binding var text: String
@FocusState var isFocused: Bool
var placeholder: String
var errorText: String
var isError: Bool
var isOnClear: Bool
var onSubmit: () -> Void

public init(
_ placeholder: String = "",
text: Binding<String>,
errorText: String = "",
isError: Bool = false,
isOnClear: Bool = true,
onSubmit: @escaping () -> Void = {}
) {
self._text = text
self.placeholder = placeholder
self.errorText = errorText
self.isError = isError
self.isOnClear = isOnClear
self.onSubmit = onSubmit
}

public var body: some View {
VStack(alignment: .leading, spacing: 8) {
ZStack(alignment: .topLeading) {
HStack {
TextEditor(text: $text)
.onSubmit(onSubmit)
.smsFont(.body1, color: .neutral(.n50))
.focused($isFocused)

SMSIcon(.xmark)
.buttonWrapper {
text = ""
}
.conditional(text.isNotEmpty && isOnClear)
}
.colorMultiply(.sms(.neutral(.n10)))
.frame(height: 216)
.padding(.horizontal, 8)
.background(Color.sms(.neutral(.n10)))
.cornerRadius(8)
.overlay {
RoundedRectangle(cornerRadius: 8)
.strokeBorder(Color.sms(.primary(.p2)))
.conditional(isFocused)
}
.onTapGesture {
isFocused = true
}

if text.isEmpty {
Text(placeholder)
.smsFont(.body1, color: .neutral(.n30))
.padding(.top, 11)
.padding(.leading, 12)
}
}
ConditionView(isError && errorText.isNotEmpty) {
Text(errorText)
.padding(.leading, 8)
.smsFont(.caption1, color: .error(.e2))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import BaseFeature
import SwiftUI
import InputAuthenticationFeatureInterface
@testable import InputAuthenticationFeature

final class DummyInputAuthenticationDelegate: InputAuthenticationDelegate {
func completeToInputInputAuthentication() {}
}

@main
struct InputAuthenticationApp: App {
var body: some Scene {
WindowGroup {
let model = InputAuthenticationModel()
let intent = InputAuthenticationIntent(
model: model,
inputAuthenticationDelegate: DummyInputAuthenticationDelegate()
)
let container = MVIContainer(
intent: intent as InputAuthenticationIntentProtocol,
model: model as InputAuthenticationStateProtocol,
modelChangePublisher: model.objectWillChange
)
InputAuthenticationView(container: container)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import SwiftUI

public protocol InputAuthenticationBuildable {
associatedtype ViewType: View
func makeView(delegate: InputAuthenticationDelegate) -> ViewType
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public protocol InputAuthenticationDelegate: AnyObject {
func completeToInputInputAuthentication()
}
12 changes: 12 additions & 0 deletions Projects/Feature/InputAuthenticationFeature/Project.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin

let project = Project.makeModule(
name: ModulePaths.Feature.InputAuthenticationFeature.rawValue,
product: .staticLibrary,
targets: [.interface, .unitTest, .demo],
internalDependencies: [
.Feature.BaseFeature
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import BaseFeature
import InputAuthenticationFeatureInterface
import NeedleFoundation
import SwiftUI

public protocol InputAuthenticationDependency: Dependency {}

public final class InputAuthenticationComponent: Component<InputAuthenticationDependency>, InputAuthenticationBuildable {
public func makeView(delegate: InputAuthenticationDelegate) -> some View {
let model = InputAuthenticationModel()
let intent = InputAuthenticationIntent(model: model, inputAuthenticationDelegate: delegate)
let container = MVIContainer(
intent: intent as InputAuthenticationIntentProtocol,
model: model as InputAuthenticationStateProtocol,
modelChangePublisher: model.objectWillChange
)
return InputAuthenticationView(container: container)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import Foundation
import InputAuthenticationFeatureInterface

final class InputAuthenticationIntent: InputAuthenticationIntentProtocol {
private weak var model: (any InputAuthenticationActionProtocol)?
private weak var inputAuthenticationDelegate: (any InputAuthenticationDelegate)?

init(
model: any InputAuthenticationActionProtocol,
inputAuthenticationDelegate: any InputAuthenticationDelegate
) {
self.model = model
self.inputAuthenticationDelegate = inputAuthenticationDelegate
}

func updateAuthenticationTitle(index: Int, title: String) {
model?.updateAuthenticationTitle(index: index, title: title)
}

func updateAuthenticationContent(index: Int, content: String) {
model?.updateAuthenticationContent(index: index, content: content)
}

func completeButtonDidTap() {
inputAuthenticationDelegate?.completeToInputInputAuthentication()
}

func authenticationAppendButtonDidTap() {
model?.appendEmptyAuthentication()
}

func appendEmptyAuthentication() {
model?.appendEmptyAuthentication()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Foundation

protocol InputAuthenticationIntentProtocol {
func completeButtonDidTap()
func updateAuthenticationTitle(index: Int, title: String)
func updateAuthenticationContent(index: Int, content: String)
func authenticationAppendButtonDidTap()
func appendEmptyAuthentication()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Foundation

final class InputAuthenticationModel: ObservableObject, InputAuthenticationStateProtocol {
@Published var authenticationTitle: String = ""
@Published var authenticationContent: String = ""
@Published var authenticationList: [AuthenticationInfo] = []
}

extension InputAuthenticationModel: InputAuthenticationActionProtocol {
func appendEmptyAuthentication() {
let newAuthentication = AuthenticationInfo(
title: "",
content: ""
)
self.authenticationList.append(newAuthentication)
}

func updateAuthenticationTitle(index: Int, title: String) {
guard authenticationList[safe: index] != nil else { return }
self.authenticationList[index].title = title
}

func updateAuthenticationContent(index: Int, content: String) {
guard authenticationList[safe: index] != nil else { return }
self.authenticationList[index].content = content
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Foundation

struct AuthenticationInfo: Equatable {
var title: String
var content: String
}

protocol InputAuthenticationStateProtocol {
var authenticationTitle: String { get }
var authenticationContent: String { get }
var authenticationList: [AuthenticationInfo] { get }
}

protocol InputAuthenticationActionProtocol: AnyObject {
func updateAuthenticationTitle(index: Int, title: String)
func updateAuthenticationContent(index: Int, content: String)
func appendEmptyAuthentication()
}
Loading

0 comments on commit ff52325

Please sign in to comment.