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

feat: LOButton, LOTextField 컴포넌트 생성, SignUpViewController 뷰 구현 #14

Merged
merged 6 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
36 changes: 36 additions & 0 deletions iOS/Layover/Layover.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
194552132B03AFFC00299768 /* DummyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194552122B03AFFC00299768 /* DummyViewController.swift */; };
19C7AFCE2B02410F003B35F2 /* AuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7AFCD2B02410F003B35F2 /* AuthManager.swift */; };
19C7AFD62B02584D003B35F2 /* KeychainStored.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7AFD52B02584D003B35F2 /* KeychainStored.swift */; };
FC2511A02B045C0A004717BC /* SignUpInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC25119F2B045C0A004717BC /* SignUpInteractor.swift */; };
FC2511A22B045C3F004717BC /* SignUpPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2511A12B045C3F004717BC /* SignUpPresenter.swift */; };
FC2511A42B045D6C004717BC /* SignUpModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2511A32B045D6C004717BC /* SignUpModels.swift */; };
FC2511A62B049020004717BC /* SignUpConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2511A52B049020004717BC /* SignUpConfigurator.swift */; };
FC49758F2B03432800D8627F /* Pretendard-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FC4975862B03432700D8627F /* Pretendard-SemiBold.ttf */; };
FC4975932B03432800D8627F /* Pretendard-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FC49758A2B03432800D8627F /* Pretendard-Bold.ttf */; };
FC4975942B03432800D8627F /* Pretendard-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FC49758B2B03432800D8627F /* Pretendard-Regular.ttf */; };
Expand All @@ -46,6 +50,9 @@
FC7E45922AFF747A004F155A /* DummyScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7E45912AFF747A004F155A /* DummyScene.swift */; };
FC7E45942AFF7486004F155A /* DummyDesignSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7E45932AFF7486004F155A /* DummyDesignSystem.swift */; };
FC7E45962AFF7497004F155A /* DummyExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7E45952AFF7497004F155A /* DummyExtension.swift */; };
FCEE0FF22B036B6000195BBE /* LOButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCEE0FF12B036B6000195BBE /* LOButton.swift */; };
FCEE0FF62B03804000195BBE /* LOTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCEE0FF52B03804000195BBE /* LOTextField.swift */; };
FCEE0FFA2B03AF8500195BBE /* SignUpViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCEE0FF92B03AF8400195BBE /* SignUpViewController.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -79,6 +86,10 @@
194552122B03AFFC00299768 /* DummyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyViewController.swift; sourceTree = "<group>"; };
19C7AFCD2B02410F003B35F2 /* AuthManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthManager.swift; sourceTree = "<group>"; };
19C7AFD52B02584D003B35F2 /* KeychainStored.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainStored.swift; sourceTree = "<group>"; };
FC25119F2B045C0A004717BC /* SignUpInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpInteractor.swift; sourceTree = "<group>"; };
FC2511A12B045C3F004717BC /* SignUpPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpPresenter.swift; sourceTree = "<group>"; };
FC2511A32B045D6C004717BC /* SignUpModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpModels.swift; sourceTree = "<group>"; };
FC2511A52B049020004717BC /* SignUpConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpConfigurator.swift; sourceTree = "<group>"; };
FC4975862B03432700D8627F /* Pretendard-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-SemiBold.ttf"; sourceTree = "<group>"; };
FC49758A2B03432800D8627F /* Pretendard-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Bold.ttf"; sourceTree = "<group>"; };
FC49758B2B03432800D8627F /* Pretendard-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Regular.ttf"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -108,6 +119,9 @@
FC7E45912AFF747A004F155A /* DummyScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyScene.swift; sourceTree = "<group>"; };
FC7E45932AFF7486004F155A /* DummyDesignSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyDesignSystem.swift; sourceTree = "<group>"; };
FC7E45952AFF7497004F155A /* DummyExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyExtension.swift; sourceTree = "<group>"; };
FCEE0FF12B036B6000195BBE /* LOButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LOButton.swift; sourceTree = "<group>"; };
FCEE0FF52B03804000195BBE /* LOTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LOTextField.swift; sourceTree = "<group>"; };
FCEE0FF92B03AF8400195BBE /* SignUpViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SignUpViewController.swift; path = ../SignUpViewController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -302,6 +316,7 @@
isa = PBXGroup;
children = (
1945520E2B03AEA400299768 /* Configurator.swift */,
FCEE0FFB2B03AFAA00195BBE /* SingUpScene */,
194552032B038FC400299768 /* Tabbar */,
194551EB2B037F1E00299768 /* Login */,
FC7E45912AFF747A004F155A /* DummyScene.swift */,
Expand All @@ -313,6 +328,8 @@
isa = PBXGroup;
children = (
FC7E45932AFF7486004F155A /* DummyDesignSystem.swift */,
FCEE0FF12B036B6000195BBE /* LOButton.swift */,
FCEE0FF52B03804000195BBE /* LOTextField.swift */,
);
path = DesignSystem;
sourceTree = "<group>";
Expand All @@ -336,6 +353,18 @@
path = Resources;
sourceTree = "<group>";
};
FCEE0FFB2B03AFAA00195BBE /* SingUpScene */ = {
isa = PBXGroup;
children = (
FCEE0FF92B03AF8400195BBE /* SignUpViewController.swift */,
FC25119F2B045C0A004717BC /* SignUpInteractor.swift */,
FC2511A12B045C3F004717BC /* SignUpPresenter.swift */,
FC2511A32B045D6C004717BC /* SignUpModels.swift */,
FC2511A52B049020004717BC /* SignUpConfigurator.swift */,
);
path = SingUpScene;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -479,12 +508,15 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FC2511A42B045D6C004717BC /* SignUpModels.swift in Sources */,
FC68E2A12B023326001AABFF /* EndPoint.swift in Sources */,
FC68E2A32B0233BC001AABFF /* NetworkError.swift in Sources */,
FC7E45962AFF7497004F155A /* DummyExtension.swift in Sources */,
1945520D2B0399E500299768 /* MainTabBarViewController.swift in Sources */,
194551F62B037F2D00299768 /* LoginViewController.swift in Sources */,
FC7E458E2AFF7462004F155A /* DummyService.swift in Sources */,
FCEE0FF22B036B6000195BBE /* LOButton.swift in Sources */,
FC2511A62B049020004717BC /* SignUpConfigurator.swift in Sources */,
194552132B03AFFC00299768 /* DummyViewController.swift in Sources */,
194551F22B037F2D00299768 /* LoginPresenter.swift in Sources */,
194552022B038B8300299768 /* OSLog+.swift in Sources */,
Expand All @@ -496,15 +528,19 @@
FC7E458A2AFF70FB004F155A /* ViewController.swift in Sources */,
FC7E453A2AFEB623004F155A /* AppDelegate.swift in Sources */,
FC68E29B2B02325D001AABFF /* Requestable.swift in Sources */,
FC2511A22B045C3F004717BC /* SignUpPresenter.swift in Sources */,
FC68E29D2B02326A001AABFF /* Responsable.swift in Sources */,
FC2511A02B045C0A004717BC /* SignUpInteractor.swift in Sources */,
19C7AFCE2B02410F003B35F2 /* AuthManager.swift in Sources */,
FC7E45902AFF746E004F155A /* DummyWorker.swift in Sources */,
1945520F2B03AEA400299768 /* Configurator.swift in Sources */,
FC68E29F2B023315001AABFF /* HTTPMethod.swift in Sources */,
FCEE0FFA2B03AF8500195BBE /* SignUpViewController.swift in Sources */,
194551F32B037F2D00299768 /* LoginWorker.swift in Sources */,
FC7E45942AFF7486004F155A /* DummyDesignSystem.swift in Sources */,
194551F72B037F2D00299768 /* LoginInteractor.swift in Sources */,
FC7E453C2AFEB623004F155A /* SceneDelegate.swift in Sources */,
FCEE0FF62B03804000195BBE /* LOTextField.swift in Sources */,
FC68E2A52B0233D3001AABFF /* Provider.swift in Sources */,
FC7E45922AFF747A004F155A /* DummyScene.swift in Sources */,
194552112B03AF2B00299768 /* MainTabBarConfigurator.swift in Sources */,
Expand Down
69 changes: 69 additions & 0 deletions iOS/Layover/Layover/DesignSystem/LOButton.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// LOButton.swift
// Layover
//
// Created by kong on 2023/11/14.
//

import UIKit

final class LOButton: UIButton {
anyukyung marked this conversation as resolved.
Show resolved Hide resolved

// MARK: - Button Type

enum Style {
case basic
}

// MARK: - Properties

private let style: Style

private var buttonBackgroundColor: UIColor {
switch style {
case .basic:
return isEnabled ? .primaryPurple : .darkGrey
}
}

private var buttonTitleColor: UIColor {
switch style {
case .basic:
return isEnabled ? .white : .grey500
}
}

override var isEnabled: Bool {
didSet {
setColors()
}
}

// MARK: - Initializer

init(style: Style) {
self.style = style
super.init(frame: .zero)
setInitialStateUI()
}

required init?(coder: NSCoder) {
self.style = .basic
super.init(coder: coder)
setInitialStateUI()
}

// MARK: - Custom Method

private func setInitialStateUI() {
layer.cornerRadius = 8
titleLabel?.font = .loFont(type: .body2Semibold)
setColors()
}

private func setColors() {
setTitleColor(buttonTitleColor, for: state)
backgroundColor = buttonBackgroundColor
}

}
67 changes: 67 additions & 0 deletions iOS/Layover/Layover/DesignSystem/LOTextField.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// LOTextField.swift
// Layover
//
// Created by kong on 2023/11/14.
//

import UIKit

final class LOTextField: UITextField {

override var placeholder: String? {
didSet {
setPlaceholderColor()
}
}

init() {
super.init(frame: .zero)
setUI()
delegate = self
}

required init?(coder: NSCoder) {
super.init(coder: coder)
setUI()
delegate = self
}

private func setUI() {
layer.cornerRadius = 8
layer.borderWidth = 1
layer.borderColor = UIColor.grey500.cgColor
backgroundColor = UIColor.clear
setPadding()
}
private func setPlaceholderColor() {
guard let placeholder else { return }
attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [.foregroundColor: UIColor.grey500])
}

private func setPadding() {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 16, height: frame.height))
leftView = paddingView
leftViewMode = .always
rightView = paddingView
rightViewMode = .always
}

