// // LNSingleSelectionPanel.swift // Gami // // Created by OneeChan on 2026/1/20. // import Foundation import UIKit import SnapKit import Combine class LNSingleSelectionPanel: LNPopupView { private let titleLabel = UILabel() private let descLabel = UILabel() private let pickerView = UIPickerView() private let confirmButton = UIButton() private var selections: [String] = [] var handler: ((Int) -> Void)? override init(frame: CGRect) { super.init(frame: frame) setupViews() } func setTitles(_ title: String, desc: String?) { titleLabel.text = title descLabel.text = desc descLabel.isHidden = desc?.isEmpty != false } func update(_ selections: [String], curSelect: String? = nil) { self.selections = selections pickerView.reloadAllComponents() if let curSelect, let index = selections.firstIndex(of: curSelect) { pickerView.selectRow(index, inComponent: 0, animated: false) } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension LNSingleSelectionPanel: UIPickerViewDataSource, UIPickerViewDelegate { func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { selections.count } func numberOfComponents(in pickerView: UIPickerView) -> Int { 1 } func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView { let label = UILabel() label.font = .systemFont(ofSize: 22) label.textColor = .text_5 label.text = selections[row] label.textAlignment = .center return label } func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat { 52 } } extension LNSingleSelectionPanel { private func setupViews() { let headerView = buildHeader() container.addSubview(headerView) headerView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.top.equalToSuperview() } pickerView.dataSource = self pickerView.delegate = self container.addSubview(pickerView) pickerView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.top.equalTo(headerView.snp.bottom) make.height.equalTo(240) } 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.backgroundColor = .fill_4 confirmButton.setBackgroundImage(.primary_8, for: .normal) confirmButton.addAction(UIAction(handler: { [weak self] _ in guard let self else { return } dismiss() handler?(pickerView.selectedRow(inComponent: 0)) }), for: .touchUpInside) container.addSubview(confirmButton) confirmButton.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(16) make.top.equalTo(pickerView.snp.bottom).offset(10) make.bottom.equalToSuperview().offset(commonBottomInset) make.height.equalTo(47) } } private func buildHeader() -> UIView { let container = UIView() container.snp.makeConstraints { make in make.height.equalTo(56) } let stackView = UIStackView() stackView.axis = .vertical stackView.spacing = 3 container.addSubview(stackView) stackView.snp.makeConstraints { make in make.centerY.equalToSuperview() make.horizontalEdges.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 } }