Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "report_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "report_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "report_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
102 changes: 79 additions & 23 deletions Projects/Presentation/Sources/Common/Component/FloatingMenuView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,47 @@ import SnapKit
import UIKit

protocol FloatingMenuViewDelegate: AnyObject {
func floatingMenuDidTapReportButton(_ sender: FloatingMenuView)
func floatingMenuDidTapRegisterRoutineButton(_ sender: FloatingMenuView)
}

final class FloatingMenuView: UIView {
private enum Layout {
static let registerRoutineButtonHeight: CGFloat = 24
static let registerRoutineIconSize: CGFloat = 24
static let registerRoutineLabelLeadingSpacing: CGFloat = 14
static let registerRoutineButtonWidth: CGFloat = 112
static let registerRoutineLabelHeight: CGFloat = 20
static let menuButtonStackViewSpacing: CGFloat = 24
static let menuButtonHeight: CGFloat = 24
static let menuIconSize: CGFloat = 24
static let menuLabelLeadingSpacing: CGFloat = 14
static let menuButtonWidth: CGFloat = 112
static let menuLabelHeight: CGFloat = 20
}

private enum FloatingMenu {
case addRoutine
case report

var menuIcon: UIImage? {
switch self {
case .addRoutine:
return BitnagilIcon.addRoutineIcon
case .report:
return BitnagilIcon.reportIcon
}
}

var menuLabel: String {
switch self {
case .addRoutine:
return "루틴 등록"
case .report:
return "제보하기"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

홈 화면 버튼 작업도 해주셨군요 감사합니다!

}
}
}

private let containerView = UIView()
private let registerRoutineButton = UIButton()
private let registerRoutineIconView = UIImageView()
private let registerRoutineLabel = UILabel()
private let menuButtonStackView = UIStackView()
private var reportButton = UIButton()
private var registerRoutineButton = UIButton()
weak var delegate: FloatingMenuViewDelegate?

init() {
Expand All @@ -42,12 +67,18 @@ final class FloatingMenuView: UIView {
containerView.layer.masksToBounds = true
containerView.layer.cornerRadius = 12

registerRoutineIconView.image = BitnagilIcon.addRoutineIcon
menuButtonStackView.axis = .vertical
menuButtonStackView.spacing = Layout.menuButtonStackViewSpacing

registerRoutineLabel.text = "루틴 등록"
registerRoutineLabel.font = BitnagilFont(style: .body2, weight: .medium).font
registerRoutineLabel.textColor = BitnagilColor.gray30
reportButton = makeMenuButton(menu: .report)
reportButton.addAction(
UIAction { [weak self] _ in
guard let self else { return }
self.delegate?.floatingMenuDidTapReportButton(self)
},
for: .touchUpInside)

registerRoutineButton = makeMenuButton(menu: .addRoutine)
registerRoutineButton.addAction(
UIAction { [weak self] _ in
guard let self else { return }
Expand All @@ -58,31 +89,56 @@ final class FloatingMenuView: UIView {

private func configureLayout() {
addSubview(containerView)
containerView.addSubview(registerRoutineButton)
[registerRoutineIconView, registerRoutineLabel].forEach {
registerRoutineButton.addSubview($0)
[reportButton, registerRoutineButton].forEach { menuButton in
menuButtonStackView.addArrangedSubview(menuButton)
}
containerView.addSubview(menuButtonStackView)

containerView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}

menuButtonStackView.snp.makeConstraints { make in
make.edges.equalToSuperview().inset(16)
}

reportButton.snp.makeConstraints { make in
make.height.equalTo(Layout.menuButtonHeight)
make.width.equalTo(Layout.menuButtonWidth)
}

registerRoutineButton.snp.makeConstraints { make in
make.center.equalToSuperview()
make.height.equalTo(Layout.registerRoutineButtonHeight)
make.width.equalTo(Layout.registerRoutineButtonWidth)
make.height.equalTo(Layout.menuButtonHeight)
make.width.equalTo(Layout.menuButtonWidth)
}
}

private func makeMenuButton(menu: FloatingMenu) -> UIButton {
let menuButton = UIButton()
let menuIconView = UIImageView()
let menuLabel = UILabel()

menuIconView.image = menu.menuIcon
menuLabel.text = menu.menuLabel
menuLabel.font = BitnagilFont(style: .body2, weight: .medium).font
menuLabel.textColor = BitnagilColor.gray30

[menuIconView, menuLabel].forEach {
menuButton.addSubview($0)
}

registerRoutineIconView.snp.makeConstraints { make in
menuIconView.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.leading.equalToSuperview()
make.size.equalTo(Layout.registerRoutineIconSize)
make.size.equalTo(Layout.menuIconSize)
}

registerRoutineLabel.snp.makeConstraints { make in
make.leading.equalTo(registerRoutineIconView.snp.trailing).offset(Layout.registerRoutineLabelLeadingSpacing)
menuLabel.snp.makeConstraints { make in
make.leading.equalTo(menuIconView.snp.trailing).offset(Layout.menuLabelLeadingSpacing)
make.centerY.equalToSuperview()
make.height.equalTo(Layout.registerRoutineLabelHeight)
make.height.equalTo(Layout.menuLabelHeight)
}

return menuButton
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enum BitnagilIcon {
// MARK: - Common Icons
static let backButtonIcon = UIImage(named: "back_button_icon", in: bundle, with: nil)
static let plusIcon = UIImage(named: "plus_icon", in: bundle, with: nil)?.withRenderingMode(.alwaysTemplate)
static let reportIcon = UIImage(named: "report_icon", in: bundle, with: nil)
static let bitnagilChevronIcon = UIImage(named: "bitnagil_chevron_icon", in: bundle, with: nil)
static func bitnagilChevronIcon(direction: Direction) -> UIImage? {
return BitnagilIcon.bitnagilChevronIcon?.rotate(degrees: direction.rotation)?.withRenderingMode(.alwaysTemplate)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,9 @@ public struct PresentationDependencyAssembler: DependencyAssemblerProtocol {

return ReportViewModel(reportUseCase: reportUseCase)
}

DIContainer.shared.register(type: ReportDetailViewModel.self) { container in
return ReportDetailViewModel()
}
}
}
14 changes: 13 additions & 1 deletion Projects/Presentation/Sources/Home/View/HomeViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ final class HomeViewController: BaseViewController<HomeViewModel> {
static let floatingButtonBottomSpacing: CGFloat = 19
static let floatingButtonSize: CGFloat = 52
static let floatingMenuBottomSpacing: CGFloat = 16
static let floatingMenuHeight: CGFloat = 56
static let floatingMenuHeight: CGFloat = 104
static let floatingMenuWidth: CGFloat = 144
}

Expand Down Expand Up @@ -664,6 +664,18 @@ extension HomeViewController: RoutineViewDelegate {

// MARK: FloatingMenuViewDelegate
extension HomeViewController: FloatingMenuViewDelegate {
func floatingMenuDidTapReportButton(_ sender: FloatingMenuView) {
toggleFloatingButton()
// TODO: 제보하기 뷰로 이동 (현재는 제보 detailView)
guard let reportDetailViewModel = DIContainer.shared.resolve(type: ReportDetailViewModel.self)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요 부분은 다음 pr 올릴때 적용해서 올리겠습니다!

else { fatalError("reportDetailViewModel 의존성이 등록되지 않았습니다.") }

let reportDetailViewController = ReportDetailViewController(viewModel: reportDetailViewModel)
reportDetailViewController.hidesBottomBarWhenPushed = true

self.navigationController?.pushViewController(reportDetailViewController, animated: true)
}

func floatingMenuDidTapRegisterRoutineButton(_ sender: FloatingMenuView) {
toggleFloatingButton()
guard let routineCreationViewModel = DIContainer.shared.resolve(type: RoutineCreationViewModel.self) else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ final class RecommendedRoutineViewController: BaseViewController<RecommendedRout
static let floatingButtonBottomSpacing: CGFloat = 19
static let floatingButtonSize: CGFloat = 52
static let floatingMenuBottomSpacing: CGFloat = 15
static let floatingMenuHeight: CGFloat = 64
static let floatingMenuHeight: CGFloat = 104
static let floatingMenuWidth: CGFloat = 144
static let toastMessageViewHeight: CGFloat = 52
static let toastMessageViewBottomSpacing: CGFloat = 38
Expand Down Expand Up @@ -335,6 +335,11 @@ extension RecommendedRoutineViewController: SelectableItemTableViewDelegate {

// MARK: FloatingMenuViewDelegate
extension RecommendedRoutineViewController: FloatingMenuViewDelegate {
func floatingMenuDidTapReportButton(_ sender: FloatingMenuView) {
toggleFloatingButton()
// TODO: 제보하기 뷰로 이동
}

func floatingMenuDidTapRegisterRoutineButton(_ sender: FloatingMenuView) {
toggleFloatingButton()
guard let routineCreationViewModel = DIContainer.shared.resolve(type: RoutineCreationViewModel.self)
Expand Down
16 changes: 16 additions & 0 deletions Projects/Presentation/Sources/Report/Model/ReportDetail.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// ReportDetail.swift
// Presentation
//
// Created by 최정인 on 11/18/25.
//

import Domain

struct ReportDetail {
let date: String
let title: String
let category: ReportType
let description: String
let location: String
}
Loading