private func setFocusStateColors(isFocused: Bool) {
let color = isFocused ? UIColor.grey200 : UIColor.grey500
layer.borderColor = color.cgColor
textColor = color
}

}

extension LOTextField: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
setFocusStateColors(isFocused: true)
}

func textFieldDidEndEditing(_ textField: UITextField) {
layer.borderColor = UIColor.grey500.cgColor
setFocusStateColors(isFocused: false)
}
}
132 changes: 132 additions & 0 deletions iOS/Layover/Layover/Scenes/SignUpViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
//
// SignUpViewController.swift
// Layover
//
// Created by kong on 2023/11/14.
// Copyright © 2023 CodeBomber. All rights reserved.
//

import UIKit

protocol SignUpDisplayLogic: AnyObject {
func displayNicknameValidation(response: SignUpModels.ValidateNickname.ViewModel)
func displayNickanmeDuplication()
}

final class SignUpViewController: UIViewController {

// MARK: - UI Components

private let titleLabel: UILabel = {
let label = UILabel()
label.text = "여정 기록을 위한\n닉네임을 입력해주세요."
label.numberOfLines = 0
label.font = .loFont(type: .header2)
label.textColor = .white
return label
}()
anyukyung marked this conversation as resolved.
Show resolved Hide resolved

private lazy var nicknameTextfield: LOTextField = {
let textField = LOTextField()
textField.placeholder = "닉네임을 입력해주세요."
textField.addTarget(self, action: #selector(setUpTextFieldState(_:)), for: .editingChanged)
return textField
}()

private let nicknameAlertLabel: UILabel = {
let label = UILabel()
label.font = .loFont(type: .caption)
label.textColor = .error
return label
}()

private let checkDuplicateNicknameButton: LOButton = {
let button = LOButton(style: .basic)
button.isEnabled = false
button.setTitle("중복확인", for: .normal)
return button
}()

private let confirmButton: LOButton = {
let button = LOButton(style: .basic)
button.isEnabled = false
button.setTitle("회원가입", for: .normal)
return button
}()

var interactor: SignUpBusinessLogic?

// MARK: - Life Cycle

override func viewDidLoad() {
super.viewDidLoad()
SignUpConfigurator.shared.configure(self)
setUI()

// TODO: Base ViewController 로직으로 분리
view.backgroundColor = .background
addTapGesture()
}

// MARK: - UI + Layout

private func setUI() {
[titleLabel, nicknameTextfield, nicknameAlertLabel, checkDuplicateNicknameButton, confirmButton].forEach {
view.addSubview($0)
$0.translatesAutoresizingMaskIntoConstraints = false
}

NSLayoutConstraint.activate([
titleLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 17),
titleLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16),
titleLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16),

nicknameTextfield.heightAnchor.constraint(equalToConstant: 44),
nicknameTextfield.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 17),
nicknameTextfield.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16),
nicknameTextfield.trailingAnchor.constraint(equalTo: checkDuplicateNicknameButton.leadingAnchor, constant: -16),

