Skip to content

Commit

Permalink
Merge pull request #182 from 0inn/feat/#159
Browse files Browse the repository at this point in the history
[Feat] #159 - 출석하기 UI 구현
  • Loading branch information
0inn authored Apr 21, 2023
2 parents 3578d6b + e0e4302 commit 9e14846
Show file tree
Hide file tree
Showing 27 changed files with 886 additions and 36 deletions.
10 changes: 10 additions & 0 deletions SOPT-iOS/Projects/Core/Sources/Extension/Foundation+/String+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,14 @@ public extension String {
return dateFormatter.string(from: self.toDate())
}
}

/// 맨 앞 문자열 가져오는 메서드
func getFirst() -> String? {
return map({String($0)}).first
}

/// 맨 뒤 문자열 가져오는 메서트
func getLast() -> String? {
return map({String($0)}).last
}
}

This file was deleted.

3 changes: 3 additions & 0 deletions SOPT-iOS/Projects/Core/Sources/Literals/StringLiterals.swift
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ public struct I18N {
public static let beforeAttendance = "출석 전"
public static let completeAttendacne = "출석완료"
public static let giveFeedback = "세션 피드백하기"

public static let inputCodeDescription = "출석 코드 다섯 자리를 입력해 주세요."
public static let codeMismatch = "코드가 일치하지 않아요!"
}

public struct MyPage {
Expand Down
2 changes: 1 addition & 1 deletion SOPT-iOS/Projects/Core/Sources/Utils/addToolBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public extension UIViewController {
self.view.endEditing(true)
}

func addTapGesture() {
func hideKeyboard() {
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyBoard))
self.view.addGestureRecognizer(tap)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// AttendanceRepository.swift
// Data
//
// Created by 김영인 on 2023/04/16.
// Copyright © 2023 SOPT-iOS. All rights reserved.
//

import Combine

import Core
import Domain
import Network

public class AttendanceRepository {

private let attendanceService: AttendanceService
private let cancelBag = CancelBag()

public init(service: AttendanceService) {
self.attendanceService = service
}
}

extension AttendanceRepository: AttendanceRepositoryInterface {

public func fetchLectureRound(lectureId: Int) -> AnyPublisher<Int, Error> {
return self.attendanceService
.fetchAttendanceRound(lectureId: lectureId)
.compactMap { $0.data?.round }
.eraseToAnyPublisher()
}

public func postAttendance(lectureRoundId: Int, code: Int) -> AnyPublisher<Bool, Error> {
return self.attendanceService
.postAttendance(lectureRoundId: lectureRoundId, code: code)
.map { $0.success }
.eraseToAnyPublisher()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// AttendanceRepositoryInterface.swift
// Domain
//
// Created by 김영인 on 2023/04/16.
// Copyright © 2023 SOPT-iOS. All rights reserved.
//

import Combine

import Core

public protocol AttendanceRepositoryInterface {
func fetchLectureRound(lectureId: Int) -> AnyPublisher<Int, Error>
func postAttendance(lectureRoundId: Int, code: Int) -> AnyPublisher<Bool, Error>
}
64 changes: 64 additions & 0 deletions SOPT-iOS/Projects/Domain/Sources/UseCase/AttendanceUseCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//
// AttendanceUseCase.swift
// Domain
//
// Created by 김영인 on 2023/04/16.
// Copyright © 2023 SOPT-iOS. All rights reserved.
//

import Combine

import Core

public protocol AttendanceUseCase {
func fetchLectureRound(lectureId: Int)
func postAttendance(lectureRoundId: Int, code: Int)
var lectureRound: PassthroughSubject<Int, Never> { get set }
var attendSuccess: PassthroughSubject<Bool, Never> { get set }
}

public class DefaultAttendanceUseCase {

private let repository: AttendanceRepositoryInterface
private var cancelBag = CancelBag()

public var lectureRound = PassthroughSubject<Int, Never>()
public var attendSuccess = PassthroughSubject<Bool, Never>()

public init(repository: AttendanceRepositoryInterface, cancelBag: CancelBag = CancelBag()) {
self.repository = repository
self.cancelBag = cancelBag
}
}

extension DefaultAttendanceUseCase: AttendanceUseCase {
public func fetchLectureRound(lectureId: Int) {
repository.fetchLectureRound(lectureId: lectureId)
.sink(receiveCompletion: { event in
switch event {
case .failure(let error):
print("failure: fetchLectureRound \(error)")
case .finished:
print("completion: fetchLectureRound \(event)")
}
}, receiveValue: { result in
self.lectureRound.send(result)
})
.store(in: cancelBag)
}

public func postAttendance(lectureRoundId: Int, code: Int) {
repository.postAttendance(lectureRoundId: lectureRoundId, code: code)
.sink(receiveCompletion: { event in
switch event {
case .failure(let error):
print("failure: postAttendance \(error)")
case .finished:
print("completion: postAttendance \(event)")
}
}, receiveValue: { result in
self.attendSuccess.send(result)
})
.store(in: cancelBag)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import BaseFeatureDependency

public protocol ShowAttendanceViewControllable: ViewControllable { }

public protocol AttendanceViewControllable: ViewControllable { }

public protocol AttendanceFeatureViewBuildable {
func makeShowAttendanceVC() -> ShowAttendanceViewControllable
func makeAttendanceVC() -> AttendanceViewControllable
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//
// OPCodeTextField.swift
// AttendanceFeature
//
// Created by 김영인 on 2023/04/17.
// Copyright © 2023 SOPT-iOS. All rights reserved.
//

import UIKit

import Core
import DSKit

@frozen
public enum AttendanceCodeState {
case empty
case fill

var backgroundColor: UIColor {
switch self {
case .empty:
return DSKitAsset.Colors.black40.color
case .fill:
return DSKitAsset.Colors.black80.color
}
}

var borderColor: CGColor {
switch self {
case .empty:
return DSKitAsset.Colors.black40.color.cgColor
case .fill:
return DSKitAsset.Colors.purple40.color.cgColor
}
}
}

/// 숫자코드 입력 자리수, 숫자
public struct AttendanceCodeInfo {
var idx: Int
var text: String?
}

public class OPAttendanceCodeTextField: UITextField {

// MARK: - Init

public override init(frame: CGRect) {
super.init(frame: .zero)

self.setUI()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

// MARK: - Methods

extension OPAttendanceCodeTextField {

public var textChanged: Driver<AttendanceCodeInfo> {
self.publisher(for: .editingChanged)
.map { _ in
AttendanceCodeInfo(
idx: self.tag,
text: self.text
)
}
.asDriver()
}

public func updateUI(text: String?) {
let state: AttendanceCodeState = (text == "") ? .empty : .fill

backgroundColor = state.backgroundColor
layer.borderColor = state.borderColor
self.text = text
}

/// 복사 붙여넣기 방지
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}


// MARK: - UI

extension OPAttendanceCodeTextField {
private func setUI() {
backgroundColor = AttendanceCodeState.empty.backgroundColor

textColor = DSKitAsset.Colors.purple40.color
font = .Main.headline2
textAlignment = .center
tintColor = .clear

layer.cornerRadius = 8
layer.borderWidth = 1
layer.borderColor = AttendanceCodeState.empty.borderColor

keyboardType = .numberPad
textContentType = .oneTimeCode
}
}
Loading

0 comments on commit 9e14846

Please sign in to comment.