| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- //
- // LNCreateOrderFromSkillListPanel.swift
- // Lanu
- //
- // Created by OneeChan on 2025/12/2.
- //
- import Foundation
- import UIKit
- import SnapKit
- class LNCreateOrderFromSkillListPanel: LNPopupView {
- private let skillListView = UIStackView()
- private let costLabel = UILabel()
-
- private let minusButton = UIButton()
- private let countLabel = UILabel()
- private let addButton = UIButton()
-
- private var curCount = 1 {
- didSet {
- countLabel.text = "\(curCount)"
- if curCount <= 1 {
- minusButton.isEnabled = false
- } else {
- minusButton.isEnabled = true
- }
- updatePrice()
- }
- }
-
- private var skillItemViews: [LNProfileOrderSkillItemView] = []
- private var curSelected: LNGameMateSkillVO? {
- didSet {
- skillItemViews.forEach {
- $0.isSelected = $0.cur?.id == curSelected?.id
- }
- updatePrice()
- }
- }
-
- override init(frame: CGRect) {
- super.init(frame: frame)
-
- setupViews()
- }
-
- func update(_ skills: [LNGameMateSkillVO], selected: LNGameMateSkillVO?) {
- guard !skills.isEmpty else { return }
- skillListView.arrangedSubviews.forEach {
- skillListView.removeArrangedSubview($0)
- $0.removeFromSuperview()
- }
-
- skills.forEach { skill in
- let view = LNProfileOrderSkillItemView()
- view.update(skill)
- view.onTap { [weak self] in
- guard let self else { return }
- self.curSelected = skill
- }
- skillListView.addArrangedSubview(view)
- skillItemViews.append(view)
- }
-
- curSelected = selected ?? skills[0]
- curCount = 1
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
- extension LNCreateOrderFromSkillListPanel {
- private func updatePrice() {
- guard let skill = curSelected else { return }
- let cost = skill.price * Double(curCount)
- let text: String = .init(key: "A00121", cost.toDisplay, curCount, skill.unit)
- let attrStr = NSMutableAttributedString(string: text)
- let range = (text as NSString).range(of: "\(cost.toDisplay)")
- attrStr.addAttribute(.font, value: UIFont.heading_h2, range: range)
- costLabel.attributedText = attrStr
- }
-
- private func setupViews() {
- skillListView.axis = .vertical
- skillListView.spacing = 8
- container.addSubview(skillListView)
- skillListView.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(16)
- make.top.equalToSuperview().offset(18)
- }
-
- let priceView = buildPriceView()
- container.addSubview(priceView)
- priceView.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.top.equalTo(skillListView.snp.bottom).offset(4)
- }
-
- let orderView = buildOrderButton()
- container.addSubview(orderView)
- orderView.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.top.equalTo(priceView.snp.bottom).offset(17)
- make.bottom.equalTo(commonBottomInset)
- }
- }
-
- private func buildPriceView() -> UIView {
- let container = UIView()
- container.snp.makeConstraints { make in
- make.height.equalTo(54)
- }
-
- let label = UILabel()
- label.text = .init(key: "A00122")
- label.font = .heading_h3
- label.textColor = .text_5
- container.addSubview(label)
- label.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalToSuperview().offset(20)
- }
-
- addButton.setTitle("+", for: .normal)
- addButton.setTitleColor(.text_4, for: .normal)
- addButton.setTitleColor(.text_2, for: .disabled)
- addButton.backgroundColor = .primary_1
- addButton.layer.cornerRadius = 12
- addButton.addAction(UIAction(handler: { [weak self] _ in
- guard let self else { return }
- self.curCount += 1
- }), for: .touchUpInside)
- container.addSubview(addButton)
- addButton.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalToSuperview().offset(-20)
- make.width.height.equalTo(24)
- }
-
- countLabel.font = .body_m
- countLabel.textColor = .text_5
- container.addSubview(countLabel)
- countLabel.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalTo(addButton.snp.leading).offset(-10)
- }
-
- minusButton.setTitle("-", for: .normal)
- minusButton.setTitleColor(.text_4, for: .normal)
- minusButton.setTitleColor(.text_2, for: .disabled)
- minusButton.backgroundColor = .primary_1
- minusButton.layer.cornerRadius = 12
- minusButton.addAction(UIAction(handler: { [weak self] _ in
- guard let self else { return }
- self.curCount -= 1
- }), for: .touchUpInside)
- container.addSubview(minusButton)
- minusButton.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalTo(countLabel.snp.leading).offset(-10)
- make.width.height.equalTo(24)
- }
-
- return container
- }
-
- private func buildOrderButton() -> UIView {
- let container = UIView()
-
- let buttonView = UIView()
- buttonView.backgroundColor = .init(hex: "#1789FF14")
- buttonView.layer.cornerRadius = 23.5
- container.addSubview(buttonView)
- buttonView.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(16)
- make.verticalEdges.equalToSuperview()
- make.height.equalTo(47)
- }
-
- let orderButton = UIButton()
- orderButton.setBackgroundImage(.icSkillOrderLong, for: .normal)
- orderButton.setTitle(.init(key: "A00041"), for: .normal)
- orderButton.setTitleColor(.text_1, for: .normal)
- orderButton.titleLabel?.font = .heading_h3
- orderButton.addAction(UIAction(handler: { [weak self] _ in
- guard let self else { return }
- guard let curSelected else { return }
-
- LNOrderManager.shared.createOrder(
- skillId: curSelected.id, count: curCount, remark: "")
- { [weak self] orderNo in
- guard let self else { return }
- guard orderNo != nil else { return }
-
- dismiss()
- }
- }), for: .touchUpInside)
- buttonView.addSubview(orderButton)
- orderButton.snp.makeConstraints { make in
- make.trailing.equalToSuperview()
- make.verticalEdges.equalToSuperview()
- }
-
- let descView = UIView()
- buttonView.addSubview(descView)
- descView.snp.makeConstraints { make in
- make.leading.verticalEdges.equalToSuperview()
- make.trailing.equalTo(orderButton.snp.leading)
- }
-
- let priceView = UIView()
- descView.addSubview(priceView)
- priceView.snp.makeConstraints { make in
- make.center.equalToSuperview()
- }
-
- let coin = UIImageView.coinImageView()
- priceView.addSubview(coin)
- coin.snp.makeConstraints { make in
- make.leading.centerY.equalToSuperview()
- make.width.height.equalTo(20)
- }
-
- costLabel.font = .body_s
- costLabel.textColor = .text_4
- priceView.addSubview(costLabel)
- costLabel.snp.makeConstraints { make in
- make.verticalEdges.trailing.equalToSuperview()
- make.leading.equalTo(coin.snp.trailing).offset(4)
- }
-
- return container
- }
- }
- private class LNProfileOrderSkillItemView: UIView {
- private let icon = UIImageView()
- private let nameLabel = UILabel()
- private let priceLabel = UILabel()
-
- var cur: LNGameMateSkillVO?
-
- var isSelected: Bool = false {
- didSet {
- if isSelected {
- layer.borderColor = UIColor.init(hex: "#1789FF").cgColor
- backgroundColor = .fill_5
- } else {
- layer.borderColor = UIColor.fill_4.cgColor
- backgroundColor = .clear
- }
- }
- }
-
- func update(_ skill: LNGameMateSkillVO) {
- icon.sd_setImage(with: URL(string: skill.icon))
- nameLabel.text = skill.name
-
- let text: String = .init(key: "A00040", skill.price.toDisplay, skill.unit)
- let attrStr = NSMutableAttributedString(string: text)
- let range = (text as NSString).range(of: "\(skill.price.toDisplay)")
- attrStr.addAttribute(.font, value: UIFont.heading_h4, range: range)
- priceLabel.attributedText = attrStr
-
- cur = skill
- }
-
- override init(frame: CGRect) {
- super.init(frame: frame)
-
- layer.cornerRadius = 12
- layer.borderWidth = 1
- layer.borderColor = UIColor.fill_4.cgColor
- snp.makeConstraints { make in
- make.height.equalTo(52)
- }
-
- addSubview(icon)
- icon.snp.makeConstraints { make in
- make.leading.equalToSuperview().offset(14)
- make.centerY.equalToSuperview()
- make.width.height.equalTo(32)
- }
-
- priceLabel.font = .body_s
- priceLabel.textColor = .text_4
- priceLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal)
- priceLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
- addSubview(priceLabel)
- priceLabel.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalToSuperview().offset(-15)
- }
-
- nameLabel.font = .heading_h4
- nameLabel.textColor = .text_5
- addSubview(nameLabel)
- nameLabel.snp.makeConstraints { make in
- make.leading.equalTo(icon.snp.trailing).offset(10)
- make.centerY.equalToSuperview()
- }
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
- #if DEBUG
- import SwiftUI
- struct LNProfileOrderPanelPreview: UIViewRepresentable {
- func makeUIView(context: Context) -> some UIView {
- let container = UIView()
- container.backgroundColor = .lightGray
-
- let view = LNCreateOrderFromSkillListPanel()
- view.popup(container)
-
- return container
- }
-
- func updateUIView(_ uiView: UIViewType, context: Context) { }
- }
- #Preview(body: {
- LNProfileOrderPanelPreview()
- })
- #endif // DEBUG
|