From c269e92326370b18126399f5e668b67cd7555c4e Mon Sep 17 00:00:00 2001 From: taipaise Date: Thu, 20 Nov 2025 22:23:21 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EC=A0=9C=EB=B3=B4=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=ED=9E=88=EC=8A=A4=ED=86=A0=EB=A6=AC=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EA=B5=AC=ED=98=84(=EC=99=84=EB=A3=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PresentationDependencyAssembler.swift | 8 +-- .../Sources/MyPage/View/MypageView.swift | 27 +++++--- .../MyPage/ViewModel/MypageViewModel.swift | 3 + .../Report/Model/ReportProgress+.swift | 37 ++++++++++ .../ReportCategoryTableViewCell.swift | 0 .../Component/Common/ReportProgressView.swift | 66 ++++++++++++++++++ .../ReportHistoryEmptyView.swift | 69 +++++++++++++++++++ .../ReportHistoryTableHeaderView.swift | 0 .../ReportHistoryTableViewCell.swift | 64 +---------------- .../ReportProgressCollectionViewCell.swift | 0 .../LocationButton.swift | 0 .../ReportCameraButton.swift | 0 .../ReportPhotoCollectionViewCell.swift | 0 .../ReportTextView.swift | 0 ...wift => ReportHistoryViewController.swift} | 46 +++++++++++-- ...=> ReportRegistrationViewController.swift} | 18 ++--- ...del.swift => ReportHistoryViewModel.swift} | 6 +- ...wift => ReportRegistrationViewModel.swift} | 2 +- 18 files changed, 254 insertions(+), 92 deletions(-) create mode 100644 Projects/Presentation/Sources/Report/Model/ReportProgress+.swift rename Projects/Presentation/Sources/Report/View/Component/{ => Common}/ReportCategoryTableViewCell.swift (100%) create mode 100644 Projects/Presentation/Sources/Report/View/Component/Common/ReportProgressView.swift create mode 100644 Projects/Presentation/Sources/Report/View/Component/ReportHistory/ReportHistoryEmptyView.swift rename Projects/Presentation/Sources/Report/View/Component/{ => ReportHistory}/ReportHistoryTableHeaderView.swift (100%) rename Projects/Presentation/Sources/Report/View/Component/{ => ReportHistory}/ReportHistoryTableViewCell.swift (75%) rename Projects/Presentation/Sources/Report/View/Component/{ => ReportHistory}/ReportProgressCollectionViewCell.swift (100%) rename Projects/Presentation/Sources/Report/View/Component/{ => ReportRegistration}/LocationButton.swift (100%) rename Projects/Presentation/Sources/Report/View/Component/{ => ReportRegistration}/ReportCameraButton.swift (100%) rename Projects/Presentation/Sources/Report/View/Component/{ => ReportRegistration}/ReportPhotoCollectionViewCell.swift (100%) rename Projects/Presentation/Sources/Report/View/Component/{ => ReportRegistration}/ReportTextView.swift (100%) rename Projects/Presentation/Sources/Report/View/{ReportListHistoryViewController.swift => ReportHistoryViewController.swift} (86%) rename Projects/Presentation/Sources/Report/View/{ReportViewController.swift => ReportRegistrationViewController.swift} (96%) rename Projects/Presentation/Sources/Report/ViewModel/{ReportListHistoryViewModel.swift => ReportHistoryViewModel.swift} (94%) rename Projects/Presentation/Sources/Report/ViewModel/{ReportViewModel.swift => ReportRegistrationViewModel.swift} (98%) diff --git a/Projects/Presentation/Sources/Common/PresentationDependencyAssembler.swift b/Projects/Presentation/Sources/Common/PresentationDependencyAssembler.swift index 69267ef8..296529ad 100644 --- a/Projects/Presentation/Sources/Common/PresentationDependencyAssembler.swift +++ b/Projects/Presentation/Sources/Common/PresentationDependencyAssembler.swift @@ -121,16 +121,16 @@ public struct PresentationDependencyAssembler: DependencyAssemblerProtocol { return WithdrawViewModel(authRepository: authRepository) } - DIContainer.shared.register(type: ReportViewModel.self) { container in + DIContainer.shared.register(type: ReportRegistrationViewModel.self) { container in guard let reportUseCase = container.resolve(type: ReportUseCaseProtocol.self) else { fatalError("reportUseCase 의존성이 등록되지 않았습니다.") } - return ReportViewModel(reportUseCase: reportUseCase) + return ReportRegistrationViewModel(reportUseCase: reportUseCase) } DIContainer.shared - .register(type: ReportListHistoryViewModel.self) { container in - return ReportListHistoryViewModel() + .register(type: ReportHistoryViewModel.self) { container in + return ReportHistoryViewModel() } DIContainer.shared.register(type: ReportDetailViewModel.self) { container in diff --git a/Projects/Presentation/Sources/MyPage/View/MypageView.swift b/Projects/Presentation/Sources/MyPage/View/MypageView.swift index bb62b692..ac55d7ec 100644 --- a/Projects/Presentation/Sources/MyPage/View/MypageView.swift +++ b/Projects/Presentation/Sources/MyPage/View/MypageView.swift @@ -52,7 +52,6 @@ final class MypageView: BaseViewController { navigationController?.navigationBar.standardAppearance = appearance navigationController?.navigationBar.scrollEdgeAppearance = appearance navigationController?.navigationBar.compactAppearance = appearance - navigationController?.navigationBar.isHidden = false } override func configureAttribute() { @@ -165,16 +164,24 @@ extension MypageView: UITableViewDataSource { let selectedMenu = MypageViewModel.MypageMenu.allCases[indexPath.row] - guard selectedMenu == .resetGoal else { - viewModel.action(input: .didSelectMenu(menu: selectedMenu)) - return - } + switch selectedMenu { + + case .reportHistory: + guard let reportHistoryViewModel = DIContainer.shared.resolve(type: ReportHistoryViewModel.self) + else { fatalError("reportHistoryViewModel 의존성이 등록되지 않았습니다.") } - guard let onboardingViewModel = DIContainer.shared.resolve(type: OnboardingViewModel.self) - else { fatalError("onboardingViewModel 의존성이 등록되지 않았습니다.") } + let reportHistoryViewController = ReportHistoryViewController(viewModel: reportHistoryViewModel) + reportHistoryViewController.hidesBottomBarWhenPushed = true + navigationController?.pushViewController(reportHistoryViewController, animated: true) + case .resetGoal: + guard let onboardingViewModel = DIContainer.shared.resolve(type: OnboardingViewModel.self) + else { fatalError("onboardingViewModel 의존성이 등록되지 않았습니다.") } - let onboardingView = OnboardingResultViewController(viewModel: onboardingViewModel, entryPoint: .myPagePrevious) - onboardingView.hidesBottomBarWhenPushed = true - navigationController?.pushViewController(onboardingView, animated: true) + let onboardingView = OnboardingResultViewController(viewModel: onboardingViewModel, entryPoint: .myPagePrevious) + onboardingView.hidesBottomBarWhenPushed = true + navigationController?.pushViewController(onboardingView, animated: true) + case .notice, .faq: + viewModel.action(input: .didSelectMenu(menu: selectedMenu)) + } } } diff --git a/Projects/Presentation/Sources/MyPage/ViewModel/MypageViewModel.swift b/Projects/Presentation/Sources/MyPage/ViewModel/MypageViewModel.swift index c1d726a7..8b006133 100644 --- a/Projects/Presentation/Sources/MyPage/ViewModel/MypageViewModel.swift +++ b/Projects/Presentation/Sources/MyPage/ViewModel/MypageViewModel.swift @@ -21,6 +21,7 @@ final class MypageViewModel: ViewModel { } enum MypageMenu: String, CaseIterable { + case reportHistory = "내 제보 기록" case resetGoal = "내 목표 재설정" case notice = "공지사항" case faq = "자주 묻는 질문" @@ -67,6 +68,8 @@ final class MypageViewModel: ViewModel { if let url = URL(string: "https://complex-wombat-99f.notion.site/23ff4587491d80659ae3ea392afbc05e") { externalURLPublisher.send(url) } + case .reportHistory: + break } } } diff --git a/Projects/Presentation/Sources/Report/Model/ReportProgress+.swift b/Projects/Presentation/Sources/Report/Model/ReportProgress+.swift new file mode 100644 index 00000000..757b80de --- /dev/null +++ b/Projects/Presentation/Sources/Report/Model/ReportProgress+.swift @@ -0,0 +1,37 @@ +// +// ReportProgress+.swift +// Presentation +// +// Created by 이동현 on 11/20/25. +// + +import Domain +import UIKit + +extension ReportProgress { + var backgroundColor: UIColor? { + switch self { + case .received: + BitnagilColor.green10 + case .inProgress: + BitnagilColor.skyblue10 + case .completed: + BitnagilColor.gray95 + case .entire: + nil + } + } + + var titleColor: UIColor? { + switch self { + case .received: + BitnagilColor.green500 + case .inProgress: + BitnagilColor.blue300 + case .completed: + BitnagilColor.gray40 + case .entire: + nil + } + } +} diff --git a/Projects/Presentation/Sources/Report/View/Component/ReportCategoryTableViewCell.swift b/Projects/Presentation/Sources/Report/View/Component/Common/ReportCategoryTableViewCell.swift similarity index 100% rename from Projects/Presentation/Sources/Report/View/Component/ReportCategoryTableViewCell.swift rename to Projects/Presentation/Sources/Report/View/Component/Common/ReportCategoryTableViewCell.swift diff --git a/Projects/Presentation/Sources/Report/View/Component/Common/ReportProgressView.swift b/Projects/Presentation/Sources/Report/View/Component/Common/ReportProgressView.swift new file mode 100644 index 00000000..2c70fb82 --- /dev/null +++ b/Projects/Presentation/Sources/Report/View/Component/Common/ReportProgressView.swift @@ -0,0 +1,66 @@ +// +// ReportProgressView.swift +// Presentation +// +// Created by 이동현 on 11/20/25. +// + +import Domain +import SnapKit +import UIKit + +final class ReportProgressView: UIView { + + private enum Layout { + static let progressViewHeight: CGFloat = 26 + static let progressLabelHeight: CGFloat = 18 + static let progressLabelHorizontalSpacing: CGFloat = 10 + static let progressLabelVerticalSpacing: CGFloat = 4 + } + + private let progressLabel = UILabel() + + override init(frame: CGRect) { + super.init(frame: frame) + configureAttribute() + configureLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func configureAttribute() { + layer.cornerRadius = 6 + layer.masksToBounds = true + + progressLabel.font = BitnagilFont.init(style: .caption1, weight: .semiBold).font + } + + private func configureLayout() { + addSubview(progressLabel) + + self.snp.makeConstraints { make in + make.height.equalTo(Layout.progressViewHeight) + } + + progressLabel.snp.makeConstraints { make in + make.height.equalTo(Layout.progressLabelHeight) + + make.verticalEdges + .equalToSuperview() + .inset(Layout.progressLabelVerticalSpacing) + + make.horizontalEdges + .equalToSuperview() + .inset(Layout.progressLabelHorizontalSpacing) + } + } + + func configure(with progress: ReportProgress) { + backgroundColor = progress.backgroundColor + + progressLabel.textColor = progress.titleColor + progressLabel.text = progress.description + } +} diff --git a/Projects/Presentation/Sources/Report/View/Component/ReportHistory/ReportHistoryEmptyView.swift b/Projects/Presentation/Sources/Report/View/Component/ReportHistory/ReportHistoryEmptyView.swift new file mode 100644 index 00000000..f11e219c --- /dev/null +++ b/Projects/Presentation/Sources/Report/View/Component/ReportHistory/ReportHistoryEmptyView.swift @@ -0,0 +1,69 @@ +// +// ReportHistoryEmptyView.swift +// Presentation +// +// Created by 이동현 on 11/20/25. +// + +import SnapKit +import UIKit + +final class ReportHistoryEmptyView: UIView { + private enum Layout { + static let semiBoldLabelHeight: CGFloat = 28 + static let regularLabelHeight: CGFloat = 20 + static let stackViewSpacing: CGFloat = 2 + static let stackViewHeight: CGFloat = 50 + static let stackViewWidth: CGFloat = 269 + } + + private let labelStackView = UIStackView() + private let semiBoldLabel = UILabel() + private let regularLabel = UILabel() + + override init(frame: CGRect) { + super.init(frame: frame) + + configureAttribute() + configureLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func configureAttribute() { + backgroundColor = BitnagilColor.gray99 + + labelStackView.axis = .vertical + labelStackView.alignment = .center + + semiBoldLabel.font = BitnagilFont.init(style: .subtitle1, weight: .semiBold).font + semiBoldLabel.textColor = BitnagilColor.gray30 + semiBoldLabel.text = "제보한 내역이 없어요." + + regularLabel.font = BitnagilFont.init(style: .body2, weight: .regular).font + regularLabel.textColor = BitnagilColor.gray70 + regularLabel.text = "원하는 카테고리로 제보를 시작해보세요." + } + + private func configureLayout() { + addSubview(labelStackView) + labelStackView.addArrangedSubview(semiBoldLabel) + labelStackView.addArrangedSubview(regularLabel) + + labelStackView.snp.makeConstraints { make in + make.center.equalToSuperview() + make.height.equalTo(Layout.stackViewHeight) + make.width.equalTo(Layout.stackViewWidth) + } + + semiBoldLabel.snp.makeConstraints { make in + make.height.equalTo(Layout.semiBoldLabelHeight) + } + + regularLabel.snp.makeConstraints { make in + make.height.equalTo(Layout.regularLabelHeight) + } + } +} diff --git a/Projects/Presentation/Sources/Report/View/Component/ReportHistoryTableHeaderView.swift b/Projects/Presentation/Sources/Report/View/Component/ReportHistory/ReportHistoryTableHeaderView.swift similarity index 100% rename from Projects/Presentation/Sources/Report/View/Component/ReportHistoryTableHeaderView.swift rename to Projects/Presentation/Sources/Report/View/Component/ReportHistory/ReportHistoryTableHeaderView.swift diff --git a/Projects/Presentation/Sources/Report/View/Component/ReportHistoryTableViewCell.swift b/Projects/Presentation/Sources/Report/View/Component/ReportHistory/ReportHistoryTableViewCell.swift similarity index 75% rename from Projects/Presentation/Sources/Report/View/Component/ReportHistoryTableViewCell.swift rename to Projects/Presentation/Sources/Report/View/Component/ReportHistory/ReportHistoryTableViewCell.swift index e3b6fa4c..5d50f045 100644 --- a/Projects/Presentation/Sources/Report/View/Component/ReportHistoryTableViewCell.swift +++ b/Projects/Presentation/Sources/Report/View/Component/ReportHistory/ReportHistoryTableViewCell.swift @@ -5,7 +5,6 @@ // Created by 이동현 on 11/15/25. // -import Domain import SnapKit import UIKit @@ -15,10 +14,6 @@ final class ReportHistoryTableViewCell: UITableViewCell { static let verticalSpacing: CGFloat = 14 static let containerViewBottomSpacing: CGFloat = 10 static let photoSize: CGFloat = 74 - static let progressViewHeight: CGFloat = 26 - static let progressLabelHeight: CGFloat = 18 - static let progressLabelHorizontalSpacing: CGFloat = 10 - static let progressLabelVerticalSpacing: CGFloat = 4 static let titleLabelMaxHeight: CGFloat = 40 static let titleLabelTopSpacing: CGFloat = 8 static let titleLabelTrailingSpacing: CGFloat = 14 @@ -30,8 +25,7 @@ final class ReportHistoryTableViewCell: UITableViewCell { } private let containerView = UIView() - private let progressView = UIView() - private let progressLabel = UILabel() + private let progressView = ReportProgressView() private let titleLabel = UILabel() private let categoryLabel = UILabel() private let dotView = UIView() @@ -56,9 +50,6 @@ final class ReportHistoryTableViewCell: UITableViewCell { containerView.layer.cornerRadius = Layout.containerViewCornerRadius containerView.layer.masksToBounds = true - progressView.layer.cornerRadius = 6 - progressView.layer.masksToBounds = true - photoImageView.layer.cornerRadius = 9.25 photoImageView.layer.masksToBounds = true @@ -79,9 +70,8 @@ final class ReportHistoryTableViewCell: UITableViewCell { private func configureLayout() { addSubview(containerView) - containerView.addSubview(progressView) - containerView.addSubview(progressLabel) containerView.addSubview(photoImageView) + containerView.addSubview(progressView) containerView.addSubview(titleLabel) containerView.addSubview(categoryLabel) containerView.addSubview(dotView) @@ -98,19 +88,6 @@ final class ReportHistoryTableViewCell: UITableViewCell { progressView.snp.makeConstraints { make in make.leading.equalToSuperview().offset(Layout.horizontalSpacing) make.top.equalToSuperview().offset(Layout.verticalSpacing) - make.height.equalTo(Layout.progressViewHeight) - } - - progressLabel.snp.makeConstraints { make in - make.height.equalTo(Layout.progressLabelHeight) - - make.verticalEdges - .equalTo(progressView) - .inset(Layout.progressLabelVerticalSpacing) - - make.horizontalEdges - .equalTo(progressView) - .inset(Layout.progressLabelHorizontalSpacing) } photoImageView.snp.makeConstraints { make in @@ -180,17 +157,10 @@ final class ReportHistoryTableViewCell: UITableViewCell { } func configure(with item: ReportHistoryItem) { - progressView.backgroundColor = item.progress.backgroundColor - - progressLabel.textColor = item.progress.titleColor - progressLabel.text = item.progress.description - progressLabel.font = BitnagilFont.init(style: .caption1, weight: .semiBold).font + progressView.configure(with: item.progress) titleLabel.text = item.title - categoryLabel.text = item.type.name - - addressLabel.text = item.location guard let imageURL = URL(string: item.thumbnailUrl) else { @@ -200,31 +170,3 @@ final class ReportHistoryTableViewCell: UITableViewCell { photoImageView.kf.setImage(with: imageURL) } } - -extension ReportProgress { - var backgroundColor: UIColor? { - switch self { - case .received: - BitnagilColor.green10 - case .inProgress: - BitnagilColor.skyblue10 - case .completed: - BitnagilColor.gray95 - case .entire: - nil - } - } - - var titleColor: UIColor? { - switch self { - case .received: - BitnagilColor.green500 - case .inProgress: - BitnagilColor.lightBlue300 - case .completed: - BitnagilColor.gray40 - case .entire: - nil - } - } -} diff --git a/Projects/Presentation/Sources/Report/View/Component/ReportProgressCollectionViewCell.swift b/Projects/Presentation/Sources/Report/View/Component/ReportHistory/ReportProgressCollectionViewCell.swift similarity index 100% rename from Projects/Presentation/Sources/Report/View/Component/ReportProgressCollectionViewCell.swift rename to Projects/Presentation/Sources/Report/View/Component/ReportHistory/ReportProgressCollectionViewCell.swift diff --git a/Projects/Presentation/Sources/Report/View/Component/LocationButton.swift b/Projects/Presentation/Sources/Report/View/Component/ReportRegistration/LocationButton.swift similarity index 100% rename from Projects/Presentation/Sources/Report/View/Component/LocationButton.swift rename to Projects/Presentation/Sources/Report/View/Component/ReportRegistration/LocationButton.swift diff --git a/Projects/Presentation/Sources/Report/View/Component/ReportCameraButton.swift b/Projects/Presentation/Sources/Report/View/Component/ReportRegistration/ReportCameraButton.swift similarity index 100% rename from Projects/Presentation/Sources/Report/View/Component/ReportCameraButton.swift rename to Projects/Presentation/Sources/Report/View/Component/ReportRegistration/ReportCameraButton.swift diff --git a/Projects/Presentation/Sources/Report/View/Component/ReportPhotoCollectionViewCell.swift b/Projects/Presentation/Sources/Report/View/Component/ReportRegistration/ReportPhotoCollectionViewCell.swift similarity index 100% rename from Projects/Presentation/Sources/Report/View/Component/ReportPhotoCollectionViewCell.swift rename to Projects/Presentation/Sources/Report/View/Component/ReportRegistration/ReportPhotoCollectionViewCell.swift diff --git a/Projects/Presentation/Sources/Report/View/Component/ReportTextView.swift b/Projects/Presentation/Sources/Report/View/Component/ReportRegistration/ReportTextView.swift similarity index 100% rename from Projects/Presentation/Sources/Report/View/Component/ReportTextView.swift rename to Projects/Presentation/Sources/Report/View/Component/ReportRegistration/ReportTextView.swift diff --git a/Projects/Presentation/Sources/Report/View/ReportListHistoryViewController.swift b/Projects/Presentation/Sources/Report/View/ReportHistoryViewController.swift similarity index 86% rename from Projects/Presentation/Sources/Report/View/ReportListHistoryViewController.swift rename to Projects/Presentation/Sources/Report/View/ReportHistoryViewController.swift index 7cf5202f..dd234631 100644 --- a/Projects/Presentation/Sources/Report/View/ReportListHistoryViewController.swift +++ b/Projects/Presentation/Sources/Report/View/ReportHistoryViewController.swift @@ -6,10 +6,11 @@ // import Combine +import Domain import SnapKit import UIKit -final class ReportListHistoryViewController: BaseViewController { +final class ReportHistoryViewController: BaseViewController { private enum Layout { static let horizontalSpacing: CGFloat = 20 static let progressCollectionViewTopSpacing: CGFloat = 80 @@ -27,6 +28,9 @@ final class ReportListHistoryViewController: BaseViewController? private var historyDataSource: UITableViewDiffableDataSource? private var cancellables: Set = [] @@ -45,11 +50,12 @@ final class ReportListHistoryViewController: BaseViewController UIView? { guard let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: ReportHistoryTableHeaderView.className) as? ReportHistoryTableHeaderView, @@ -290,3 +317,12 @@ extension ReportListHistoryViewController: UITableViewDelegate { return header } } + +extension ReportHistoryViewController: ReportCategoryTableViewControllerDelegate { + func reportCategoryTableViewController(_ sender: ReportCategoryTableViewController, selectedCategory: ReportType?) { + guard let selectedCategory = selectedCategory else { return } + + viewModel.action(input: .filterCategory(type: selectedCategory)) + } + +} diff --git a/Projects/Presentation/Sources/Report/View/ReportViewController.swift b/Projects/Presentation/Sources/Report/View/ReportRegistrationViewController.swift similarity index 96% rename from Projects/Presentation/Sources/Report/View/ReportViewController.swift rename to Projects/Presentation/Sources/Report/View/ReportRegistrationViewController.swift index 60d29144..92f877fa 100644 --- a/Projects/Presentation/Sources/Report/View/ReportViewController.swift +++ b/Projects/Presentation/Sources/Report/View/ReportRegistrationViewController.swift @@ -11,7 +11,7 @@ import PhotosUI import SnapKit import UIKit -final class ReportViewController: BaseViewController { +final class ReportRegistrationViewController: BaseViewController { private enum CollectionViewSection { case main } private enum Layout { @@ -42,7 +42,7 @@ final class ReportViewController: BaseViewController { static let cameraBottomSheetHeight: CGFloat = 174 } - private typealias Section = ReportViewController.CollectionViewSection + private typealias Section = ReportRegistrationViewController.CollectionViewSection private typealias DataSource = UICollectionViewDiffableDataSource private typealias Snapshot = NSDiffableDataSourceSnapshot @@ -451,7 +451,7 @@ final class ReportViewController: BaseViewController { } } -extension ReportViewController: ReportTextViewDelegate { +extension ReportRegistrationViewController: ReportTextViewDelegate { func reportTextViewDidChanged(_ reportTextView: ReportTextView, text: String?) { switch reportTextView { case reportTitleTextView: @@ -467,24 +467,24 @@ extension ReportViewController: ReportTextViewDelegate { } } -extension ReportViewController: ReportPhotoCollectionViewCellDelegate { +extension ReportRegistrationViewController: ReportPhotoCollectionViewCellDelegate { func reportPhotoCollectionViewCellWillDeleteCell(_ cell: ReportPhotoCollectionViewCell, uuid: UUID) { viewModel.action(input: .removePhoto(id: uuid)) } } -extension ReportViewController: UICollectionViewDelegate { +extension ReportRegistrationViewController: UICollectionViewDelegate { } -extension ReportViewController: ReportCategoryTableViewControllerDelegate { +extension ReportRegistrationViewController: ReportCategoryTableViewControllerDelegate { func reportCategoryTableViewController(_ sender: ReportCategoryTableViewController, selectedCategory: ReportType?) { guard let selectedCategory else { return } viewModel.action(input: .selectCategory(type: selectedCategory)) } } -extension ReportViewController: SelectableItemTableViewDelegate { +extension ReportRegistrationViewController: SelectableItemTableViewDelegate { func selectableItemTableView(_ sender: SelectableItemTableView, didSelectItem: T?) where T : SelectableItem, T : CaseIterable, T : Equatable { if T.self == ReportType.self, @@ -510,7 +510,7 @@ extension ReportViewController: SelectableItemTableViewDelegate { } } -extension ReportViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { +extension ReportRegistrationViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { picker.dismiss(animated: true) } @@ -527,7 +527,7 @@ extension ReportViewController: UIImagePickerControllerDelegate, UINavigationCon } } -extension ReportViewController: PHPickerViewControllerDelegate { +extension ReportRegistrationViewController: PHPickerViewControllerDelegate { func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true, completion: nil) guard diff --git a/Projects/Presentation/Sources/Report/ViewModel/ReportListHistoryViewModel.swift b/Projects/Presentation/Sources/Report/ViewModel/ReportHistoryViewModel.swift similarity index 94% rename from Projects/Presentation/Sources/Report/ViewModel/ReportListHistoryViewModel.swift rename to Projects/Presentation/Sources/Report/ViewModel/ReportHistoryViewModel.swift index 488dcedc..6a5fdd45 100644 --- a/Projects/Presentation/Sources/Report/ViewModel/ReportListHistoryViewModel.swift +++ b/Projects/Presentation/Sources/Report/ViewModel/ReportHistoryViewModel.swift @@ -9,7 +9,7 @@ import Combine import Domain import Foundation -final class ReportListHistoryViewModel: ViewModel { +final class ReportHistoryViewModel: ViewModel { enum Input { case fetchReports case fetchReport(index: Int) @@ -31,6 +31,7 @@ final class ReportListHistoryViewModel: ViewModel { private let selectedCategorySubject = CurrentValueSubject(nil) private let reportSubject = CurrentValueSubject<[ReportHistoryItem], Never>([]) private let selectedReportSubject = PassthroughSubject() + private(set) var selectedReportCategory: ReportType? private var reports: [ReportHistoryItem] = [] init() { @@ -76,6 +77,7 @@ final class ReportListHistoryViewModel: ViewModel { currentType = reportType } + selectedReportCategory = currentType selectedCategorySubject.send(currentType) filterReports() } @@ -101,7 +103,7 @@ final class ReportListHistoryViewModel: ViewModel { } private func fetchReports() { - reportSubject.send(ReportHistoryItem.dummyData) + //reportSubject.send(ReportHistoryItem.dummyData) } private func fetchReport(index: Int) { diff --git a/Projects/Presentation/Sources/Report/ViewModel/ReportViewModel.swift b/Projects/Presentation/Sources/Report/ViewModel/ReportRegistrationViewModel.swift similarity index 98% rename from Projects/Presentation/Sources/Report/ViewModel/ReportViewModel.swift rename to Projects/Presentation/Sources/Report/ViewModel/ReportRegistrationViewModel.swift index 9c790b4f..711ae60a 100644 --- a/Projects/Presentation/Sources/Report/ViewModel/ReportViewModel.swift +++ b/Projects/Presentation/Sources/Report/ViewModel/ReportRegistrationViewModel.swift @@ -9,7 +9,7 @@ import Combine import Domain import Foundation -final class ReportViewModel: ViewModel { +final class ReportRegistrationViewModel: ViewModel { enum Input { case selectCategory(type: ReportType) case inputTitle(title: String?) From bfabbb19318bad1e695e5ed878ee08e44ef30c10 Mon Sep 17 00:00:00 2001 From: taipaise Date: Thu, 20 Nov 2025 23:07:40 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EB=A7=88=EC=9D=B4=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Common/Extension/UIViewController+.swift | 29 +++++++++++++- .../Sources/MyPage/View/MypageView.swift | 40 ++++++++----------- 2 files changed, 45 insertions(+), 24 deletions(-) diff --git a/Projects/Presentation/Sources/Common/Extension/UIViewController+.swift b/Projects/Presentation/Sources/Common/Extension/UIViewController+.swift index 1bb97ed1..ce5c143d 100644 --- a/Projects/Presentation/Sources/Common/Extension/UIViewController+.swift +++ b/Projects/Presentation/Sources/Common/Extension/UIViewController+.swift @@ -14,6 +14,12 @@ extension UIViewController { case withBackButton(title: String) // 백버튼 + 타이틀 (없으면 빈 String) case withTitle(title: String) // 오로지 타이틀만 case withProgressBar(step: Int) // 백버튼 + progress + case withRightButton( + title: String, + rightButtonImage: UIImage, + rightButtonAction: UIAction, + rightButtonTintColor: UIColor? = nil, + withBackButton: Bool = false) // 커스텀 우측 버튼 } func configureCustomNavigationBar(navigationBarStyle: NavigationBarStyle, backgroundColor: UIColor? = .white) { @@ -31,6 +37,7 @@ extension UIViewController { private func customNavigationBar(navigationBarStyle: NavigationBarStyle) -> UIView { let navigationBar = UIView() let customBackButton = UIButton() + let customRightButton = UIButton() let titleLabel = UILabel() let progressView = UIImageView() @@ -46,6 +53,7 @@ extension UIViewController { titleLabel.textColor = BitnagilColor.gray10 progressView.isHidden = true + customRightButton.isHidden = true switch navigationBarStyle { case .withBackButton(let title): @@ -59,10 +67,23 @@ extension UIViewController { titleLabel.isHidden = true progressView.image = progressImage(step: step) progressView.isHidden = false + case .withRightButton( + title: let title, + rightButtonImage: let rightButtonImage, + rightButtonAction: let action, + rightButtonTintColor: let tintColor, + withBackButton: let withBackButton): + + customBackButton.isHidden = !withBackButton + customRightButton.isHidden = false + customRightButton.addAction(action, for: .touchUpInside) + titleLabel.text = title + customRightButton.setImage(rightButtonImage, for: .normal) + customRightButton.tintColor = tintColor } navigationBar.backgroundColor = .systemBackground - [customBackButton, titleLabel, progressView].forEach { + [customBackButton, titleLabel, progressView, customRightButton].forEach { navigationBar.addSubview($0) } @@ -72,6 +93,12 @@ extension UIViewController { make.size.equalTo(48) } + customRightButton.snp.makeConstraints { make in + make.top.equalToSuperview() + make.trailing.equalToSuperview() + make.size.equalTo(48) + } + titleLabel.snp.makeConstraints { make in make.center.equalToSuperview() } diff --git a/Projects/Presentation/Sources/MyPage/View/MypageView.swift b/Projects/Presentation/Sources/MyPage/View/MypageView.swift index ac55d7ec..ec856794 100644 --- a/Projects/Presentation/Sources/MyPage/View/MypageView.swift +++ b/Projects/Presentation/Sources/MyPage/View/MypageView.swift @@ -14,7 +14,7 @@ final class MypageView: BaseViewController { private enum Layout { static let profileImageViewSize: CGFloat = 80 static let profileImageViewCornerRadius: CGFloat = profileImageViewSize / 2 - static let profileImageViewTopSpacing: CGFloat = 32 + static let profileImageViewTopSpacing: CGFloat = 74 static let nicknameLabelHeight: CGFloat = 24 static let nicknameLabelTopSpacing: CGFloat = 12 static let divideLineHeight: CGFloat = 6 @@ -41,27 +41,12 @@ final class MypageView: BaseViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - - navigationController?.setNavigationBarHidden(false, animated: animated) - - let appearance = UINavigationBarAppearance() - appearance.configureWithOpaqueBackground() - appearance.backgroundColor = .white - appearance.shadowColor = .clear - - navigationController?.navigationBar.standardAppearance = appearance - navigationController?.navigationBar.scrollEdgeAppearance = appearance - navigationController?.navigationBar.compactAppearance = appearance + navigationController?.navigationBar.isHidden = true } override func configureAttribute() { view.backgroundColor = .white - navigationItem.rightBarButtonItem = settingButton - title = "마이페이지" - settingButton.action = #selector(settingButtonTapped) - settingButton.target = self - settingButton.image = BitnagilIcon.settingIcon?.withRenderingMode(.alwaysOriginal) profileImageView.image = BitnagilGraphic.profileGraphic nicknameLabel.font = BitnagilFont(style: .title3, weight: .semiBold).font @@ -75,6 +60,21 @@ final class MypageView: BaseViewController { tableView.delegate = self tableView.separatorStyle = .none tableView.bounces = false + + let settingButtonImage = BitnagilIcon.settingIcon + let settingButtonAction = UIAction { [weak self] _ in + guard let settingViewModel = Shared.DIContainer.shared.resolve(type: SettingViewModel.self) else { return } + let settingView = SettingView(viewModel: settingViewModel) + self?.navigationController?.pushViewController(settingView, animated: true) + } + + configureCustomNavigationBar(navigationBarStyle: + .withRightButton( + title: "마이페이지", + rightButtonImage: settingButtonImage ?? .init(), + rightButtonAction: settingButtonAction, + rightButtonTintColor: BitnagilColor.gray70, + withBackButton: false)) } override func configureLayout() { @@ -125,12 +125,6 @@ final class MypageView: BaseViewController { } .store(in: &cancellables) } - - @objc private func settingButtonTapped() { - guard let settingViewModel = Shared.DIContainer.shared.resolve(type: SettingViewModel.self) else { return } - let settingView = SettingView(viewModel: settingViewModel) - navigationController?.pushViewController(settingView, animated: true) - } } extension MypageView: UITableViewDelegate {