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

🔀 :: 정보 입력 - 근무 조건 페이지 정보 검사 및 입력 전달 #108

Merged
merged 7 commits into from
May 23, 2023
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
public enum FormOfEmployment: String, Encodable {
public enum FormOfEmployment: String, Codable, CaseIterable {
case fullTime = "FULL_TIME"
case temporary = "TEMPORARY"
case constract = "CONSTRACT"
case intern = "INTERN"
}

public extension FormOfEmployment {
func display() -> String {
switch self {
case .fullTime: return "정규직"
case .temporary: return "비정규직"
case .constract: return "계약직"
case .intern: return "인턴"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public enum MilitaryService: String, Encodable {
public enum MilitaryService: String, Codable {
case hope = "HOPE"
case notHope = "NOT_HOPE"
case noMatter = "NO_MATTER"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ extension InputInformationIntent: InputWorkDelegate {
model?.prevButtonDidTap()
}

func completeToInputWork() {
func completeToInputWork(input: InputWorkInformationObject) {
model?.updateInputWorkInformationObject(object: input)
model?.nextButtonDidTap()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import Foundation
import InputProfileInfoFeatureInterface
import InputSchoolLifeInfoFeatureInterface
import InputWorkInfoFeatureInterface

final class InputInformationModel: ObservableObject, InputInformationStateProtocol {
@Published var phase: InformationPhase = .profile
@Published var inputProfileInformationObject: InputProfileInformationObject?
@Published var inputSchoolLifeInformationObject: InputSchoolLifeInformationObject?
var inputProfileInformationObject: InputProfileInformationObject?
var inputSchoolLifeInformationObject: InputSchoolLifeInformationObject?
var inputWorkInfomationObject: InputWorkInformationObject?
}

extension InputInformationModel: InputInformationActionProtocol {
Expand All @@ -30,4 +32,8 @@ extension InputInformationModel: InputInformationActionProtocol {
func updateInputSchoolLifeInformationObject(object: InputSchoolLifeInformationObject) {
self.inputSchoolLifeInformationObject = object
}

func updateInputWorkInformationObject(object: InputWorkInformationObject) {
self.inputWorkInfomationObject = object
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation
import InputProfileInfoFeatureInterface
import InputSchoolLifeInfoFeatureInterface
import InputWorkInfoFeatureInterface

enum InformationPhase: CaseIterable {
case profile
Expand All @@ -15,11 +16,13 @@ protocol InputInformationStateProtocol {
var phase: InformationPhase { get }
var inputProfileInformationObject: InputProfileInformationObject? { get }
var inputSchoolLifeInformationObject: InputSchoolLifeInformationObject? { get }
var inputWorkInfomationObject: InputWorkInformationObject? { get }
}

protocol InputInformationActionProtocol: AnyObject {
func prevButtonDidTap()
func nextButtonDidTap()
func updateInputProfileInformationObject(object: InputProfileInformationObject)
func updateInputSchoolLifeInformationObject(object: InputSchoolLifeInformationObject)
func updateInputWorkInformationObject(object: InputWorkInformationObject)
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,21 @@ final class InputSchoolLifeInfoIntent: InputSchoolLifeInfoIntentProtocol {
func nextButtonDidTap(state: any InputSchoolLifeInfoStateProtocol) {
var errorSet = Set<InputSchoolLifeErrorField>()

if Int(state.authenticationScroe) != nil {
if Int(state.authenticationScore) == nil || state.authenticationScore.isEmpty {
errorSet.insert(.gsmAuthentication)
}

if state.hwpFileURL != nil {
if state.hwpFileURL == nil {
errorSet.insert(.hwp)
}

model?.updateErrorField(field: errorSet)
guard
let gsmScore = Int(state.authenticationScroe),
let gsmScore = Int(state.authenticationScore),
let hwpURL = state.hwpFileURL,
let hwpData = try? Data(contentsOf: hwpURL)
let hwpData = try? Data(contentsOf: hwpURL),
errorSet.isEmpty
else {
model?.updateErrorField(field: errorSet)
return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ enum InputSchoolLifeErrorField: Hashable {
}

final class InputSchoolLifeInfoModel: ObservableObject, InputSchoolLifeInfoStateProtocol {
@Published var authenticationScroe: String = ""
@Published var authenticationScore: String = ""
@Published var isPresentedHWPFileImporter: Bool = false
@Published var hwpFileURL: URL?
var hwpFilename: String {
Expand All @@ -20,7 +20,7 @@ final class InputSchoolLifeInfoModel: ObservableObject, InputSchoolLifeInfoState

extension InputSchoolLifeInfoModel: InputSchoolLifeInfoActionProtocol {
func updateAuthenticationScore(score: String) {
self.authenticationScroe = score
self.authenticationScore = score
}

func updateIsPresentedHWPFileImporter(isPresented: Bool) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation

protocol InputSchoolLifeInfoStateProtocol {
var authenticationScroe: String { get }
var authenticationScore: String { get }
var isPresentedHWPFileImporter: Bool { get }
var hwpFileURL: URL? { get }
var hwpFilename: String { get }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct InputSchoolLifeInfoView: View {
SMSTextField(
"인증제 점수 입력",
text: Binding(
get: { state.authenticationScroe },
get: { state.authenticationScore },
set: intent.updateAuthenticationScore(score:)
),
errorText: "인증제 점수를 입력해주세요",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,20 @@ final class InputSchoolLifeInfoFeatureTests: XCTestCase {

func test_update_authentication_score() {
sut.intent.updateAuthenticationScore(score: "2")
XCTAssertEqual(sut.model.authenticationScroe, "2")
XCTAssertEqual(sut.model.authenticationScore, "2")

sut.intent.updateAuthenticationScore(score: "123")
XCTAssertEqual(sut.model.authenticationScroe, "123")
XCTAssertEqual(sut.model.authenticationScore, "123")

sut.intent.updateAuthenticationScore(score: "ASDF")
XCTAssertNotEqual(sut.model.authenticationScroe, "ASDF")
XCTAssertNotEqual(sut.model.authenticationScore, "ASDF")

sut.intent.updateAuthenticationScore(score: "CXZ")
XCTAssertNotEqual(sut.model.authenticationScroe, "CXZ")
XCTAssertNotEqual(sut.model.authenticationScore, "CXZ")

let randomScore = Int.random(in: 0...100)
sut.intent.updateAuthenticationScore(score: "\(randomScore)")
XCTAssertEqual(sut.model.authenticationScroe, "\(randomScore)")
XCTAssertEqual(sut.model.authenticationScore, "\(randomScore)")
}

func test_file_importer_sheet() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
public protocol InputWorkDelegate: AnyObject {
func workPrevButtonDidTap()
func completeToInputWork()
func completeToInputWork(input: InputWorkInformationObject)
}

public struct InputWorkInformationObject {
public let formOfEmployment: String
public let salary: Int
public let workRegion: [String]

public init(formOfEmployment: String, salary: Int, workRegion: [String]) {
self.formOfEmployment = formOfEmployment
self.salary = salary
self.workRegion = workRegion
}
}
3 changes: 2 additions & 1 deletion Projects/Feature/InputWorkInfoFeature/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ let project = Project.makeModule(
product: .staticLibrary,
targets: [.interface, .unitTest],
internalDependencies: [
.Feature.BaseFeature
.Feature.BaseFeature,
.Domain.StudentDomainInterface
]
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation
import InputWorkInfoFeatureInterface
import StudentDomainInterface

final class InputWorkInfoIntent: InputWorkInfoIntentProtocol {
private weak var model: (any InputWorkInfoActionProtocol)?
Expand Down Expand Up @@ -29,6 +30,10 @@ final class InputWorkInfoIntent: InputWorkInfoIntentProtocol {
model?.updateSalary(salary: salary)
}

func updateFormOfEmployment(form: FormOfEmployment) {
model?.updateFormOfEmployment(form: form)
}

func formOfEmployeementSheetIsRequired() {
model?.updateIsPresentedFormOfEmployeementSheet(isPresented: true)
}
Expand All @@ -41,7 +46,13 @@ final class InputWorkInfoIntent: InputWorkInfoIntentProtocol {
inputWorkDelegate?.workPrevButtonDidTap()
}

func nextButtonDidTap() {
inputWorkDelegate?.completeToInputWork()
func nextButtonDidTap(state: any InputWorkInfoStateProtocol) {
let input = InputWorkInformationObject(
formOfEmployment: state.formOfEmployment.rawValue,
salary: Int(state.salary) ?? 0,
workRegion: state.workRegionList
.filter { !$0.isEmpty }
)
inputWorkDelegate?.completeToInputWork(input: input)
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import Foundation
import StudentDomainInterface

protocol InputWorkInfoIntentProtocol {
func appendWorkRegion()
func updateWorkRegion(region: String, at index: Int)
func deleteWorkRegion(at index: Int)
func updateSalary(salary: String)
func updateFormOfEmployment(form: FormOfEmployment)
func formOfEmployeementSheetIsRequired()
func formOfEmployeementSheetDismissed()
func prevButtonDidTap()
func nextButtonDidTap()
func nextButtonDidTap(state: any InputWorkInfoStateProtocol)
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import Foundation
import FoundationUtil
import StudentDomainInterface

final class InputWorkInfoModel: ObservableObject, InputWorkInfoStateProtocol {
private let numberFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter
}()
@Published var workRegionList: [String] = [""]
@Published var salary: String = ""
@Published var formOfEmployment: FormOfEmployment = .fullTime
@Published var isPresentedFormOfEmployeementSheet: Bool = false
var salaryDisplay: String {
guard !salary.isEmpty else { return "상관없음" }
return "\(numberFormatter.string(for: Int(salary)) ?? "0") 만원"
}
}

extension InputWorkInfoModel: InputWorkInfoActionProtocol {
Expand All @@ -22,7 +33,11 @@ extension InputWorkInfoModel: InputWorkInfoActionProtocol {
}

func updateSalary(salary: String) {
self.salary = salary
self.salary = Int(salary).map { String(min($0, 9999)) } ?? salary
}

func updateFormOfEmployment(form: FormOfEmployment) {
self.formOfEmployment = form
}

func updateIsPresentedFormOfEmployeementSheet(isPresented: Bool) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import Foundation
import StudentDomainInterface

protocol InputWorkInfoStateProtocol {
var workRegionList: [String] { get }
var salary: String { get }
var salaryDisplay: String { get }
var formOfEmployment: FormOfEmployment { get }
var isPresentedFormOfEmployeementSheet: Bool { get }
}

Expand All @@ -11,5 +14,6 @@ protocol InputWorkInfoActionProtocol: AnyObject {
func updateWorkRegion(region: String, at index: Int)
func deleteWorkRegion(at index: Int)
func updateSalary(salary: String)
func updateFormOfEmployment(form: FormOfEmployment)
func updateIsPresentedFormOfEmployeementSheet(isPresented: Bool)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import BaseFeature
import DesignSystem
import FoundationUtil
import SwiftUI
import StudentDomainInterface
import ViewUtil

struct InputWorkInfoView: View {
Expand All @@ -22,24 +23,36 @@ struct InputWorkInfoView: View {
pageTitleView()

VStack(spacing: 24) {
SMSTextField("정규직", text: .constant(""))
.disabled(true)
.overlay(alignment: .trailing) {
SMSIcon(.downChevron)
.padding(.trailing, 12)
}
.titleWrapper("희망 고용 형태")
.onTapGesture {
intent.formOfEmployeementSheetIsRequired()
}

SMSTextField(
"희망 연봉 (10,000원 단위)",
"정규직",
text: Binding(
get: { state.salary },
set: intent.updateSalary(salary:)
)
get: { state.formOfEmployment.display() },
set: { _ in }
),
isOnClear: false
)
.disabled(true)
.overlay(alignment: .trailing) {
SMSIcon(.downChevron)
.padding(.trailing, 12)
}
.titleWrapper("희망 고용 형태")
.onTapGesture {
intent.formOfEmployeementSheetIsRequired()
}

VStack(alignment: .leading, spacing: 4) {
SMSTextField(
"희망 연봉 (10,000원 단위)",
text: Binding(
get: { state.salary },
set: intent.updateSalary(salary:)
)
)

Text(state.salaryDisplay)
.smsFont(.caption1, color: .neutral(.n30))
}
.titleWrapper("희망 연봉")

workRegionList()
Expand All @@ -56,7 +69,7 @@ struct InputWorkInfoView: View {
.frame(maxWidth: proxy.size.width / 3)

CTAButton(text: "다음") {
intent.nextButtonDidTap()
intent.nextButtonDidTap(state: state)
}
.frame(maxWidth: .infinity)
}
Expand Down Expand Up @@ -127,17 +140,22 @@ struct InputWorkInfoView: View {
@ViewBuilder
func formOfEmployeementList() -> some View {
VStack(spacing: 16) {
ForEach(0..<4, id: \.self) { index in
ForEach(FormOfEmployment.allCases, id: \.self) { formOfEmployment in
HStack {
Text("\(index)")
Text(formOfEmployment.display())
.smsFont(.body1, color: .neutral(.n50))

Spacer()

Circle()
.fill(Color.sms(.primary(.p2)))
.frame(width: 24, height: 24)
SMSSelectionControls(
isSeleted: Binding(
get: { state.formOfEmployment == formOfEmployment },
set: { $0 ? intent.updateFormOfEmployment(form: formOfEmployment) : () }
)
)
.buttonWrapper {}
}
.animation(.default, value: state.formOfEmployment)
.padding(.horizontal, 20)
}
}
Expand Down