nicknameAlertLabel.topAnchor.constraint(equalTo: nicknameTextfield.bottomAnchor, constant: 5),
nicknameAlertLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16),
nicknameTextfield.trailingAnchor.constraint(equalTo: nicknameTextfield.trailingAnchor),

checkDuplicateNicknameButton.heightAnchor.constraint(equalToConstant: 44),
checkDuplicateNicknameButton.widthAnchor.constraint(equalToConstant: 83),
checkDuplicateNicknameButton.centerYAnchor.constraint(equalTo: nicknameTextfield.centerYAnchor),
checkDuplicateNicknameButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16),

confirmButton.heightAnchor.constraint(equalToConstant: 50),
confirmButton.bottomAnchor.constraint(equalTo: view.keyboardLayoutGuide.topAnchor),
confirmButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16),
confirmButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16)
])
}

// MARK: - Custom Method

private func addTapGesture() {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard(_:)))
view.addGestureRecognizer(tapGesture)
}

@objc private func setUpTextFieldState(_ sender: UITextField) {
guard let nickname = sender.text else { return }
interactor?.validateNickname(with: SignUpModels.ValidateNickname.Request(nickname: nickname))
}

@objc private func hideKeyboard(_ sender: Any) {
view.endEditing(true)
}
}

extension SignUpViewController: SignUpDisplayLogic {
func displayNicknameValidation(response: SignUpModels.ValidateNickname.ViewModel) {
nicknameAlertLabel.isHidden = response.canCheckDuplication
checkDuplicateNicknameButton.isEnabled = response.canCheckDuplication
nicknameAlertLabel.text = response.alertDescription
}

func displayNickanmeDuplication() {

}
}
Loading