AplikasiStatusCell.swift 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. //
  2. // AplikasiStatusCell.swift
  3. // Sirani
  4. //
  5. // Created by Anhar Solehudin on 21/04/19.
  6. // Copyright © 2019 Anhar Solehudin. All rights reserved.
  7. //
  8. import UIKit
  9. import MaterialComponents.MaterialCards
  10. class AplikasiStatusCell: UITableViewCell {
  11. @IBOutlet weak var card: MDCCard!
  12. @IBOutlet weak var lblAplikasiId: UILabel!
  13. @IBOutlet weak var lblNo: UILabel!
  14. @IBOutlet weak var lblTgl: UILabel!
  15. @IBOutlet weak var lblPlgId: UILabel!
  16. @IBOutlet weak var lblNib: UILabel!
  17. @IBOutlet weak var lblCustName: UILabel!
  18. @IBOutlet weak var lblEqpName: UILabel!
  19. @IBOutlet weak var lblMerk: UILabel!
  20. @IBOutlet weak var lblModel: UILabel!
  21. @IBOutlet weak var lblBrand: UILabel!
  22. @IBOutlet weak var lblStatus: UILabel!
  23. // Modern Programmatic UI Elements
  24. private let modernContainer = UIView()
  25. private let modernBadgeView = UIView()
  26. private let modernBadgeIcon = UIImageView()
  27. private let modernIdLabel = UILabel()
  28. private let modernCategoryLabel = UILabel()
  29. private let modernStatusPill = UIView()
  30. private let modernStatusDot = UIView()
  31. private let modernStatusLabel = UILabel()
  32. private let modernPerangkatLabel = UILabel()
  33. private let modernCompanyIcon = UIImageView()
  34. private let modernCustLabel = UILabel()
  35. private let modernSpecStack = UIStackView()
  36. private let modernMerkCard = UIView()
  37. private let modernMerkTitle = UILabel()
  38. private let modernMerkVal = UILabel()
  39. private let modernNibCard = UIView()
  40. private let modernNibTitle = UILabel()
  41. private let modernNibVal = UILabel()
  42. private let modernFooterCard = UIView()
  43. private let modernCalendarIcon = UIImageView()
  44. private let modernDateLabel = UILabel()
  45. private let modernResiLabel = UILabel()
  46. private var isModernLayoutBuilt = false
  47. override func awakeFromNib() {
  48. super.awakeFromNib()
  49. self.selectionStyle = .none
  50. self.backgroundColor = .clear
  51. setupCardVisuals()
  52. setupModernLayout()
  53. }
  54. private func setupCardVisuals() {
  55. guard let card = card else { return }
  56. card.cornerRadius = 16
  57. card.setShadowElevation(ShadowElevation(rawValue: 2), for: .normal)
  58. card.setShadowColor(UIColor.black.withAlphaComponent(0.06), for: .normal)
  59. card.layer.borderColor = UIColor(red: 228/255, green: 235/255, blue: 245/255, alpha: 1.0).cgColor
  60. card.layer.borderWidth = 1.0
  61. card.backgroundColor = .white
  62. }
  63. private func setupModernLayout() {
  64. guard let card = card, !isModernLayoutBuilt else { return }
  65. isModernLayoutBuilt = true
  66. for subview in card.subviews {
  67. subview.isHidden = true
  68. }
  69. modernContainer.translatesAutoresizingMaskIntoConstraints = false
  70. modernContainer.backgroundColor = .clear
  71. card.addSubview(modernContainer)
  72. NSLayoutConstraint.activate([
  73. modernContainer.topAnchor.constraint(equalTo: card.topAnchor, constant: 14),
  74. modernContainer.bottomAnchor.constraint(equalTo: card.bottomAnchor, constant: -14),
  75. modernContainer.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 14),
  76. modernContainer.trailingAnchor.constraint(equalTo: card.trailingAnchor, constant: -14)
  77. ])
  78. // 1. Header Bar
  79. let headerStack = UIStackView()
  80. headerStack.translatesAutoresizingMaskIntoConstraints = false
  81. headerStack.axis = .horizontal
  82. headerStack.alignment = .center
  83. headerStack.spacing = 10
  84. modernContainer.addSubview(headerStack)
  85. modernBadgeView.translatesAutoresizingMaskIntoConstraints = false
  86. modernBadgeView.backgroundColor = UIColor(red: 235/255, green: 242/255, blue: 252/255, alpha: 1.0)
  87. modernBadgeView.layer.cornerRadius = 8
  88. modernBadgeView.layer.masksToBounds = true
  89. modernBadgeIcon.translatesAutoresizingMaskIntoConstraints = false
  90. if #available(iOS 13.0, *) {
  91. modernBadgeIcon.image = UIImage(systemName: "clock.arrow.circlepath")
  92. }
  93. modernBadgeIcon.tintColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  94. modernBadgeIcon.contentMode = .scaleAspectFit
  95. modernBadgeView.addSubview(modernBadgeIcon)
  96. let titleStack = UIStackView()
  97. titleStack.translatesAutoresizingMaskIntoConstraints = false
  98. titleStack.axis = .vertical
  99. titleStack.spacing = 2
  100. modernCategoryLabel.translatesAutoresizingMaskIntoConstraints = false
  101. modernCategoryLabel.font = UIFont.systemFont(ofSize: 10, weight: .bold)
  102. modernCategoryLabel.textColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  103. modernCategoryLabel.text = "STATUS PERMOHONAN"
  104. modernIdLabel.translatesAutoresizingMaskIntoConstraints = false
  105. modernIdLabel.font = UIFont.systemFont(ofSize: 14, weight: .bold)
  106. modernIdLabel.textColor = UIColor(red: 26/255, green: 32/255, blue: 44/255, alpha: 1.0)
  107. modernIdLabel.numberOfLines = 1
  108. titleStack.addArrangedSubview(modernCategoryLabel)
  109. titleStack.addArrangedSubview(modernIdLabel)
  110. modernStatusPill.translatesAutoresizingMaskIntoConstraints = false
  111. modernStatusPill.layer.cornerRadius = 12
  112. modernStatusPill.layer.masksToBounds = true
  113. modernStatusDot.translatesAutoresizingMaskIntoConstraints = false
  114. modernStatusDot.layer.cornerRadius = 3.5
  115. modernStatusLabel.translatesAutoresizingMaskIntoConstraints = false
  116. modernStatusLabel.font = UIFont.systemFont(ofSize: 11, weight: .bold)
  117. let pillStack = UIStackView(arrangedSubviews: [modernStatusDot, modernStatusLabel])
  118. pillStack.translatesAutoresizingMaskIntoConstraints = false
  119. pillStack.axis = .horizontal
  120. pillStack.spacing = 5
  121. pillStack.alignment = .center
  122. modernStatusPill.addSubview(pillStack)
  123. headerStack.addArrangedSubview(modernBadgeView)
  124. headerStack.addArrangedSubview(titleStack)
  125. headerStack.addArrangedSubview(modernStatusPill)
  126. // 2. Equipment Name
  127. modernPerangkatLabel.translatesAutoresizingMaskIntoConstraints = false
  128. modernPerangkatLabel.font = UIFont.systemFont(ofSize: 15, weight: .bold)
  129. modernPerangkatLabel.textColor = UIColor(red: 26/255, green: 32/255, blue: 44/255, alpha: 1.0)
  130. modernPerangkatLabel.numberOfLines = 2
  131. modernContainer.addSubview(modernPerangkatLabel)
  132. // 3. Company Row
  133. let companyStack = UIStackView()
  134. companyStack.translatesAutoresizingMaskIntoConstraints = false
  135. companyStack.axis = .horizontal
  136. companyStack.spacing = 6
  137. companyStack.alignment = .center
  138. modernContainer.addSubview(companyStack)
  139. modernCompanyIcon.translatesAutoresizingMaskIntoConstraints = false
  140. if #available(iOS 13.0, *) {
  141. modernCompanyIcon.image = UIImage(systemName: "building.2.fill")
  142. }
  143. modernCompanyIcon.tintColor = UIColor(red: 113/255, green: 128/255, blue: 150/255, alpha: 1.0)
  144. modernCompanyIcon.contentMode = .scaleAspectFit
  145. modernCustLabel.translatesAutoresizingMaskIntoConstraints = false
  146. modernCustLabel.font = UIFont.systemFont(ofSize: 13, weight: .medium)
  147. modernCustLabel.textColor = UIColor(red: 74/255, green: 85/255, blue: 104/255, alpha: 1.0)
  148. modernCustLabel.numberOfLines = 1
  149. companyStack.addArrangedSubview(modernCompanyIcon)
  150. companyStack.addArrangedSubview(modernCustLabel)
  151. // 4. Spec Stack (Merk/Model/Brand | NIB/PLG)
  152. modernSpecStack.translatesAutoresizingMaskIntoConstraints = false
  153. modernSpecStack.axis = .horizontal
  154. modernSpecStack.distribution = .fillEqually
  155. modernSpecStack.spacing = 8
  156. modernContainer.addSubview(modernSpecStack)
  157. func styleMiniCard(_ cardView: UIView, titleLabel: UILabel, valLabel: UILabel, title: String) {
  158. cardView.translatesAutoresizingMaskIntoConstraints = false
  159. cardView.backgroundColor = UIColor(red: 248/255, green: 250/255, blue: 253/255, alpha: 1.0)
  160. cardView.layer.cornerRadius = 8
  161. cardView.layer.borderColor = UIColor(red: 235/255, green: 240/255, blue: 248/255, alpha: 1.0).cgColor
  162. cardView.layer.borderWidth = 1
  163. titleLabel.translatesAutoresizingMaskIntoConstraints = false
  164. titleLabel.font = UIFont.systemFont(ofSize: 10, weight: .semibold)
  165. titleLabel.textColor = UIColor(red: 113/255, green: 128/255, blue: 150/255, alpha: 1.0)
  166. titleLabel.text = title
  167. valLabel.translatesAutoresizingMaskIntoConstraints = false
  168. valLabel.font = UIFont.systemFont(ofSize: 12, weight: .semibold)
  169. valLabel.textColor = UIColor(red: 45/255, green: 55/255, blue: 72/255, alpha: 1.0)
  170. valLabel.numberOfLines = 1
  171. let stack = UIStackView(arrangedSubviews: [titleLabel, valLabel])
  172. stack.translatesAutoresizingMaskIntoConstraints = false
  173. stack.axis = .vertical
  174. stack.spacing = 2
  175. cardView.addSubview(stack)
  176. NSLayoutConstraint.activate([
  177. stack.topAnchor.constraint(equalTo: cardView.topAnchor, constant: 6),
  178. stack.bottomAnchor.constraint(equalTo: cardView.bottomAnchor, constant: -6),
  179. stack.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 8),
  180. stack.trailingAnchor.constraint(equalTo: cardView.trailingAnchor, constant: -8)
  181. ])
  182. }
  183. styleMiniCard(modernMerkCard, titleLabel: modernMerkTitle, valLabel: modernMerkVal, title: "MERK / MODEL / BRAND")
  184. styleMiniCard(modernNibCard, titleLabel: modernNibTitle, valLabel: modernNibVal, title: "NIB & ID PELANGGAN")
  185. modernSpecStack.addArrangedSubview(modernMerkCard)
  186. modernSpecStack.addArrangedSubview(modernNibCard)
  187. // 5. Footer Bar
  188. modernFooterCard.translatesAutoresizingMaskIntoConstraints = false
  189. modernFooterCard.backgroundColor = UIColor(red: 244/255, green: 248/255, blue: 254/255, alpha: 1.0)
  190. modernFooterCard.layer.cornerRadius = 10
  191. modernContainer.addSubview(modernFooterCard)
  192. modernCalendarIcon.translatesAutoresizingMaskIntoConstraints = false
  193. if #available(iOS 13.0, *) {
  194. modernCalendarIcon.image = UIImage(systemName: "calendar")
  195. }
  196. modernCalendarIcon.tintColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  197. modernCalendarIcon.contentMode = .scaleAspectFit
  198. modernDateLabel.translatesAutoresizingMaskIntoConstraints = false
  199. modernDateLabel.font = UIFont.systemFont(ofSize: 11, weight: .medium)
  200. modernDateLabel.textColor = UIColor(red: 74/255, green: 85/255, blue: 104/255, alpha: 1.0)
  201. modernResiLabel.translatesAutoresizingMaskIntoConstraints = false
  202. modernResiLabel.font = UIFont.systemFont(ofSize: 10, weight: .bold)
  203. modernResiLabel.textColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  204. let dateContentStack = UIStackView(arrangedSubviews: [modernCalendarIcon, modernDateLabel])
  205. dateContentStack.translatesAutoresizingMaskIntoConstraints = false
  206. dateContentStack.axis = .horizontal
  207. dateContentStack.spacing = 6
  208. dateContentStack.alignment = .center
  209. let footerStack = UIStackView(arrangedSubviews: [dateContentStack, modernResiLabel])
  210. footerStack.translatesAutoresizingMaskIntoConstraints = false
  211. footerStack.axis = .horizontal
  212. footerStack.distribution = .equalSpacing
  213. footerStack.alignment = .center
  214. modernFooterCard.addSubview(footerStack)
  215. // Constraints
  216. NSLayoutConstraint.activate([
  217. headerStack.topAnchor.constraint(equalTo: modernContainer.topAnchor),
  218. headerStack.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  219. headerStack.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  220. modernBadgeView.widthAnchor.constraint(equalToConstant: 34),
  221. modernBadgeView.heightAnchor.constraint(equalToConstant: 34),
  222. modernBadgeIcon.centerXAnchor.constraint(equalTo: modernBadgeView.centerXAnchor),
  223. modernBadgeIcon.centerYAnchor.constraint(equalTo: modernBadgeView.centerYAnchor),
  224. modernBadgeIcon.widthAnchor.constraint(equalToConstant: 18),
  225. modernBadgeIcon.heightAnchor.constraint(equalToConstant: 18),
  226. modernStatusDot.widthAnchor.constraint(equalToConstant: 7),
  227. modernStatusDot.heightAnchor.constraint(equalToConstant: 7),
  228. pillStack.topAnchor.constraint(equalTo: modernStatusPill.topAnchor, constant: 5),
  229. pillStack.bottomAnchor.constraint(equalTo: modernStatusPill.bottomAnchor, constant: -5),
  230. pillStack.leadingAnchor.constraint(equalTo: modernStatusPill.leadingAnchor, constant: 10),
  231. pillStack.trailingAnchor.constraint(equalTo: modernStatusPill.trailingAnchor, constant: -10),
  232. modernPerangkatLabel.topAnchor.constraint(equalTo: headerStack.bottomAnchor, constant: 10),
  233. modernPerangkatLabel.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  234. modernPerangkatLabel.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  235. companyStack.topAnchor.constraint(equalTo: modernPerangkatLabel.bottomAnchor, constant: 6),
  236. companyStack.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  237. companyStack.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  238. modernCompanyIcon.widthAnchor.constraint(equalToConstant: 14),
  239. modernCompanyIcon.heightAnchor.constraint(equalToConstant: 14),
  240. modernSpecStack.topAnchor.constraint(equalTo: companyStack.bottomAnchor, constant: 10),
  241. modernSpecStack.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  242. modernSpecStack.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  243. modernFooterCard.topAnchor.constraint(equalTo: modernSpecStack.bottomAnchor, constant: 10),
  244. modernFooterCard.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  245. modernFooterCard.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  246. modernFooterCard.bottomAnchor.constraint(equalTo: modernContainer.bottomAnchor),
  247. modernCalendarIcon.widthAnchor.constraint(equalToConstant: 13),
  248. modernCalendarIcon.heightAnchor.constraint(equalToConstant: 13),
  249. footerStack.topAnchor.constraint(equalTo: modernFooterCard.topAnchor, constant: 8),
  250. footerStack.bottomAnchor.constraint(equalTo: modernFooterCard.bottomAnchor, constant: -8),
  251. footerStack.leadingAnchor.constraint(equalTo: modernFooterCard.leadingAnchor, constant: 10),
  252. footerStack.trailingAnchor.constraint(equalTo: modernFooterCard.trailingAnchor, constant: -10)
  253. ])
  254. }
  255. private func updateStatusBadge(statusText: String) {
  256. let clean = statusText.trimmingCharacters(in: .whitespacesAndNewlines)
  257. modernStatusLabel.text = clean.isEmpty ? "-" : clean.uppercased()
  258. let lower = clean.lowercased()
  259. if lower.contains("tolak") || lower.contains("batal") || lower.contains("reject") {
  260. modernStatusPill.backgroundColor = UIColor(red: 254/255, green: 226/255, blue: 226/255, alpha: 1.0)
  261. modernStatusLabel.textColor = UIColor(red: 185/255, green: 28/255, blue: 28/255, alpha: 1.0)
  262. modernStatusDot.backgroundColor = UIColor(red: 239/255, green: 68/255, blue: 68/255, alpha: 1.0)
  263. } else if lower.contains("selesai") || lower.contains("terbit") || lower.contains("approved") || lower.contains("setuju") {
  264. modernStatusPill.backgroundColor = UIColor(red: 232/255, green: 248/255, blue: 240/255, alpha: 1.0)
  265. modernStatusLabel.textColor = UIColor(red: 16/255, green: 124/255, blue: 65/255, alpha: 1.0)
  266. modernStatusDot.backgroundColor = UIColor(red: 16/255, green: 124/255, blue: 65/255, alpha: 1.0)
  267. } else {
  268. modernStatusPill.backgroundColor = UIColor(red: 254/255, green: 243/255, blue: 199/255, alpha: 1.0)
  269. modernStatusLabel.textColor = UIColor(red: 180/255, green: 83/255, blue: 9/255, alpha: 1.0)
  270. modernStatusDot.backgroundColor = UIColor(red: 245/255, green: 158/255, blue: 11/255, alpha: 1.0)
  271. }
  272. }
  273. func updateViews(aplikasiStatus: AplikasiStatus) {
  274. card?.isInteractable = false
  275. setupModernLayout()
  276. modernIdLabel.text = "APL ID: \(aplikasiStatus.apl_id)"
  277. lblAplikasiId?.text = "\(aplikasiStatus.apl_id)"
  278. let resi = aplikasiStatus.resi_cek.isEmpty ? "-" : aplikasiStatus.resi_cek
  279. modernResiLabel.text = "Resi: \(resi)"
  280. lblNo?.text = resi
  281. let tglFormatted = CommonHelper.formatDate(from: aplikasiStatus.tgla)
  282. modernDateLabel.text = "Tanggal: \(tglFormatted)"
  283. lblTgl?.text = "\(tglFormatted)"
  284. let plgId = "\(aplikasiStatus.plg_id)"
  285. let nib = aplikasiStatus.nib.isEmpty ? "-" : aplikasiStatus.nib
  286. lblPlgId?.text = "PLG ID: \(plgId)"
  287. lblNib?.text = "NIB: \(nib)"
  288. modernNibVal.text = "NIB: \(nib) | PLG: \(plgId)"
  289. let cust = aplikasiStatus.custs.isEmpty ? "-" : aplikasiStatus.custs
  290. modernCustLabel.text = cust
  291. lblCustName?.text = cust
  292. let eqp = aplikasiStatus.eqp_name.isEmpty ? "-" : aplikasiStatus.eqp_name
  293. modernPerangkatLabel.text = eqp
  294. lblEqpName?.text = eqp
  295. var merk = "-"
  296. var model = "-"
  297. var brand = "-"
  298. let merkModelBrand = aplikasiStatus.merk_model_brand
  299. let values = merkModelBrand.split(separator: "&")
  300. if values.count >= 1 {
  301. let m = String(values[0]).trimmingCharacters(in: .whitespacesAndNewlines)
  302. if !m.isEmpty { merk = m }
  303. }
  304. if values.count >= 2 {
  305. let mod = String(values[1]).trimmingCharacters(in: .whitespacesAndNewlines)
  306. if !mod.isEmpty { model = mod }
  307. }
  308. if values.count >= 3 {
  309. let b = String(values[2]).trimmingCharacters(in: .whitespacesAndNewlines)
  310. if !b.isEmpty { brand = b }
  311. }
  312. lblMerk?.text = "Merk: \(merk)"
  313. lblModel?.text = "Model: \(model)"
  314. lblBrand?.text = "Brand: \(brand)"
  315. modernMerkVal.text = "\(merk) / \(model) / \(brand)"
  316. lblStatus?.text = "STATUS: \(aplikasiStatus.status)"
  317. updateStatusBadge(statusText: aplikasiStatus.status)
  318. }
  319. }