// // LNMultiSelectionPanel.swift // Gami // // Created by OneeChan on 2026/1/20. // import Foundation import UIKit import SnapKit class LNMultiSelectionPanel: LNPopupView { private var minCount: Int = 0 private var maxCount: Int = 0 private let titleLabel = UILabel() private let descLabel = UILabel() private let stackView = LNMultiLineStackView() private let confirmButton = UIButton() private var itemViews: [LNMultiSelectPanelItemView] = [] private var curSelection: [Int] { var indexs: [Int] = [] for (index, itemView) in itemViews.enumerated() { if itemView.isSelected { indexs.append(index) } } return indexs } var handler: (([Int]) -> Void)? override init(frame: CGRect) { super.init(frame: frame) setupViews() } func setTitles(_ title: String, desc: String? = nil) { titleLabel.text = title descLabel.text = desc descLabel.isHidden = desc?.isEmpty != false } func update(_ items: [String], curSelected: [String]) { var views: [LNMultiSelectPanelItemView] = [] for item in items { let itemView = LNMultiSelectPanelItemView() itemView.titleLabel.text = item itemView.isSelected = curSelected.contains(item) itemView.onTap { [weak self, weak itemView] in guard let self, let itemView else { return } itemView.isSelected.toggle() if maxCount > 0, curSelection.count >= maxCount { itemViews.forEach { $0.isEnable = $0.isSelected } } else { itemViews.forEach { $0.isEnable = true } } updateConfirm() } views.append(itemView) } itemViews = views stackView.update(views) updateConfirm() } func setLimie(min: Int, max: Int) { minCount = min maxCount = max } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension LNMultiSelectionPanel { private func updateConfirm() { let isEmpty = if minCount > 0 { curSelection.count < minCount } else { curSelection.isEmpty } if isEmpty == confirmButton.isEnabled { confirmButton.isEnabled = !isEmpty confirmButton.setBackgroundImage(isEmpty ? nil : .primary_8, for: .normal) } } private func setupViews() { let headerView = buildHeader() container.addSubview(headerView) headerView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.top.equalToSuperview() make.height.equalTo(56) } let selection = buildSelection() container.addSubview(selection) selection.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(21) make.top.equalTo(headerView.snp.bottom).offset(16) } confirmButton.setTitle(.init(key: "A00223"), for: .normal) confirmButton.setTitleColor(.text_1, for: .normal) confirmButton.titleLabel?.font = .heading_h3 confirmButton.layer.cornerRadius = 23.5 confirmButton.clipsToBounds = true confirmButton.isEnabled = false confirmButton.backgroundColor = .fill_4 confirmButton.addAction(UIAction(handler: { [weak self] _ in guard let self else { return } dismiss() handler?(curSelection) }), for: .touchUpInside) container.addSubview(confirmButton) confirmButton.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(16) make.top.equalTo(selection.snp.bottom).offset(24) make.bottom.equalToSuperview().offset(commonBottomInset) make.height.equalTo(47) } } private func buildHeader() -> UIView { let container = UIView() let stackView = UIStackView() stackView.axis = .vertical stackView.spacing = 3 container.addSubview(stackView) stackView.snp.makeConstraints { make in make.center.equalToSuperview() } titleLabel.font = .heading_h3 titleLabel.textColor = .text_5 titleLabel.textAlignment = .center stackView.addArrangedSubview(titleLabel) descLabel.font = .body_s descLabel.textColor = .text_3 descLabel.textAlignment = .center stackView.addArrangedSubview(descLabel) return container } private func buildSelection() -> UIView { stackView.columns = 3 stackView.itemSpacing = 16 stackView.spacing = 20 return stackView } } private class LNMultiSelectPanelItemView: UIView { let titleLabel = UILabel() var isSelected: Bool = false { didSet { backgroundColor = isSelected ? .fill_5 : .fill_1 titleLabel.font = isSelected ? .heading_h5 : .body_s titleLabel.textColor = isSelected ? .text_6 : .text_4 } } var isEnable: Bool = true { didSet { isUserInteractionEnabled = isEnable alpha = isEnable ? 1.0 : 0.5 } } override init(frame: CGRect) { super.init(frame: frame) layer.cornerRadius = 13 snp.makeConstraints { make in make.height.equalTo(26) } titleLabel.textAlignment = .center addSubview(titleLabel) titleLabel.snp.makeConstraints { make in make.centerY.equalToSuperview() make.horizontalEdges.equalToSuperview().inset(7) } isSelected = false } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }