Skip to content

Commit ec82e3b

Browse files
committed
🧩 :: 겨울인턴 뷰 퍼블리싱
1 parent 3e407a1 commit ec82e3b

File tree

2 files changed

+222
-0
lines changed

2 files changed

+222
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import UIKit
2+
import Domain
3+
import RxSwift
4+
import RxCocoa
5+
import SnapKit
6+
import Then
7+
import Core
8+
import DesignSystem
9+
10+
public final class WinterInternViewController: BaseViewController<WinterInternVieModel> {
11+
public var viewWillappearWithTap: (() -> Void)?
12+
public var isTabNavigation: Bool = true
13+
private let bookmarkButtonDidClicked = PublishRelay<Int>()
14+
private let pageCount = PublishRelay<Int>()
15+
private let listEmptyView = ListEmptyView().then {
16+
$0.setEmptyView(title: "아직 등록된 모집의뢰서가 없어요")
17+
$0.isHidden = true
18+
}
19+
private let recruitmentTableView = UITableView().then {
20+
$0.register(
21+
RecruitmentTableViewCell.self,
22+
forCellReuseIdentifier: RecruitmentTableViewCell.identifier
23+
)
24+
$0.separatorStyle = .none
25+
$0.rowHeight = 72
26+
$0.showsVerticalScrollIndicator = false
27+
}
28+
private let filterButton = UIButton().then {
29+
$0.setImage(.jobisIcon(.filterIcon), for: .normal)
30+
}
31+
private let searchButton = UIButton().then {
32+
$0.setImage(.jobisIcon(.searchIcon), for: .normal)
33+
}
34+
35+
public override func addView() {
36+
self.view.addSubview(recruitmentTableView)
37+
recruitmentTableView.addSubview(listEmptyView)
38+
}
39+
40+
public override func setLayout() {
41+
recruitmentTableView.snp.makeConstraints {
42+
$0.edges.equalToSuperview()
43+
}
44+
listEmptyView.snp.makeConstraints {
45+
$0.centerX.equalToSuperview()
46+
$0.top.equalToSuperview().inset(80)
47+
}
48+
}
49+
50+
public override func bind() {
51+
let input = WinterInternVieModel.Input(
52+
viewAppear: self.viewDidLoadPublisher,
53+
bookMarkButtonDidTap: bookmarkButtonDidClicked,
54+
pageChange: recruitmentTableView.rx.willDisplayCell
55+
.filter {
56+
$0.indexPath.row == self.recruitmentTableView.numberOfRows(
57+
inSection: $0.indexPath.section
58+
) - 1
59+
},
60+
recruitmentTableViewDidTap: recruitmentTableView.rx
61+
.modelSelected(RecruitmentEntity.self)
62+
.asObservable()
63+
.map { $0.recruitID }
64+
.do(onNext: { _ in
65+
self.isTabNavigation = false
66+
}),
67+
searchButtonDidTap: searchButton.rx.tap.asSignal(),
68+
filterButtonDidTap: filterButton.rx.tap.asSignal()
69+
)
70+
71+
let output = viewModel.transform(input)
72+
73+
output.recruitmentData
74+
.skip(1)
75+
.do(onNext: {
76+
self.listEmptyView.isHidden = !$0.isEmpty
77+
})
78+
.bind(
79+
to: recruitmentTableView.rx.items(
80+
cellIdentifier: RecruitmentTableViewCell.identifier,
81+
cellType: RecruitmentTableViewCell.self
82+
)) { _, element, cell in
83+
cell.adapt(model: element)
84+
cell.bookmarkButtonDidTap = {
85+
self.bookmarkButtonDidClicked.accept(cell.model!.recruitID)
86+
}
87+
}
88+
.disposed(by: disposeBag)
89+
}
90+
91+
public override func configureViewController() {
92+
viewWillAppearPublisher.asObservable()
93+
.bind {
94+
self.hideTabbar()
95+
if self.isTabNavigation {
96+
self.viewWillappearWithTap?()
97+
}
98+
}
99+
.disposed(by: disposeBag)
100+
}
101+
102+
public override func configureNavigation() {
103+
self.setSmallTitle(title: "체험형 현장실습")
104+
navigationItem.rightBarButtonItems = [
105+
UIBarButtonItem(customView: searchButton),
106+
UIBarButtonItem(customView: filterButton)
107+
]
108+
}
109+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import UIKit
2+
import RxSwift
3+
import RxCocoa
4+
import RxFlow
5+
import Core
6+
import Domain
7+
8+
public final class WinterInternVieModel: BaseViewModel, Stepper {
9+
public let steps = PublishRelay<Step>()
10+
public var jobCode: String = ""
11+
public var techCode: [String]?
12+
public var recruitmentData = BehaviorRelay<[RecruitmentEntity]>(value: [])
13+
private let disposeBag = DisposeBag()
14+
private let fetchRecruitmentListUseCase: FetchRecruitmentListUseCase
15+
private let bookmarkUseCase: BookmarkUseCase
16+
private var pageCount: Int = 1
17+
18+
init(
19+
fetchRecruitmentListUseCase: FetchRecruitmentListUseCase,
20+
bookmarkUseCase: BookmarkUseCase
21+
) {
22+
self.fetchRecruitmentListUseCase = fetchRecruitmentListUseCase
23+
self.bookmarkUseCase = bookmarkUseCase
24+
}
25+
26+
public struct Input {
27+
let viewAppear: PublishRelay<Void>
28+
let bookMarkButtonDidTap: PublishRelay<Int>
29+
var pageChange: Observable<WillDisplayCellEvent>
30+
let recruitmentTableViewDidTap: Observable<Int>
31+
let searchButtonDidTap: Signal<Void>
32+
let filterButtonDidTap: Signal<Void>
33+
}
34+
35+
public struct Output {
36+
var recruitmentData = BehaviorRelay<[RecruitmentEntity]>(value: [])
37+
}
38+
39+
public func transform(_ input: Input) -> Output {
40+
input.viewAppear.asObservable()
41+
.flatMap {
42+
self.pageCount = 1
43+
return self.fetchRecruitmentListUseCase.execute(
44+
page: self.pageCount,
45+
jobCode: self.jobCode,
46+
techCode: self.techCode,
47+
winterIntern: true
48+
)
49+
}
50+
.bind(onNext: {
51+
self.recruitmentData.accept([])
52+
self.recruitmentData.accept(self.recruitmentData.value + $0)
53+
self.pageCount = 1
54+
})
55+
.disposed(by: disposeBag)
56+
57+
input.pageChange.asObservable()
58+
.flatMap { _ in
59+
self.pageCount += 1
60+
return self.fetchRecruitmentListUseCase.execute(
61+
page: self.pageCount,
62+
jobCode: self.jobCode,
63+
techCode: self.techCode,
64+
winterIntern: true
65+
)
66+
.asObservable()
67+
.take(while: {
68+
!$0.isEmpty
69+
})
70+
}
71+
.bind { self.recruitmentData.accept(self.recruitmentData.value + $0) }
72+
.disposed(by: disposeBag)
73+
74+
input.bookMarkButtonDidTap.asObservable()
75+
.do(onNext: { id in
76+
var oldData = self.recruitmentData.value
77+
oldData.enumerated().forEach {
78+
if $0.element.recruitID == id {
79+
oldData[$0.offset].bookmarked.toggle()
80+
}
81+
}
82+
self.recruitmentData.accept(oldData)
83+
})
84+
.flatMap { id in
85+
self.bookmarkUseCase.execute(id: id)
86+
}
87+
.subscribe()
88+
.disposed(by: disposeBag)
89+
90+
input.recruitmentTableViewDidTap.asObservable()
91+
.map {
92+
RecruitmentStep.recruitmentDetailIsRequired(
93+
recruitmentId: $0
94+
)
95+
}
96+
.bind(to: steps)
97+
.disposed(by: disposeBag)
98+
99+
input.searchButtonDidTap.asObservable()
100+
.map {
101+
RecruitmentStep.searchRecruitmentIsRequired
102+
}
103+
.bind(to: steps)
104+
.disposed(by: disposeBag)
105+
106+
input.filterButtonDidTap.asObservable()
107+
.map { _ in RecruitmentStep.recruitmentFilterIsRequired }
108+
.bind(to: steps)
109+
.disposed(by: disposeBag)
110+
111+
return Output(recruitmentData: recruitmentData)
112+
}
113+
}

0 commit comments

Comments
 (0)