-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathReportDetailViewController.swift
More file actions
225 lines (189 loc) · 8.09 KB
/
ReportDetailViewController.swift
File metadata and controls
225 lines (189 loc) · 8.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
//
// ReportDetailViewController.swift
// Presentation
//
// Created by 최정인 on 11/17/25.
//
import Combine
import Kingfisher
import SnapKit
import UIKit
class ReportDetailViewController: BaseViewController<ReportDetailViewModel> {
private enum Layout {
static let horizontalMargin: CGFloat = 20
static let scrollViewTopSpacing: CGFloat = 48
static let photoStackViewSpacing: CGFloat = 8
static let photoStackViewTopSpacing: CGFloat = 14
static let photoSize: CGFloat = 74
static let contentStackViewSpacing: CGFloat = 28
static let contentStackViewTopSpacing: CGFloat = 23
static let contentStackViewBottomSpacing: CGFloat = 40
static let reportStatusViewTopSpacing: CGFloat = 20
static let dateLabelTopSpacing: CGFloat = 6
static let reportContentBackgroudViewTopSpacing: CGFloat = 8
static let reportContentDescriptionVerticalMargin: CGFloat = 16
}
private enum ReportDetailContent: CaseIterable {
case title
case category
case description
case location
var title: String {
switch self {
case .title:
return "제목"
case .category:
return "카테고리"
case .description:
return "상세 제보 내용"
case .location:
return "신고 위치"
}
}
}
private let scrollView = UIScrollView()
private let contentView = UIView()
private let reportStatusView = ReportProgressView()
private let dateLabel = UILabel()
private let photoStackView = UIStackView()
private let contentStackView = UIStackView()
private let titleContentLabel = UILabel()
private let categoryLabel = UILabel()
private let detailDescriptionLabel = UILabel()
private let locationLabel = UILabel()
private var cancellables: Set<AnyCancellable> = []
private let reportId: Int
init(viewModel: ReportDetailViewModel, reportId: Int) {
self.reportId = reportId
super.init(viewModel: viewModel)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
viewModel.action(input: .fetchReportDetail(reportId: reportId))
}
override func configureAttribute() {
view.backgroundColor = .white
configureCustomNavigationBar(navigationBarStyle: .withBackButton(title: "제보하기"))
scrollView.showsVerticalScrollIndicator = false
dateLabel.font = BitnagilFont(style: .body1, weight: .semiBold).font
dateLabel.textColor = BitnagilColor.gray10
photoStackView.axis = .horizontal
photoStackView.spacing = Layout.photoStackViewSpacing
contentStackView.axis = .vertical
contentStackView.spacing = Layout.contentStackViewSpacing
ReportDetailContent.allCases.forEach { reportDetailContent in
let reportContentView = makeReportContentView(reportDetailContentType: reportDetailContent)
contentStackView.addArrangedSubview(reportContentView)
}
}
override func configureLayout() {
let safeArea = view.safeAreaLayoutGuide
view.addSubview(scrollView)
scrollView.addSubview(contentView)
[reportStatusView, dateLabel, photoStackView, contentStackView].forEach {
contentView.addSubview($0)
}
scrollView.snp.makeConstraints { make in
make.top.equalTo(safeArea).offset(Layout.scrollViewTopSpacing)
make.horizontalEdges.bottom.equalToSuperview()
}
contentView.snp.makeConstraints { make in
make.edges.equalTo(scrollView.contentLayoutGuide)
make.width.equalTo(scrollView.frameLayoutGuide)
}
reportStatusView.snp.makeConstraints { make in
make.top.equalTo(contentView).offset(Layout.reportStatusViewTopSpacing)
make.leading.equalTo(contentView).offset(Layout.horizontalMargin)
}
dateLabel.snp.makeConstraints { make in
make.top.equalTo(reportStatusView.snp.bottom).offset(Layout.dateLabelTopSpacing)
make.leading.equalTo(contentView).offset(Layout.horizontalMargin)
}
photoStackView.snp.makeConstraints { make in
make.top.equalTo(dateLabel.snp.bottom).offset(Layout.photoStackViewTopSpacing)
make.leading.equalTo(contentView).offset(Layout.horizontalMargin)
}
contentStackView.snp.makeConstraints { make in
make.top.equalTo(photoStackView.snp.bottom).offset(Layout.contentStackViewTopSpacing)
make.horizontalEdges.equalTo(contentView).inset(Layout.horizontalMargin)
make.bottom.equalToSuperview().offset(-Layout.contentStackViewBottomSpacing)
}
}
override func bind() {
viewModel.output.reportDetailPublisher
.receive(on: DispatchQueue.main)
.sink { [weak self] reportDetail in
self?.fillReportContent(reportDetail: reportDetail)
}
.store(in: &cancellables)
}
private func makeReportContentView(reportDetailContentType: ReportDetailContent) -> UIView {
let reportContentView = UIView()
let titleLabel = UILabel()
let backgroudView = UIView()
titleLabel.text = reportDetailContentType.title
titleLabel.font = BitnagilFont(style: .body2, weight: .semiBold).font
titleLabel.textColor = BitnagilColor.gray10
titleLabel.numberOfLines = 2
backgroudView.layer.masksToBounds = true
backgroudView.layer.cornerRadius = 12
backgroudView.backgroundColor = BitnagilColor.gray99
var descriptionLabel: UILabel
switch reportDetailContentType {
case .title:
descriptionLabel = titleContentLabel
case .category:
descriptionLabel = categoryLabel
case .description:
descriptionLabel = detailDescriptionLabel
descriptionLabel.numberOfLines = 0
case .location:
descriptionLabel = locationLabel
}
descriptionLabel.font = BitnagilFont(style: .body2, weight: .medium).font
descriptionLabel.textColor = BitnagilColor.gray10
backgroudView.addSubview(descriptionLabel)
[titleLabel, backgroudView].forEach {
reportContentView.addSubview($0)
}
titleLabel.snp.makeConstraints { make in
make.top.leading.equalToSuperview()
make.height.equalTo(Layout.horizontalMargin)
}
backgroudView.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom).offset(Layout.reportContentBackgroudViewTopSpacing)
make.horizontalEdges.equalToSuperview()
make.bottom.equalToSuperview()
}
descriptionLabel.snp.makeConstraints { make in
make.verticalEdges.equalToSuperview().inset(Layout.reportContentDescriptionVerticalMargin)
make.horizontalEdges.equalToSuperview().inset(Layout.horizontalMargin)
}
return reportContentView
}
private func fillReportContent(reportDetail: ReportDetail?) {
guard let reportDetail else { return }
reportStatusView.configure(with: reportDetail.status)
dateLabel.text = reportDetail.date
titleContentLabel.text = reportDetail.title
categoryLabel.text = reportDetail.category.name
detailDescriptionLabel.attributedText = BitnagilFont(style: .body2, weight: .medium)
.attributedString(text: reportDetail.description)
locationLabel.text = reportDetail.location
reportDetail.photoUrls.forEach { photoUrl in
let photoView = UIImageView()
if let url = URL(string: photoUrl) {
photoView.kf.setImage(with: url)
}
photoView.layer.masksToBounds = true
photoView.layer.cornerRadius = 9.25
photoView.snp.makeConstraints { make in
make.size.equalTo(Layout.photoSize)
}
photoStackView.addArrangedSubview(photoView)
}
}
}