diff --git a/Roomie/Roomie/Global/Enums/AlertType.swift b/Roomie/Roomie/Global/Enums/AlertType.swift deleted file mode 100644 index d46233d..0000000 --- a/Roomie/Roomie/Global/Enums/AlertType.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// AlertType.swift -// Roomie -// -// Created by 김승원 on 7/4/25. -// - -import Foundation - -enum AlertType { - case logout - case signout - - var title: String { - switch self { - case .logout: - return "로그아웃 하시겠어요?" - case .signout: - return "정말 탈퇴하시겠어요?" - } - } - - var message: String { - switch self { - case .logout: - return "로그아웃 시, 다시 로그인해야 앱을 사용할 수 있어요." - case .signout: - return "탈퇴 시, 모든 정보가 삭제되며 복구할 수 없어요." - } - } - - var isCancelButtonEnabled: Bool { - switch self { - case .logout, .signout: - return true - } - } - - var isDestructiveButtonEnabled: Bool { - switch self { - case .logout: - return false - case .signout: - return true - } - } -} diff --git a/Roomie/Roomie/Global/Utils/AlertBuilder.swift b/Roomie/Roomie/Global/Utils/AlertBuilder.swift new file mode 100644 index 0000000..d692e6f --- /dev/null +++ b/Roomie/Roomie/Global/Utils/AlertBuilder.swift @@ -0,0 +1,186 @@ +// +// AlertBuilder.swift +// Roomie +// +// Created by 김승원 on 7/22/25. +// + +import UIKit + +final class AlertBuilder { + + // MARK: - Properties + + private let baseViewController: UIViewController + private let alertViewController = RoomieAlertViewController() + + private var alertTitle: String? + private var confirmAction: AlertAction? + private var cancelAction: AlertAction? + + // MARK: - Initializer + + init(viewController: UIViewController) { + self.baseViewController = viewController + } + + // MARK: - Functions + + func setTitle(_ alertTitle: String) -> AlertBuilder { + self.alertTitle = alertTitle + return self + } + + func setConfirmAction(_ text: String, action: (() -> Void)? = nil) -> AlertBuilder { + self.confirmAction = AlertAction(text: text, action: action) + return self + } + + func setCancelAction(_ text: String, action: (() -> Void)? = nil) -> AlertBuilder { + self.cancelAction = AlertAction(text: text, action: action) + return self + } + + @discardableResult + func build() -> Self { + alertViewController.modalPresentationStyle = .overFullScreen + alertViewController.modalTransitionStyle = .crossDissolve + + alertViewController.alertTitle = alertTitle + alertViewController.confirmAction = confirmAction + alertViewController.cancelAction = cancelAction + + baseViewController.present(alertViewController, animated: true) + return self + } +} + +// MARK: - RoomieAlertViewController + +final class RoomieAlertViewController: UIViewController { + + var alertTitle: String? + var confirmAction: AlertAction? + var cancelAction: AlertAction? + + private let alertContainer = UIView() + private let alertTitleLabel = UILabel() + private let confirmButton = UIButton() + private let cancelButton = UIButton() + + override func viewDidLoad() { + super.viewDidLoad() + + setStyle() + setUI() + setLayout() + setAction() + } + + private func setStyle() { + view.do { + $0.backgroundColor = .transpGray1260 + } + + alertContainer.do { + $0.backgroundColor = .grayscale1 + $0.layer.cornerRadius = 8 + $0.layer.masksToBounds = true + } + + alertTitleLabel.do { + $0.setText(alertTitle ?? " ", style: .body6, color: .grayscale12) + $0.numberOfLines = 0 + } + + confirmButton.do { + $0.setTitle(confirmAction?.text ?? " ", style: .body5, color: .grayscale1) + + var configuration = UIButton.Configuration.filled() + configuration.baseBackgroundColor = .primaryPurple + configuration.baseForegroundColor = .grayscale1 + configuration.contentInsets = NSDirectionalEdgeInsets( + top: Screen.height(8), + leading: Screen.width(16), + bottom: Screen.height(8), + trailing: Screen.width(16) + ) + configuration.cornerStyle = .fixed + configuration.background.cornerRadius = 6 + + $0.configuration = configuration + } + + cancelButton.do { + $0.setTitle(cancelAction?.text ?? " ", style: .body5, color: .grayscale12) + + var configuration = UIButton.Configuration.filled() + configuration.baseBackgroundColor = .grayscale4 + configuration.baseForegroundColor = .grayscale12 + configuration.contentInsets = NSDirectionalEdgeInsets( + top: Screen.height(8), + leading: Screen.width(16), + bottom: Screen.height(8), + trailing: Screen.width(16) + ) + configuration.cornerStyle = .fixed + configuration.background.cornerRadius = 6 + + $0.configuration = configuration + } + } + + private func setUI() { + view.addSubview(alertContainer) + alertContainer.addSubviews( + alertTitleLabel, + confirmButton, + cancelButton + ) + } + + private func setLayout() { + alertContainer.snp.makeConstraints { + $0.center.equalToSuperview() + $0.width.equalTo(Screen.width(257)) + $0.height.greaterThanOrEqualTo(Screen.height(108)) + } + + alertTitleLabel.snp.makeConstraints { + $0.top.equalToSuperview().inset(Screen.height(14)) + $0.horizontalEdges.equalToSuperview().inset(Screen.width(16)) + } + + confirmButton.snp.makeConstraints { + $0.trailing.equalToSuperview().inset(Screen.width(16)) + $0.bottom.equalToSuperview().inset(Screen.height(14)) + $0.height.equalTo(Screen.height(34)) + } + + cancelButton.snp.makeConstraints { + $0.trailing.equalTo(confirmButton.snp.leading).offset(-Screen.width(6)) + $0.bottom.equalToSuperview().inset(Screen.height(14)) + $0.height.equalTo(Screen.height(34)) + $0.top.greaterThanOrEqualTo(alertTitleLabel.snp.bottom).offset(Screen.height(28)).priority(.medium) + $0.top.greaterThanOrEqualTo(alertTitleLabel.snp.bottom).offset(Screen.height(22)).priority(.high) + } + } + + private func setAction() { + confirmButton.addTarget(self, action: #selector(alertButtonDidTap), for: .touchUpInside) + cancelButton.addTarget(self, action: #selector(alertButtonDidTap), for: .touchUpInside) + } + + @objc + private func alertButtonDidTap(_ sender: UIButton) { + sender == confirmButton ? confirmAction?.action?() : cancelAction?.action?() + dismiss(animated: true) + } +} + +// MARK: - AlertAction + +struct AlertAction { + var text: String + var action: (() -> Void)? +} diff --git a/Roomie/Roomie/Global/Utils/AlertManager.swift b/Roomie/Roomie/Global/Utils/AlertManager.swift deleted file mode 100644 index d009acb..0000000 --- a/Roomie/Roomie/Global/Utils/AlertManager.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// AlertManager.swift -// Roomie -// -// Created by 김승원 on 7/4/25. -// - -import UIKit - -final class AlertManager { - - static let shared = AlertManager() - private init() { } - - /// 화면에 알림을 표시합니다 - /// - Parameters: - /// - viewController: 알림 표시 대상 UIViewcontroller 인스턴스 - /// - alertType: Alert타입 - /// - confirmHandler: 확인 버튼 후 실행할 클로저 - func showAlert( - on viewController: UIViewController, - alertType: AlertType, - confirmHandler: ((UIAlertAction) -> Void)? = nil - ) { - DispatchQueue.main.async { - let alert = UIAlertController(title: alertType.title, message: alertType.message, preferredStyle: .alert) - - let confirmAction = UIAlertAction( - title: "확인", - style: alertType.isDestructiveButtonEnabled ? .destructive : .default, - handler: confirmHandler - ) - alert.addAction(confirmAction) - - if alertType.isCancelButtonEnabled { - let cancelAction = UIAlertAction(title: "취소", style: .cancel, handler: nil) - alert.addAction(cancelAction) - } - - viewController.present(alert, animated: true, completion: nil) - } - } -} diff --git a/Roomie/Roomie/Presentation/MyAccount/ViewController/MyAccountViewController.swift b/Roomie/Roomie/Presentation/MyAccount/ViewController/MyAccountViewController.swift index 28cd3fa..46b0f27 100644 --- a/Roomie/Roomie/Presentation/MyAccount/ViewController/MyAccountViewController.swift +++ b/Roomie/Roomie/Presentation/MyAccount/ViewController/MyAccountViewController.swift @@ -126,12 +126,14 @@ final class MyAccountViewController: BaseViewController { .tapPublisher .sink { [weak self] in guard let self else { return } - AlertManager.shared.showAlert( - on: self, - alertType: .logout - ) { _ in - self.logoutButtonDidTapSubject.send() - } + + AlertBuilder(viewController: self) + .setTitle("로그아웃 하시겠습니까?") + .setConfirmAction("확인") { + self.logoutButtonDidTapSubject.send() + } + .setCancelAction("취소") + .build() } .store(in: cancelBag) @@ -139,12 +141,14 @@ final class MyAccountViewController: BaseViewController { .tapPublisher .sink { [weak self] in guard let self else { return } - AlertManager.shared.showAlert( - on: self, - alertType: .signout - ) { _ in - self.signoutButtonDidTapSubject.send() - } + + AlertBuilder(viewController: self) + .setTitle("회원 탈퇴 시, 고미와 찾았던\n셰어하우스는 모두 사라져요") + .setConfirmAction("유지하기") + .setCancelAction("탈퇴하기") { + self.signoutButtonDidTapSubject.send() + } + .build() } .store(in: cancelBag) }