// // LNSkillFieldBaseEditView.swift // Gami // // Created by OneeChan on 2026/1/21. // import Foundation import UIKit import SnapKit protocol LNSkillFieldBaseEditViewDelegate: AnyObject { func onSkillFieldBaseEditViewInputChanged(view: LNSkillFieldBaseEditView) } class LNSkillFieldBaseEditView: LNJoinUsInputFieldGroupView { private(set) var field: LNSkillEditField? var needReview: Bool = false weak var delegate: LNSkillFieldBaseEditViewDelegate? func update(_ field: LNSkillEditField) { titleLabel.text = field.fieldName descLabel.text = field.fieldDesc descLabel.isHidden = field.fieldDesc.isEmpty if let example = field.example, !example.value.isEmpty { showExample { switch example.type { case .photo: let panel = LNJoinUsPhotoExamplePanel() panel.update(example) panel.popup() case .voice: let panel = LNJoinUsVoiceExamplePanel() panel.update(example) panel.popup() } } } self.field = field } func hasInput() -> Bool { guard let field else { return false } if !field.validate.required { return true } return field.value != nil } func checkAvailable() -> Bool { guard let field else { return false } if !field.validate.required { return true } let isMatchLimit = if field.array { checkArrayAvailable() } else { checkValueAvailable() } return isMatchLimit } private func checkArrayAvailable() -> Bool { guard let field else { return false } if !field.validate.required { return true } guard let limit = field.validate.arraySize else { if field.value == nil { showToast(.init(key: "B00064", field.fieldName)) return false } else { return true } } let count = if let texts = field.value as? [String] { texts.count } else if let numbers = field.value as? [Int] { numbers.count } else if let numbers = field.value as? [Double] { numbers.count } else { 0 } if count < limit.min { showToast(.init(key: "B00059", limit.min, field.fieldName)) return false } else if count > limit.max { return false } else { return true } } private func checkValueAvailable() -> Bool { guard let field else { return false } if !field.validate.required { return true } switch field.type { case .singleLineText, .multiLineText: guard let text = field.value as? String else { showToast(.init(key: "B00065", field.fieldName)) return false } guard let size = field.validate.size else { return true } if text.count < size.min { showToast(.init(key: "B00066", field.fieldName, size.min)) return false } else if text.count > size.max { return false } else { return true } case .singleSelection: if field.value == nil { showToast(.init(key: "B00064", field.fieldName)) return false } else { return true } case .multiSelection: if (field.value as? [String])?.isEmpty != false { showToast(.init(key: "B00064", field.fieldName)) return false } else { return true } case .number: guard let limit = field.validate.numLimit else { if field.value == nil { showToast(.init(key: "B00065", field.fieldName)) return false } else { return true } } if let number = field.value as? Int { if Double(number) < limit.min { showToast(.init(key: "B00067", field.fieldName, limit.min.toDisplay)) return false } else if Double(number) > limit.max { showToast(.init(key: "B00068", field.fieldName, limit.max.toDisplay)) return false } else { return true } } else if let number = field.value as? Double { if number < limit.min { showToast(.init(key: "B00067", field.fieldName, limit.min.toDisplay)) return false } else if number > limit.max { showToast(.init(key: "B00068", field.fieldName, limit.max.toDisplay)) return false } else { return true } } else { return false } case .photo: if (field.value as? [String])?.isEmpty != false { showToast(.init(key: "B00069", field.fieldName)) return false } else { return true } case .voice: guard (field.value as? String)?.isEmpty == false else { showToast(.init(key: "B00070", field.fieldName)) return false } guard let limit = field.validate.numLimit else { return true } if Double(field.duration) < limit.min { showToast(.init(key: "B00009", limit.max)) return false // } else if Double(field.duration) > limit.max { // return false } else { return true } case .unknown: return false } } }