Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

๐Ÿ”€ :: [#317] ์ธ์ฆ์ œ ์ž…๋ ฅ ํŽ˜์ด์ง€ ํผ๋ธ”๋ฆฌ์‹ฑ #320

Merged
merged 2 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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,29 @@
import Foundation

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

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

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,19 @@
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 }
var collapsedAuthentication: [Bool] { get }
}

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