| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- //
- // SearchSertifikatNewVC.swift
- // Sirani
- //
- // Created by Hendi on 19/06/23.
- // Copyright © 2026 PT. Mitra Sinerji Teknoindo. All rights reserved.
- //
- import UIKit
- protocol SearchSertifikatNewDelegate {
- func onSearch(search: String, status: String, jenisLabel: String)
- }
- class SearchSertifikatNewVC: UIViewController {
-
- // Outlets / Views
- @IBOutlet weak var inputSearch: RoundTextField!
- @IBOutlet weak var optionsLayoutTV: UITableView!
- @IBOutlet weak var optionsLayout: UIView!
- @IBOutlet weak var optionsBg: UIView!
- @IBOutlet weak var btnStatusOptions: UIButton!
-
- // Initialize
- var delegate: SearchSertifikatNewDelegate?
-
- var backtoSertifikatPrivate = "unwindSearchToSertifikatSegueId"
- var backtoSertifikatPublic = "unwindSearchToSertifikatPublicSegueId"
-
- var isSertifikat = 1
- var currentSearch: String = ""
- var currentStatus: String = ""
-
- // Constants value data
- private let statusSertifikatPrivateOptionItems = [
- OptionItem(label: "Semua Sertifikat", value: ""),
- OptionItem(label: "Sertifikat Berlaku", value: "sertifkat_berlaku"),
- OptionItem(label: "Sertifikat Tidak Berlaku", value: "sertifikat_tidak_berlaku"),
- OptionItem(label: "Sertifikat Revisi", value: "sertifikat_revisi")
- ]
- private let statusSertifikatPublicOptionItems = [
- OptionItem(label: "Sertifikat Terbit", value: "sertifikat_terbit"),
- OptionItem(label: "Sertifikat Dicabut", value: "sertifikat_dicabut")
- ]
- private let OPTION_JENIS_SERTIFIKAT_ID = 1
-
- // Others
- private var selectedOptions = 0
- private var selectedOptionItems = [OptionItem]()
- private var optionsShown = false
-
- // Result Values
- private var search = ""
- private var status = ""
- private var jenisLabel = "Semua"
-
- // Modern UI Elements
- private let chipContainerStack = UIStackView()
- private var chipButtons = [UIButton]()
- private let modernCard = UIView()
- private let modernSearchIcon = UIImageView()
- private let btnApplyModern = UIButton(type: .system)
- private let btnResetModern = UIButton(type: .system)
-
- private var isModernFilterBuilt = false
-
- // View Lifecycles
- override var preferredStatusBarStyle: UIStatusBarStyle {
- return .lightContent
- }
-
- override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
-
- setupInitialState()
- updateToolbarTitle()
- buildModernFilterUI()
- updateChipSelection()
- }
- override func viewDidLoad() {
- super.viewDidLoad()
-
- optionsLayoutTV.delegate = self
- optionsLayoutTV.dataSource = self
- optionsLayoutTV.tableFooterView = UIView()
-
- let tapDismiss = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
- tapDismiss.cancelsTouchesInView = false
- view.addGestureRecognizer(tapDismiss)
- }
-
- @objc private func dismissKeyboard() {
- view.endEditing(true)
- }
-
- private func setupInitialState() {
- if !currentSearch.isEmpty {
- search = currentSearch
- inputSearch.text = currentSearch
- } else {
- search = inputSearch.text ?? ""
- }
-
- if isSertifikat == 2 {
- // Public certificates
- if currentStatus == "sertifikat_dicabut" {
- status = "sertifikat_dicabut"
- jenisLabel = "Sertifikat Dicabut"
- } else {
- status = "sertifikat_terbit"
- jenisLabel = "Sertifikat Terbit"
- }
- } else {
- // Private certificates
- if !currentStatus.isEmpty {
- status = currentStatus
- if let matched = statusSertifikatPrivateOptionItems.first(where: { ($0.value as? String) == currentStatus }) {
- jenisLabel = matched.label
- } else {
- jenisLabel = "Sertifikat Berlaku"
- }
- } else {
- status = ""
- jenisLabel = "Semua Sertifikat"
- }
- }
-
- btnStatusOptions.setTitle(jenisLabel, for: .normal)
- hideOptions()
- }
-
- private func updateToolbarTitle() {
- // Find Toolbar Title in subviews and set modern title
- for subview in view.subviews {
- for inner in subview.subviews {
- if let lbl = inner as? UILabel, lbl.text?.lowercased().contains("search") == true {
- lbl.text = "Filter & Pencarian"
- lbl.font = UIFont.systemFont(ofSize: 18, weight: .bold)
- }
- }
- }
- }
-
- private func buildModernFilterUI() {
- guard !isModernFilterBuilt else { return }
- isModernFilterBuilt = true
-
- // Style search input
- inputSearch.layer.cornerRadius = 12
- inputSearch.layer.borderWidth = 1
- inputSearch.layer.borderColor = UIColor(red: 226/255, green: 232/255, blue: 240/255, alpha: 1.0).cgColor
- inputSearch.backgroundColor = UIColor(red: 250/255, green: 251/255, blue: 253/255, alpha: 1.0)
- inputSearch.placeholder = "Cari nomor sertifikat, pemohon, model..."
- inputSearch.clearButtonMode = .whileEditing
-
- // Hide legacy dropdown button & arrow and build modern interactive chips
- btnStatusOptions.isHidden = true
- if let arrowImg = btnStatusOptions.superview?.subviews.first(where: { ($0 as? UIImageView)?.image == UIImage(named: "dropdown") }) {
- arrowImg.isHidden = true
- }
-
- // Find existing CARI and RESET buttons and hide them so we can use our modern action buttons
- for subview in view.subviews {
- findAndHideLegacyActionButtons(in: subview)
- }
-
- guard let container = btnStatusOptions.superview else { return }
-
- // Build Chip Stack
- chipContainerStack.translatesAutoresizingMaskIntoConstraints = false
- chipContainerStack.axis = .horizontal
- chipContainerStack.distribution = .fillEqually
- chipContainerStack.spacing = 8
- chipContainerStack.alignment = .fill
- container.addSubview(chipContainerStack)
-
- let activeOptions = (isSertifikat == 2) ? statusSertifikatPublicOptionItems : statusSertifikatPrivateOptionItems
- chipButtons.removeAll()
-
- for item in activeOptions {
- let btn = UIButton(type: .system)
- btn.translatesAutoresizingMaskIntoConstraints = false
- btn.setTitle(item.label, for: .normal)
- btn.titleLabel?.font = UIFont.systemFont(ofSize: 12, weight: .semibold)
- btn.layer.cornerRadius = 10
- btn.layer.borderWidth = 1
- btn.tag = activeOptions.firstIndex(where: { $0.label == item.label }) ?? 0
- btn.addTarget(self, action: #selector(onChipTapped(_:)), for: .touchUpInside)
-
- chipButtons.append(btn)
- chipContainerStack.addArrangedSubview(btn)
- }
-
- NSLayoutConstraint.activate([
- chipContainerStack.topAnchor.constraint(equalTo: btnStatusOptions.topAnchor),
- chipContainerStack.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16),
- chipContainerStack.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -16),
- chipContainerStack.heightAnchor.constraint(equalToConstant: 44)
- ])
-
- // Modern Action Buttons: Terapkan Filter & Reset
- let buttonStack = UIStackView()
- buttonStack.translatesAutoresizingMaskIntoConstraints = false
- buttonStack.axis = .vertical
- buttonStack.spacing = 10
- container.addSubview(buttonStack)
-
- // 1. Primary Button
- btnApplyModern.translatesAutoresizingMaskIntoConstraints = false
- btnApplyModern.setTitle("🔍 TERAPKAN FILTER", for: .normal)
- btnApplyModern.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .bold)
- btnApplyModern.setTitleColor(.white, for: .normal)
- btnApplyModern.backgroundColor = UIColor.siraniPrimaryBlue
- btnApplyModern.layer.cornerRadius = 12
- btnApplyModern.layer.masksToBounds = false
- btnApplyModern.layer.shadowColor = UIColor.siraniPrimaryBlue.cgColor
- btnApplyModern.layer.shadowOffset = CGSize(width: 0, height: 4)
- btnApplyModern.layer.shadowRadius = 8
- btnApplyModern.layer.shadowOpacity = 0.25
- btnApplyModern.addTarget(self, action: #selector(onSearchTapped(_:)), for: .touchUpInside)
-
- NSLayoutConstraint.activate([
- btnApplyModern.heightAnchor.constraint(equalToConstant: 48)
- ])
- buttonStack.addArrangedSubview(btnApplyModern)
-
- // 2. Secondary Reset Button
- btnResetModern.translatesAutoresizingMaskIntoConstraints = false
- btnResetModern.setTitle("↺ Reset Filter", for: .normal)
- btnResetModern.titleLabel?.font = UIFont.systemFont(ofSize: 13, weight: .semibold)
- btnResetModern.setTitleColor(UIColor(red: 100/255, green: 116/255, blue: 139/255, alpha: 1.0), for: .normal)
- btnResetModern.backgroundColor = UIColor(red: 241/255, green: 245/255, blue: 249/255, alpha: 1.0)
- btnResetModern.layer.cornerRadius = 12
- btnResetModern.layer.borderWidth = 1
- btnResetModern.layer.borderColor = UIColor(red: 226/255, green: 232/255, blue: 240/255, alpha: 1.0).cgColor
- btnResetModern.addTarget(self, action: #selector(onResetTapped(_:)), for: .touchUpInside)
-
- NSLayoutConstraint.activate([
- btnResetModern.heightAnchor.constraint(equalToConstant: 44)
- ])
- buttonStack.addArrangedSubview(btnResetModern)
-
- NSLayoutConstraint.activate([
- buttonStack.topAnchor.constraint(equalTo: chipContainerStack.bottomAnchor, constant: 28),
- buttonStack.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16),
- buttonStack.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -16)
- ])
- }
-
- private func findAndHideLegacyActionButtons(in view: UIView) {
- for sub in view.subviews {
- if let btn = sub as? UIButton {
- let title = btn.title(for: .normal)?.uppercased() ?? ""
- if (title == "CARI" || title == "RESET") && btn != btnApplyModern && btn != btnResetModern {
- btn.isHidden = true
- }
- }
- findAndHideLegacyActionButtons(in: sub)
- }
- }
-
- @objc private func onChipTapped(_ sender: UIButton) {
- let activeOptions = (isSertifikat == 2) ? statusSertifikatPublicOptionItems : statusSertifikatPrivateOptionItems
- guard sender.tag < activeOptions.count else { return }
-
- let item = activeOptions[sender.tag]
- status = item.value as! String
- jenisLabel = item.label
- btnStatusOptions.setTitle(jenisLabel, for: .normal)
-
- updateChipSelection()
- }
-
- private func updateChipSelection() {
- let activeOptions = (isSertifikat == 2) ? statusSertifikatPublicOptionItems : statusSertifikatPrivateOptionItems
- for btn in chipButtons {
- guard btn.tag < activeOptions.count else { continue }
- let item = activeOptions[btn.tag]
- let isSelected = (item.value as! String) == status
-
- if isSelected {
- btn.backgroundColor = UIColor.siraniPrimaryBlue
- btn.setTitleColor(.white, for: .normal)
- btn.layer.borderColor = UIColor.siraniPrimaryBlue.cgColor
- } else {
- btn.backgroundColor = UIColor(red: 248/255, green: 250/255, blue: 253/255, alpha: 1.0)
- btn.setTitleColor(UIColor(red: 71/255, green: 85/255, blue: 105/255, alpha: 1.0), for: .normal)
- btn.layer.borderColor = UIColor(red: 226/255, green: 232/255, blue: 240/255, alpha: 1.0).cgColor
- }
- }
- }
-
- @IBAction func onInputSearchKeyTap(_ sender: Any) {
- view.endEditing(true)
- onSearchTapped(sender)
- }
-
- @IBAction func unwindToSertifikatNew(_ sender: Any) {
- if optionsShown {
- hideOptions()
- } else {
- if isSertifikat == 2 {
- performSegue(withIdentifier: backtoSertifikatPublic, sender: self)
- } else {
- performSegue(withIdentifier: backtoSertifikatPrivate, sender: self)
- }
- }
- }
-
- @IBAction func onJenisSertifikatOptionsTapped(_ sender: Any) {
- selectedOptions = OPTION_JENIS_SERTIFIKAT_ID
- selectedOptionItems.removeAll()
- if isSertifikat == 2 {
- selectedOptionItems += statusSertifikatPublicOptionItems
- } else {
- selectedOptionItems += statusSertifikatPrivateOptionItems
- }
-
- optionsLayoutTV.reloadData()
- showOptions()
- }
-
- @IBAction func onResetTapped(_ sender: Any) {
- search = ""
- inputSearch.text = ""
-
- if isSertifikat == 2 {
- status = "sertifikat_terbit"
- jenisLabel = "Sertifikat Terbit"
- } else {
- status = ""
- jenisLabel = "Semua Sertifikat"
- }
-
- btnStatusOptions.setTitle(jenisLabel, for: .normal)
- updateChipSelection()
- }
-
- @IBAction func onSearchTapped(_ sender: Any) {
- view.endEditing(true)
-
- let searchText = inputSearch.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
- search = searchText
-
- self.delegate?.onSearch(search: search, status: status, jenisLabel: jenisLabel)
-
- if isSertifikat == 2 {
- performSegue(withIdentifier: backtoSertifikatPublic, sender: self)
- } else {
- performSegue(withIdentifier: backtoSertifikatPrivate, sender: self)
- }
- }
-
- private func showOptions() {
- optionsLayout.show()
- optionsShown = true
- }
-
- @objc private func hideOptions() {
- optionsLayout.hide()
- optionsShown = false
- }
- }
- extension SearchSertifikatNewVC: UITableViewDelegate, UITableViewDataSource {
- func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- return selectedOptionItems.count
- }
-
- func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- if let cell = tableView.dequeueReusableCell(withIdentifier: "searchSertifikatNewCell", for: indexPath) as? OptionsCell {
- let optionItem = selectedOptionItems[indexPath.row]
- cell.updateViews(item: optionItem)
- return cell
- } else {
- return OptionsCell()
- }
- }
-
- func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- if selectedOptions == OPTION_JENIS_SERTIFIKAT_ID {
- status = selectedOptionItems[indexPath.row].value as! String
- jenisLabel = selectedOptionItems[indexPath.row].label
- btnStatusOptions.setTitle(jenisLabel, for: .normal)
- updateChipSelection()
- }
- hideOptions()
- }
- }
|