DaftarRhuCell.swift 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. //
  2. // DaftarRhuCell.swift
  3. // Sirani
  4. //
  5. // Created by Anhar Solehudin on 27/04/19.
  6. // Copyright © 2019 Anhar Solehudin. All rights reserved.
  7. //
  8. import UIKit
  9. import MaterialComponents.MaterialCards
  10. protocol DaftarRhuCellDelegate: NSObjectProtocol {
  11. func download(urlWeb: String?)
  12. }
  13. class DaftarRhuCell: UITableViewCell {
  14. @IBOutlet weak var card: MDCCard!
  15. @IBOutlet weak var lblAplkasiId: UILabel!
  16. @IBOutlet weak var lblNo: UILabel!
  17. @IBOutlet weak var lblDate: UILabel!
  18. @IBOutlet weak var lblPlgId: UILabel!
  19. @IBOutlet weak var lblCustName: UILabel!
  20. @IBOutlet weak var lblEqoName: UILabel!
  21. @IBOutlet weak var lblModels: UILabel!
  22. @IBOutlet weak var lblMerk: UILabel!
  23. @IBOutlet weak var lblStatus: UILabel!
  24. @IBOutlet weak var lblJumlah: UILabel!
  25. @IBOutlet weak var btnDwnldLhu: UIButton!
  26. @IBOutlet weak var btnDwnlEmc: UIButton!
  27. var cellDelegate: DaftarRhuCellDelegate?
  28. var urlEmc = ""
  29. var urlLhu = ""
  30. // Modern Programmatic UI Elements
  31. private let modernContainer = UIView()
  32. private let modernBadgeView = UIView()
  33. private let modernBadgeIcon = UIImageView()
  34. private let modernNomorLabel = UILabel()
  35. private let modernCategoryLabel = UILabel()
  36. private let modernStatusPill = UIView()
  37. private let modernStatusDot = UIView()
  38. private let modernStatusLabel = UILabel()
  39. private let modernPerangkatLabel = UILabel()
  40. private let modernCompanyIcon = UIImageView()
  41. private let modernCustLabel = UILabel()
  42. private let modernSpecStack = UIStackView()
  43. private let modernMerkCard = UIView()
  44. private let modernMerkTitle = UILabel()
  45. private let modernMerkVal = UILabel()
  46. private let modernJmlCard = UIView()
  47. private let modernJmlTitle = UILabel()
  48. private let modernJmlVal = UILabel()
  49. private let modernFooterCard = UIView()
  50. private let modernCalendarIcon = UIImageView()
  51. private let modernDateLabel = UILabel()
  52. private let modernAplIdLabel = UILabel()
  53. private let modernActionStack = UIStackView()
  54. private let modernBtnLhu = UIButton(type: .system)
  55. private let modernBtnEmc = UIButton(type: .system)
  56. private var isModernLayoutBuilt = false
  57. override func awakeFromNib() {
  58. super.awakeFromNib()
  59. self.selectionStyle = .none
  60. self.backgroundColor = .clear
  61. setupCardVisuals()
  62. setupModernLayout()
  63. }
  64. private func setupCardVisuals() {
  65. guard let card = card else { return }
  66. card.cornerRadius = 16
  67. card.setShadowElevation(ShadowElevation(rawValue: 2), for: .normal)
  68. card.setShadowColor(UIColor.black.withAlphaComponent(0.06), for: .normal)
  69. card.layer.borderColor = UIColor(red: 228/255, green: 235/255, blue: 245/255, alpha: 1.0).cgColor
  70. card.layer.borderWidth = 1.0
  71. card.backgroundColor = .white
  72. }
  73. private func setupModernLayout() {
  74. guard let card = card, !isModernLayoutBuilt else { return }
  75. isModernLayoutBuilt = true
  76. for subview in card.subviews {
  77. subview.isHidden = true
  78. }
  79. modernContainer.translatesAutoresizingMaskIntoConstraints = false
  80. modernContainer.backgroundColor = .clear
  81. card.addSubview(modernContainer)
  82. NSLayoutConstraint.activate([
  83. modernContainer.topAnchor.constraint(equalTo: card.topAnchor, constant: 14),
  84. modernContainer.bottomAnchor.constraint(equalTo: card.bottomAnchor, constant: -14),
  85. modernContainer.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 14),
  86. modernContainer.trailingAnchor.constraint(equalTo: card.trailingAnchor, constant: -14)
  87. ])
  88. // 1. Header Bar
  89. let headerStack = UIStackView()
  90. headerStack.translatesAutoresizingMaskIntoConstraints = false
  91. headerStack.axis = .horizontal
  92. headerStack.alignment = .center
  93. headerStack.spacing = 10
  94. modernContainer.addSubview(headerStack)
  95. modernBadgeView.translatesAutoresizingMaskIntoConstraints = false
  96. modernBadgeView.backgroundColor = UIColor(red: 235/255, green: 242/255, blue: 252/255, alpha: 1.0)
  97. modernBadgeView.layer.cornerRadius = 8
  98. modernBadgeView.layer.masksToBounds = true
  99. modernBadgeIcon.translatesAutoresizingMaskIntoConstraints = false
  100. if #available(iOS 13.0, *) {
  101. modernBadgeIcon.image = UIImage(systemName: "doc.badge.gearshape")
  102. }
  103. modernBadgeIcon.tintColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  104. modernBadgeIcon.contentMode = .scaleAspectFit
  105. modernBadgeView.addSubview(modernBadgeIcon)
  106. let titleStack = UIStackView()
  107. titleStack.translatesAutoresizingMaskIntoConstraints = false
  108. titleStack.axis = .vertical
  109. titleStack.spacing = 2
  110. modernCategoryLabel.translatesAutoresizingMaskIntoConstraints = false
  111. modernCategoryLabel.font = UIFont.systemFont(ofSize: 10, weight: .bold)
  112. modernCategoryLabel.textColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  113. modernCategoryLabel.text = "LAPORAN RHU"
  114. modernNomorLabel.translatesAutoresizingMaskIntoConstraints = false
  115. modernNomorLabel.font = UIFont.systemFont(ofSize: 14, weight: .bold)
  116. modernNomorLabel.textColor = UIColor(red: 26/255, green: 32/255, blue: 44/255, alpha: 1.0)
  117. modernNomorLabel.numberOfLines = 1
  118. titleStack.addArrangedSubview(modernCategoryLabel)
  119. titleStack.addArrangedSubview(modernNomorLabel)
  120. modernStatusPill.translatesAutoresizingMaskIntoConstraints = false
  121. modernStatusPill.layer.cornerRadius = 12
  122. modernStatusPill.layer.masksToBounds = true
  123. modernStatusPill.backgroundColor = UIColor(red: 232/255, green: 248/255, blue: 240/255, alpha: 1.0)
  124. modernStatusDot.translatesAutoresizingMaskIntoConstraints = false
  125. modernStatusDot.layer.cornerRadius = 3.5
  126. modernStatusDot.backgroundColor = UIColor(red: 16/255, green: 124/255, blue: 65/255, alpha: 1.0)
  127. modernStatusLabel.translatesAutoresizingMaskIntoConstraints = false
  128. modernStatusLabel.font = UIFont.systemFont(ofSize: 11, weight: .bold)
  129. modernStatusLabel.textColor = UIColor(red: 16/255, green: 124/255, blue: 65/255, alpha: 1.0)
  130. modernStatusLabel.text = "RHU"
  131. let pillStack = UIStackView(arrangedSubviews: [modernStatusDot, modernStatusLabel])
  132. pillStack.translatesAutoresizingMaskIntoConstraints = false
  133. pillStack.axis = .horizontal
  134. pillStack.spacing = 5
  135. pillStack.alignment = .center
  136. modernStatusPill.addSubview(pillStack)
  137. headerStack.addArrangedSubview(modernBadgeView)
  138. headerStack.addArrangedSubview(titleStack)
  139. headerStack.addArrangedSubview(modernStatusPill)
  140. // 2. Equipment Name
  141. modernPerangkatLabel.translatesAutoresizingMaskIntoConstraints = false
  142. modernPerangkatLabel.font = UIFont.systemFont(ofSize: 15, weight: .bold)
  143. modernPerangkatLabel.textColor = UIColor(red: 26/255, green: 32/255, blue: 44/255, alpha: 1.0)
  144. modernPerangkatLabel.numberOfLines = 2
  145. modernContainer.addSubview(modernPerangkatLabel)
  146. // 3. Company Row
  147. let companyStack = UIStackView()
  148. companyStack.translatesAutoresizingMaskIntoConstraints = false
  149. companyStack.axis = .horizontal
  150. companyStack.spacing = 6
  151. companyStack.alignment = .center
  152. modernContainer.addSubview(companyStack)
  153. modernCompanyIcon.translatesAutoresizingMaskIntoConstraints = false
  154. if #available(iOS 13.0, *) {
  155. modernCompanyIcon.image = UIImage(systemName: "building.2.fill")
  156. }
  157. modernCompanyIcon.tintColor = UIColor(red: 113/255, green: 128/255, blue: 150/255, alpha: 1.0)
  158. modernCompanyIcon.contentMode = .scaleAspectFit
  159. modernCustLabel.translatesAutoresizingMaskIntoConstraints = false
  160. modernCustLabel.font = UIFont.systemFont(ofSize: 13, weight: .medium)
  161. modernCustLabel.textColor = UIColor(red: 74/255, green: 85/255, blue: 104/255, alpha: 1.0)
  162. modernCustLabel.numberOfLines = 1
  163. companyStack.addArrangedSubview(modernCompanyIcon)
  164. companyStack.addArrangedSubview(modernCustLabel)
  165. // 4. Spec Stack (Merk/Model | Jml/PLG)
  166. modernSpecStack.translatesAutoresizingMaskIntoConstraints = false
  167. modernSpecStack.axis = .horizontal
  168. modernSpecStack.distribution = .fillEqually
  169. modernSpecStack.spacing = 8
  170. modernContainer.addSubview(modernSpecStack)
  171. func styleMiniCard(_ cardView: UIView, titleLabel: UILabel, valLabel: UILabel, title: String) {
  172. cardView.translatesAutoresizingMaskIntoConstraints = false
  173. cardView.backgroundColor = UIColor(red: 248/255, green: 250/255, blue: 253/255, alpha: 1.0)
  174. cardView.layer.cornerRadius = 8
  175. cardView.layer.borderColor = UIColor(red: 235/255, green: 240/255, blue: 248/255, alpha: 1.0).cgColor
  176. cardView.layer.borderWidth = 1
  177. titleLabel.translatesAutoresizingMaskIntoConstraints = false
  178. titleLabel.font = UIFont.systemFont(ofSize: 10, weight: .semibold)
  179. titleLabel.textColor = UIColor(red: 113/255, green: 128/255, blue: 150/255, alpha: 1.0)
  180. titleLabel.text = title
  181. valLabel.translatesAutoresizingMaskIntoConstraints = false
  182. valLabel.font = UIFont.systemFont(ofSize: 12, weight: .semibold)
  183. valLabel.textColor = UIColor(red: 45/255, green: 55/255, blue: 72/255, alpha: 1.0)
  184. valLabel.numberOfLines = 1
  185. let stack = UIStackView(arrangedSubviews: [titleLabel, valLabel])
  186. stack.translatesAutoresizingMaskIntoConstraints = false
  187. stack.axis = .vertical
  188. stack.spacing = 2
  189. cardView.addSubview(stack)
  190. NSLayoutConstraint.activate([
  191. stack.topAnchor.constraint(equalTo: cardView.topAnchor, constant: 6),
  192. stack.bottomAnchor.constraint(equalTo: cardView.bottomAnchor, constant: -6),
  193. stack.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 8),
  194. stack.trailingAnchor.constraint(equalTo: cardView.trailingAnchor, constant: -8)
  195. ])
  196. }
  197. styleMiniCard(modernMerkCard, titleLabel: modernMerkTitle, valLabel: modernMerkVal, title: "MERK & MODEL")
  198. styleMiniCard(modernJmlCard, titleLabel: modernJmlTitle, valLabel: modernJmlVal, title: "JUMLAH EVALUASI")
  199. modernSpecStack.addArrangedSubview(modernMerkCard)
  200. modernSpecStack.addArrangedSubview(modernJmlCard)
  201. // 5. Footer Bar
  202. modernFooterCard.translatesAutoresizingMaskIntoConstraints = false
  203. modernFooterCard.backgroundColor = UIColor(red: 244/255, green: 248/255, blue: 254/255, alpha: 1.0)
  204. modernFooterCard.layer.cornerRadius = 10
  205. modernContainer.addSubview(modernFooterCard)
  206. modernCalendarIcon.translatesAutoresizingMaskIntoConstraints = false
  207. if #available(iOS 13.0, *) {
  208. modernCalendarIcon.image = UIImage(systemName: "calendar")
  209. }
  210. modernCalendarIcon.tintColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  211. modernCalendarIcon.contentMode = .scaleAspectFit
  212. modernDateLabel.translatesAutoresizingMaskIntoConstraints = false
  213. modernDateLabel.font = UIFont.systemFont(ofSize: 11, weight: .medium)
  214. modernDateLabel.textColor = UIColor(red: 74/255, green: 85/255, blue: 104/255, alpha: 1.0)
  215. modernAplIdLabel.translatesAutoresizingMaskIntoConstraints = false
  216. modernAplIdLabel.font = UIFont.systemFont(ofSize: 10, weight: .bold)
  217. modernAplIdLabel.textColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  218. let dateContentStack = UIStackView(arrangedSubviews: [modernCalendarIcon, modernDateLabel])
  219. dateContentStack.translatesAutoresizingMaskIntoConstraints = false
  220. dateContentStack.axis = .horizontal
  221. dateContentStack.spacing = 6
  222. dateContentStack.alignment = .center
  223. let footerStack = UIStackView(arrangedSubviews: [dateContentStack, modernAplIdLabel])
  224. footerStack.translatesAutoresizingMaskIntoConstraints = false
  225. footerStack.axis = .horizontal
  226. footerStack.distribution = .equalSpacing
  227. footerStack.alignment = .center
  228. modernFooterCard.addSubview(footerStack)
  229. // 6. Action Buttons Bar (Download LHU & EMC)
  230. modernActionStack.translatesAutoresizingMaskIntoConstraints = false
  231. modernActionStack.axis = .horizontal
  232. modernActionStack.distribution = .fillEqually
  233. modernActionStack.spacing = 8
  234. modernContainer.addSubview(modernActionStack)
  235. func styleActionButton(_ button: UIButton, title: String, iconName: String, action: Selector) {
  236. button.translatesAutoresizingMaskIntoConstraints = false
  237. button.setTitle(" \(title)", for: .normal)
  238. if #available(iOS 13.0, *) {
  239. button.setImage(UIImage(systemName: iconName), for: .normal)
  240. }
  241. button.tintColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  242. button.titleLabel?.font = UIFont.systemFont(ofSize: 11, weight: .semibold)
  243. button.backgroundColor = UIColor(red: 235/255, green: 242/255, blue: 252/255, alpha: 1.0)
  244. button.layer.cornerRadius = 8
  245. button.layer.borderWidth = 1
  246. button.layer.borderColor = UIColor(red: 218/255, green: 230/255, blue: 247/255, alpha: 1.0).cgColor
  247. button.heightAnchor.constraint(equalToConstant: 34).isActive = true
  248. button.addTarget(self, action: action, for: .touchUpInside)
  249. }
  250. styleActionButton(modernBtnLhu, title: "Download LHU", iconName: "arrow.down.doc", action: #selector(onModernLhuTap))
  251. styleActionButton(modernBtnEmc, title: "Download EMC", iconName: "bolt.horizontal.doc", action: #selector(onModernEmcTap))
  252. modernActionStack.addArrangedSubview(modernBtnLhu)
  253. modernActionStack.addArrangedSubview(modernBtnEmc)
  254. // Constraints
  255. NSLayoutConstraint.activate([
  256. headerStack.topAnchor.constraint(equalTo: modernContainer.topAnchor),
  257. headerStack.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  258. headerStack.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  259. modernBadgeView.widthAnchor.constraint(equalToConstant: 34),
  260. modernBadgeView.heightAnchor.constraint(equalToConstant: 34),
  261. modernBadgeIcon.centerXAnchor.constraint(equalTo: modernBadgeView.centerXAnchor),
  262. modernBadgeIcon.centerYAnchor.constraint(equalTo: modernBadgeView.centerYAnchor),
  263. modernBadgeIcon.widthAnchor.constraint(equalToConstant: 18),
  264. modernBadgeIcon.heightAnchor.constraint(equalToConstant: 18),
  265. modernStatusDot.widthAnchor.constraint(equalToConstant: 7),
  266. modernStatusDot.heightAnchor.constraint(equalToConstant: 7),
  267. pillStack.topAnchor.constraint(equalTo: modernStatusPill.topAnchor, constant: 5),
  268. pillStack.bottomAnchor.constraint(equalTo: modernStatusPill.bottomAnchor, constant: -5),
  269. pillStack.leadingAnchor.constraint(equalTo: modernStatusPill.leadingAnchor, constant: 10),
  270. pillStack.trailingAnchor.constraint(equalTo: modernStatusPill.trailingAnchor, constant: -10),
  271. modernPerangkatLabel.topAnchor.constraint(equalTo: headerStack.bottomAnchor, constant: 10),
  272. modernPerangkatLabel.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  273. modernPerangkatLabel.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  274. companyStack.topAnchor.constraint(equalTo: modernPerangkatLabel.bottomAnchor, constant: 6),
  275. companyStack.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  276. companyStack.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  277. modernCompanyIcon.widthAnchor.constraint(equalToConstant: 14),
  278. modernCompanyIcon.heightAnchor.constraint(equalToConstant: 14),
  279. modernSpecStack.topAnchor.constraint(equalTo: companyStack.bottomAnchor, constant: 10),
  280. modernSpecStack.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  281. modernSpecStack.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  282. modernFooterCard.topAnchor.constraint(equalTo: modernSpecStack.bottomAnchor, constant: 10),
  283. modernFooterCard.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  284. modernFooterCard.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  285. modernCalendarIcon.widthAnchor.constraint(equalToConstant: 13),
  286. modernCalendarIcon.heightAnchor.constraint(equalToConstant: 13),
  287. footerStack.topAnchor.constraint(equalTo: modernFooterCard.topAnchor, constant: 8),
  288. footerStack.bottomAnchor.constraint(equalTo: modernFooterCard.bottomAnchor, constant: -8),
  289. footerStack.leadingAnchor.constraint(equalTo: modernFooterCard.leadingAnchor, constant: 10),
  290. footerStack.trailingAnchor.constraint(equalTo: modernFooterCard.trailingAnchor, constant: -10),
  291. modernActionStack.topAnchor.constraint(equalTo: modernFooterCard.bottomAnchor, constant: 10),
  292. modernActionStack.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  293. modernActionStack.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  294. modernActionStack.bottomAnchor.constraint(equalTo: modernContainer.bottomAnchor)
  295. ])
  296. }
  297. @objc private func onModernLhuTap() {
  298. cellDelegate?.download(urlWeb: urlLhu)
  299. }
  300. @objc private func onModernEmcTap() {
  301. cellDelegate?.download(urlWeb: urlEmc)
  302. }
  303. func updateViews(daftarRhu: DaftarRhu) {
  304. card?.isInteractable = false
  305. setupModernLayout()
  306. urlEmc = daftarRhu.file_emc
  307. urlLhu = daftarRhu.file_lhu
  308. var aplId = "-"
  309. if let aplIdValue = daftarRhu.apl_id {
  310. aplId = "\(aplIdValue)"
  311. }
  312. lblAplkasiId?.text = aplId
  313. modernAplIdLabel.text = "ID: \(aplId)"
  314. let rhuNo = daftarRhu.rhu_no.isEmpty ? "-" : daftarRhu.rhu_no
  315. lblNo?.text = rhuNo
  316. modernNomorLabel.text = rhuNo
  317. let date = String(daftarRhu.upload_file_date_convert.prefix(10))
  318. let dateFormatted = CommonHelper.formatDate(from: date)
  319. lblDate?.text = dateFormatted
  320. modernDateLabel.text = "Upload: \(dateFormatted)"
  321. var plgId = "-"
  322. if let plgIdValue = daftarRhu.plg_id {
  323. plgId = "\(plgIdValue)"
  324. }
  325. lblPlgId?.text = "PLG ID: \(plgId)"
  326. var custName = "-"
  327. if let custNameValue = daftarRhu.custs {
  328. custName = "\(custNameValue)"
  329. }
  330. lblCustName?.text = custName
  331. modernCustLabel.text = custName
  332. let eqp = daftarRhu.eqp_name.isEmpty ? "-" : daftarRhu.eqp_name
  333. lblEqoName?.text = eqp
  334. modernPerangkatLabel.text = eqp
  335. let models = daftarRhu.models.isEmpty ? "-" : daftarRhu.models
  336. let merk = daftarRhu.merk.isEmpty ? "-" : daftarRhu.merk
  337. lblModels?.text = models
  338. lblMerk?.text = merk
  339. modernMerkVal.text = "\(merk) / \(models)"
  340. let jmleval = "\(daftarRhu.jmleval)"
  341. lblJumlah?.text = "JML: \(jmleval)"
  342. modernJmlVal.text = "JML: \(jmleval) | PLG: \(plgId)"
  343. var status = "RHU"
  344. if let statusValue = daftarRhu.tab_desc, !statusValue.isEmpty {
  345. status = statusValue
  346. }
  347. lblStatus?.text = "STATUS: \(status)"
  348. modernStatusLabel.text = status.uppercased()
  349. modernBtnLhu.alpha = urlLhu.isEmpty ? 0.4 : 1.0
  350. modernBtnEmc.alpha = urlEmc.isEmpty ? 0.4 : 1.0
  351. }
  352. @IBAction func onBtnLhuTap(_ sender: Any) {
  353. cellDelegate?.download(urlWeb: urlLhu)
  354. }
  355. @IBAction func onBtnEmcTap(_ sender: Any) {
  356. cellDelegate?.download(urlWeb: urlEmc)
  357. }
  358. }