diff --git a/SOPT-iOS/Projects/Features/AttendanceFeature/Sources/AttendanceScene/VC/AttendanceVC.swift b/SOPT-iOS/Projects/Features/AttendanceFeature/Sources/AttendanceScene/VC/AttendanceVC.swift index 68c6a152..9f502aca 100644 --- a/SOPT-iOS/Projects/Features/AttendanceFeature/Sources/AttendanceScene/VC/AttendanceVC.swift +++ b/SOPT-iOS/Projects/Features/AttendanceFeature/Sources/AttendanceScene/VC/AttendanceVC.swift @@ -36,6 +36,8 @@ public final class AttendanceVC: UIViewController, AttendanceViewControllable { private var cancelBag = CancelBag() public var factory: AttendanceFeatureViewBuildable + private var viewWillAppear = PassthroughSubject() + // MARK: - UI Components /// 출석하기 모달 뷰 @@ -74,8 +76,6 @@ public final class AttendanceVC: UIViewController, AttendanceViewControllable { /// 출석 제목 private let titleLabel: UILabel = { let label = UILabel() -#warning("서버 붙인 후 text 변경") - label.text = "1차 출석하기" label.textColor = DSKitAsset.Colors.white100.color label.setTypoStyle(.Attendance.h1) return label @@ -154,6 +154,12 @@ public final class AttendanceVC: UIViewController, AttendanceViewControllable { self.setObserver() } + public override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + self.viewWillAppear.send(()) + } + public override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) @@ -237,15 +243,25 @@ extension AttendanceVC { .asDriver() let input = AttendanceViewModel.Input( + viewWillAppear: viewWillAppear.asDriver(), codeTextChanged: codeTextChanged, attendanceButtonDidTap: attendanceButtonDidTap ) let output = viewModel.transform(from: input, cancelBag: cancelBag) + output.attendanceTitle + .withUnretained(self) + .sink { owner, title in + owner.titleLabel.text = title + } + .store(in: self.cancelBag) + output.codeTextFieldInfo .withUnretained(self) .sink { owner, code in + owner.alertLabel.isHidden = true + let (cur, nxt) = code [cur, nxt].forEach { @@ -264,6 +280,23 @@ extension AttendanceVC { owner.attendanceButton.isEnabled = isEnabled } .store(in: self.cancelBag) + + output.attendSuccess + .filter { $0 } + .withUnretained(self) + .sink { owner, _ in + owner.dismiss(animated: true) + } + .store(in: self.cancelBag) + + output.attendErrorMsg + .withUnretained(self) + .sink { owner, errorMsg in + owner.alertLabel.text = errorMsg + owner.alertLabel.isHidden = false + owner.attendanceCodeView.setCodeTextFieldEmpty() + } + .store(in: self.cancelBag) } private func setObserver() { diff --git a/SOPT-iOS/Projects/Features/AttendanceFeature/Sources/AttendanceScene/ViewModel/AttendanceViewModel.swift b/SOPT-iOS/Projects/Features/AttendanceFeature/Sources/AttendanceScene/ViewModel/AttendanceViewModel.swift index 2a21a299..c340daf2 100644 --- a/SOPT-iOS/Projects/Features/AttendanceFeature/Sources/AttendanceScene/ViewModel/AttendanceViewModel.swift +++ b/SOPT-iOS/Projects/Features/AttendanceFeature/Sources/AttendanceScene/ViewModel/AttendanceViewModel.swift @@ -22,11 +22,13 @@ public final class AttendanceViewModel: ViewModelType { private let useCase: AttendanceUseCase private var cancelBag = CancelBag() + private var lectureRound: AttendanceRoundModel = .EMPTY private var codeText: String = "" // MARK: - Input public struct Input { + let viewWillAppear: Driver let codeTextChanged: Driver let attendanceButtonDidTap: Driver } @@ -34,12 +36,16 @@ public final class AttendanceViewModel: ViewModelType { // MARK: - Output public struct Output { + let attendanceTitle = PassthroughSubject() let codeTextFieldInfo = PassthroughSubject<(AttendanceCodeInfo, AttendanceCodeInfo), Never>() let isAttendanceButtonEnabled = CurrentValueSubject(false) + let attendSuccess = PassthroughSubject() + let attendErrorMsg = PassthroughSubject() } - public init(useCase: AttendanceUseCase) { + public init(useCase: AttendanceUseCase, lectureRound: AttendanceRoundModel) { self.useCase = useCase + self.lectureRound = lectureRound } } @@ -48,6 +54,13 @@ extension AttendanceViewModel { let output = Output() self.bindOutput(output: output, cancelBag: cancelBag) + + input.viewWillAppear + .withUnretained(self) + .sink { owner, _ in + output.attendanceTitle.send(I18N.Attendance.nthAttendance(owner.lectureRound.round)) + } + .store(in: self.cancelBag) input.codeTextChanged .withUnretained(self) @@ -61,9 +74,9 @@ extension AttendanceViewModel { input.attendanceButtonDidTap .withUnretained(self) .sink { owner, _ in - #warning("차수 서버값 넘겨주기") - let code = Int(owner.codeText) ?? 0 - owner.useCase.postAttendance(lectureRoundId: 0, code: code) + let lectureRoundId = owner.lectureRound.subLectureId + let code = owner.codeText + owner.useCase.postAttendance(lectureRoundId: lectureRoundId, code: code) } .store(in: self.cancelBag) @@ -71,7 +84,23 @@ extension AttendanceViewModel { } private func bindOutput(output: Output, cancelBag: CancelBag) { + let attendSuccess = self.useCase.attendSuccess + let attendErrorMsg = self.useCase.attendErrorMsg + attendSuccess.asDriver() + .sink { isSuccess in + output.attendSuccess.send(isSuccess) + } + .store(in: self.cancelBag) + + attendErrorMsg.asDriver() + .withUnretained(self) + .sink { owner, errorMsg in + output.attendErrorMsg.send(errorMsg) + output.isAttendanceButtonEnabled.send(false) + owner.codeText = "" + } + .store(in: self.cancelBag) } private func updateCodeText(_ code: AttendanceCodeInfo) -> (AttendanceCodeInfo, AttendanceCodeInfo) { diff --git a/SOPT-iOS/Projects/SOPT-iOS/Sources/ModuleFactory/DIContainer.swift b/SOPT-iOS/Projects/SOPT-iOS/Sources/ModuleFactory/DIContainer.swift index c5148c95..ab15ed0f 100644 --- a/SOPT-iOS/Projects/SOPT-iOS/Sources/ModuleFactory/DIContainer.swift +++ b/SOPT-iOS/Projects/SOPT-iOS/Sources/ModuleFactory/DIContainer.swift @@ -97,10 +97,10 @@ extension DIContainer: Features { return showAttendanceVC } - func makeAttendanceVC() -> AttendanceViewControllable { + func makeAttendanceVC(lectureRound: AttendanceRoundModel) -> AttendanceViewControllable { let repository = AttendanceRepository(service: attendanceService) let useCase = DefaultAttendanceUseCase(repository: repository) - let viewModel = AttendanceViewModel(useCase: useCase) + let viewModel = AttendanceViewModel(useCase: useCase, lectureRound: lectureRound) let attendanceVC = AttendanceVC(viewModel: viewModel, factory: self) return attendanceVC }