Skip to content

Commit

Permalink
Merge pull request #47 from Nexters/feature/attendanceDetailVC
Browse files Browse the repository at this point in the history
[FEAT][#7] 출석 코드 입력 상세 뷰 구현
  • Loading branch information
tngusmiso authored Feb 11, 2023
2 parents 29a8230 + 3b8fba6 commit 6605e57
Show file tree
Hide file tree
Showing 11 changed files with 800 additions and 5 deletions.
36 changes: 32 additions & 4 deletions momoIOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,20 @@
objects = {

/* Begin PBXBuildFile section */
3A5AC30A2989784A0080323A /* AbsenceModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A5AC3092989784A0080323A /* AbsenceModalViewController.swift */; };
3A5AC31029898B330080323A /* UIButton+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A5AC30F29898B330080323A /* UIButton+Extension.swift */; };
3A75FC10298827BE00B36A46 /* MainAttendanceCodeCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A75FC0F298827BE00B36A46 /* MainAttendanceCodeCell.swift */; };
3A8E2DDF2997697E00D5476A /* AttendanceCodeDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8E2DDE2997697E00D5476A /* AttendanceCodeDetailViewController.swift */; };
3A8E2DE129976A8F00D5476A /* AbsenceModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8E2DE029976A8F00D5476A /* AbsenceModalViewController.swift */; };
3AA713C929884007006F922F /* MainAttendanceDoneCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA713C829884007006F922F /* MainAttendanceDoneCell.swift */; };
3AA713D1298946FF006F922F /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA713D0298946FF006F922F /* UIColor+Extension.swift */; };
3ABBF74829975801004D4D0B /* NotActiveSessionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABBF74729975801004D4D0B /* NotActiveSessionCell.swift */; };
3ABBF75129975EDA004D4D0B /* AdminSessionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABBF74E29975ED9004D4D0B /* AdminSessionCell.swift */; };
3ABBF75229975EDA004D4D0B /* AdminSessionTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABBF74F29975ED9004D4D0B /* AdminSessionTableViewController.swift */; };
3ABBF75329975EDA004D4D0B /* AddSessionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABBF75029975ED9004D4D0B /* AddSessionViewController.swift */; };
3ABEDB7129976EF100F9BF1C /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABEDB6F29976EF100F9BF1C /* UINavigationController+Extension.swift */; };
3ABEDB7229976EF100F9BF1C /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABEDB7029976EF100F9BF1C /* Optional+Extension.swift */; };
3ABEDB742997719000F9BF1C /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABEDB732997719000F9BF1C /* String+Extension.swift */; };
3ABEDB76299771A900F9BF1C /* Collection+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABEDB75299771A900F9BF1C /* Collection+Extension.swift */; };
BF0408632987B3AA00F1129B /* LoginController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0408622987B3AA00F1129B /* LoginController.swift */; };
BF04086B2987E34800F1129B /* AuthCommonConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF04086A2987E34800F1129B /* AuthCommonConstants.swift */; };
BF04086D2987E38C00F1129B /* RegistrationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF04086C2987E38C00F1129B /* RegistrationController.swift */; };
Expand Down Expand Up @@ -47,15 +52,20 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
3A5AC3092989784A0080323A /* AbsenceModalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AbsenceModalViewController.swift; sourceTree = "<group>"; };
3A5AC30F29898B330080323A /* UIButton+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+Extension.swift"; sourceTree = "<group>"; };
3A75FC0F298827BE00B36A46 /* MainAttendanceCodeCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainAttendanceCodeCell.swift; sourceTree = "<group>"; };
3A8E2DDE2997697E00D5476A /* AttendanceCodeDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttendanceCodeDetailViewController.swift; sourceTree = "<group>"; };
3A8E2DE029976A8F00D5476A /* AbsenceModalViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AbsenceModalViewController.swift; sourceTree = "<group>"; };
3AA713C829884007006F922F /* MainAttendanceDoneCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainAttendanceDoneCell.swift; sourceTree = "<group>"; };
3AA713D0298946FF006F922F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = "<group>"; };
3ABBF74729975801004D4D0B /* NotActiveSessionCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotActiveSessionCell.swift; sourceTree = "<group>"; };
3ABBF74E29975ED9004D4D0B /* AdminSessionCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdminSessionCell.swift; sourceTree = "<group>"; };
3ABBF74F29975ED9004D4D0B /* AdminSessionTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdminSessionTableViewController.swift; sourceTree = "<group>"; };
3ABBF75029975ED9004D4D0B /* AddSessionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddSessionViewController.swift; sourceTree = "<group>"; };
3ABEDB6F29976EF100F9BF1C /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; };
3ABEDB7029976EF100F9BF1C /* Optional+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Optional+Extension.swift"; sourceTree = "<group>"; };
3ABEDB732997719000F9BF1C /* String+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = "<group>"; };
3ABEDB75299771A900F9BF1C /* Collection+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Collection+Extension.swift"; sourceTree = "<group>"; };
BF0408622987B3AA00F1129B /* LoginController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginController.swift; sourceTree = "<group>"; };
BF04086A2987E34800F1129B /* AuthCommonConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthCommonConstants.swift; sourceTree = "<group>"; };
BF04086C2987E38C00F1129B /* RegistrationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegistrationController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -99,6 +109,14 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
3A8E2DDC2997697E00D5476A /* AttendanceCodeDetail */ = {
isa = PBXGroup;
children = (
3A8E2DDE2997697E00D5476A /* AttendanceCodeDetailViewController.swift */,
);
path = AttendanceCodeDetail;
sourceTree = "<group>";
};
3ABBF73F29975082004D4D0B /* Common */ = {
isa = PBXGroup;
children = (
Expand All @@ -111,7 +129,7 @@
3ABBF742299750A4004D4D0B /* UI */ = {
isa = PBXGroup;
children = (
3A5AC3092989784A0080323A /* AbsenceModalViewController.swift */,
3A8E2DE029976A8F00D5476A /* AbsenceModalViewController.swift */,
BF43B57729951F0C0026DCE3 /* ProfileView.swift */,
);
path = UI;
Expand Down Expand Up @@ -145,6 +163,7 @@
isa = PBXGroup;
children = (
3ABBF743299752EB004D4D0B /* Main */,
3A8E2DDC2997697E00D5476A /* AttendanceCodeDetail */,
BF9988FA298AD002005723C7 /* PersonalInformation */,
);
path = UserSide;
Expand Down Expand Up @@ -220,8 +239,12 @@
E8207930298A163400B36FC9 /* Extensions */ = {
isa = PBXGroup;
children = (
3ABEDB75299771A900F9BF1C /* Collection+Extension.swift */,
3ABEDB7029976EF100F9BF1C /* Optional+Extension.swift */,
3ABEDB732997719000F9BF1C /* String+Extension.swift */,
3A5AC30F29898B330080323A /* UIButton+Extension.swift */,
3AA713D0298946FF006F922F /* UIColor+Extension.swift */,
3ABEDB6F29976EF100F9BF1C /* UINavigationController+Extension.swift */,
BFB8431E298CFF9200BA11EC /* UIStackView+Extension.swift */,
E8207931298A163400B36FC9 /* UIView+Extension.swift */,
);
Expand Down Expand Up @@ -373,14 +396,15 @@
E8D5C3F32984FC23003D1AD0 /* SceneDelegate.swift in Sources */,
3A75FC10298827BE00B36A46 /* MainAttendanceCodeCell.swift in Sources */,
E83238F1298506A000DC83C2 /* MainViewController.swift in Sources */,
3A5AC30A2989784A0080323A /* AbsenceModalViewController.swift in Sources */,
BF998900298BB0D3005723C7 /* InputMemberInfoController.swift in Sources */,
BF0408632987B3AA00F1129B /* LoginController.swift in Sources */,
BF6EC77F298D1B2E00F4B170 /* AttendanceResultCell.swift in Sources */,
BF04086B2987E34800F1129B /* AuthCommonConstants.swift in Sources */,
3A5AC31029898B330080323A /* UIButton+Extension.swift in Sources */,
BF43B57829951F0C0026DCE3 /* ProfileView.swift in Sources */,
3A8E2DDF2997697E00D5476A /* AttendanceCodeDetailViewController.swift in Sources */,
E8207934298A22D000B36FC9 /* MainSessionInfoCell.swift in Sources */,
3A8E2DE129976A8F00D5476A /* AbsenceModalViewController.swift in Sources */,
3ABBF74829975801004D4D0B /* NotActiveSessionCell.swift in Sources */,
3ABBF75229975EDA004D4D0B /* AdminSessionTableViewController.swift in Sources */,
E8207932298A163400B36FC9 /* UIView+Extension.swift in Sources */,
Expand All @@ -390,11 +414,15 @@
E820792B298A119900B36FC9 /* MainSessionDetailCell.swift in Sources */,
E8207936298A248200B36FC9 /* MainSessionNoInfoCell.swift in Sources */,
BF43B57629951EAF0026DCE3 /* MoimManagementController.swift in Sources */,
3ABEDB742997719000F9BF1C /* String+Extension.swift in Sources */,
3AA713D1298946FF006F922F /* UIColor+Extension.swift in Sources */,
3AA713C929884007006F922F /* MainAttendanceDoneCell.swift in Sources */,
BF43B57A29952AFF0026DCE3 /* MoimSettingCell.swift in Sources */,
E820792F298A138500B36FC9 /* MainSessionAbsentCell.swift in Sources */,
BF4310FA298C525900270DBF /* AttendanceHistoryCell.swift in Sources */,
3ABEDB76299771A900F9BF1C /* Collection+Extension.swift in Sources */,
3ABEDB7129976EF100F9BF1C /* UINavigationController+Extension.swift in Sources */,
3ABEDB7229976EF100F9BF1C /* Optional+Extension.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
14 changes: 14 additions & 0 deletions momoIOS/Common/Extensions/Collection+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Collection+Extension.swift
// momoIOS
//
// Created by 임수현 on 2023/02/11.
//

import Foundation

extension Collection {
subscript (safe index: Index) -> Element? {
return indices.contains(index) ? self[index] : nil
}
}
23 changes: 23 additions & 0 deletions momoIOS/Common/Extensions/Optional+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Optional+Extension.swift
// momoIOS
//
// Created by 임수현 on 2023/02/11.
//

import Foundation

extension Optional {
var isNil: Bool {
self == nil
}
var isNotNil: Bool {
self != nil
}
}

extension String? {
var isEmptyOrNil: Bool {
self?.isEmpty == true || self.isNil
}
}
40 changes: 40 additions & 0 deletions momoIOS/Common/Extensions/String+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// String+Extension.swift
// momoIOS
//
// Created by 임수현 on 2023/02/11.
//

import Foundation

extension String {
subscript (safe index: Int) -> String? {
guard self.count > index else { return nil }
let index = self.index(self.startIndex, offsetBy: index)
return "\(self[index])"
}

subscript (range: Range<Int>) -> String? {
let fromIndex = self.index(self.startIndex, offsetBy: max(0, range.lowerBound))
let toIndex = self.index(self.startIndex, offsetBy: min(range.upperBound, self.count))
return String(self[fromIndex..<toIndex])
}

subscript(_ range: Range<Int>) -> String {
let fromIndex = self.index(self.startIndex, offsetBy: range.startIndex)
let toIndex = self.index(self.startIndex, offsetBy: range.endIndex)
return String(self[fromIndex..<toIndex])
}

func replaced(_ string: String, in range: NSRange) -> String? {
guard let range = Range(range, in: self) else { return nil }
return self.replacingCharacters(in: range, with: string)
}

var isBackspace: Bool {
if let char = self.cString(using: String.Encoding.utf8) {
return strcmp(char, "\\b") == -92
}
return false
}
}
21 changes: 21 additions & 0 deletions momoIOS/Common/Extensions/UINavigationController+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// UINavigationController+Extension.swift
// momoIOS
//
// Created by 임수현 on 2023/02/11.
//

import UIKit

extension UINavigationController: ObservableObject, UIGestureRecognizerDelegate {
override open func viewDidLoad() {
super.viewDidLoad()

// backButton을 임의로 변경하면 swipe back 동작이 되지 않기 떄문에 gestureRecognizer를 설정하여 동작하도록 함.
interactivePopGestureRecognizer?.delegate = self
}

public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return viewControllers.count > 1
}
}
21 changes: 21 additions & 0 deletions momoIOS/Common/Extensions/UIView+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,25 @@ extension UIView {
func addSubviews(_ views: UIView...) {
views.forEach { addSubview($0) }
}

/// 키보드 움직임에 따라서 움직이도록 함.
func moveWithKeyboard(willShow keyboardWillShow: Bool, notification: NSNotification, safeAreaBottomInset: CGFloat = 0) {
guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
let keyboardDuration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double,
let keyboardcurveValue = notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt
else { return }

let keyboardHeight = keyboardSize.height
let curveOption = UIView.AnimationOptions(rawValue: keyboardcurveValue << 16)

if keyboardWillShow {
UIView.animate(withDuration: keyboardDuration, delay: 0, options: [curveOption]) { [weak self] in
self?.transform = CGAffineTransform(translationX: 0, y: -keyboardHeight + safeAreaBottomInset)
}
} else {
UIView.animate(withDuration: keyboardDuration, delay: 0, options: [curveOption]) { [weak self] in
self?.transform = .identity
}
}
}
}
89 changes: 89 additions & 0 deletions momoIOS/Main/Cell/MainAttendanceCodeCell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//
// MainAttendanceCodeCell.swift
// momoIOS
//
// Created by 임수현 on 2023/01/31.
//

import UIKit
import SnapKit

class MainAttendanceCodeCell: UITableViewCell {
private let cardView: UIView = UIView()
private let titleLabel: UILabel = UILabel()
private let codeStackView: UIStackView = UIStackView()
private let descriptionLabel: UILabel = UILabel()

// MARK: - Initializer
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: "MainAttendanceCodeCell")

self.selectionStyle = .none
self.setupViews()
self.setupLayout()
}

required init?(coder: NSCoder) {
super.init(coder: coder)
}

// MARK: - Setup
private func setupViews() {
// TODO: ViewModel 바라보도록 수정 필요
self.cardView.backgroundColor = .rgba(128, 135, 201, 1)
self.cardView.layer.cornerRadius = 12
self.contentView.addSubview(self.cardView)

self.titleLabel.text = "출석체크 코드 입력"
self.titleLabel.font = .systemFont(ofSize: 17, weight: .medium)
self.titleLabel.textColor = .white
self.cardView.addSubview(self.titleLabel)

self.codeStackView.axis = .horizontal
self.codeStackView.alignment = .center
self.codeStackView.spacing = 14
for _ in 0..<4 {
let lineView = UIView()
lineView.backgroundColor = .white
self.codeStackView.addArrangedSubview(lineView)
}
self.cardView.addSubview(self.codeStackView)

self.descriptionLabel.text = "운영진이 공지해준 출석체크 코드를 입력해주세요!"
self.descriptionLabel.font = .systemFont(ofSize: 14)
self.descriptionLabel.textColor = .white.withAlphaComponent(0.67)
self.cardView.addSubview(self.descriptionLabel)
}

// MARK: - Layout
private func setupLayout() {
self.cardView.snp.makeConstraints { make in
make.top.equalToSuperview()
make.leading.trailing.equalToSuperview().inset(24)
make.bottom.equalToSuperview().inset(19)
}

self.titleLabel.snp.makeConstraints { make in
make.top.equalToSuperview().inset(28)
make.centerX.equalToSuperview()
}

self.codeStackView.snp.makeConstraints { make in
make.top.equalTo(self.titleLabel.snp.bottom).offset(103)
make.centerX.equalToSuperview()
}

self.codeStackView.arrangedSubviews.forEach {
$0.snp.makeConstraints { make in
make.height.equalTo(1)
make.width.equalTo(44)
}
}

self.descriptionLabel.snp.makeConstraints { make in
make.top.equalTo(self.codeStackView.snp.bottom).offset(26)
make.bottom.equalToSuperview().inset(35)
make.centerX.equalToSuperview()
}
}
}
Loading

0 comments on commit 6605e57

Please sign in to comment.