Sp2SertifikatCell.swift 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. //
  2. // Sp2SertifikatCell.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. class Sp2SertifikatCell: UITableViewCell {
  11. @IBOutlet weak var card: MDCCard!
  12. @IBOutlet weak var lblAplId: UILabel!
  13. @IBOutlet weak var lblNo: UILabel!
  14. @IBOutlet weak var lblTgl: UILabel!
  15. @IBOutlet weak var lblCustName: UILabel!
  16. @IBOutlet weak var lblEqpName: UILabel!
  17. @IBOutlet weak var lblModels: UILabel!
  18. @IBOutlet weak var lblBiaya: UILabel!
  19. @IBOutlet weak var cbKasi: UIImageView!
  20. @IBOutlet weak var cbKasub: UIImageView!
  21. @IBOutlet weak var cbDirektur: UIImageView!
  22. // Modern Programmatic UI Elements
  23. private let modernContainer = UIView()
  24. private let modernBadgeView = UIView()
  25. private let modernBadgeIcon = UIImageView()
  26. private let modernNomorLabel = UILabel()
  27. private let modernCategoryLabel = UILabel()
  28. private let modernBiayaPill = UIView()
  29. private let modernBiayaLabel = UILabel()
  30. private let modernPerangkatLabel = UILabel()
  31. private let modernCompanyIcon = UIImageView()
  32. private let modernCustLabel = UILabel()
  33. private let modernSpecStack = UIStackView()
  34. private let modernModelCard = UIView()
  35. private let modernModelTitle = UILabel()
  36. private let modernModelVal = UILabel()
  37. private let modernBiayaCard = UIView()
  38. private let modernBiayaTitle = UILabel()
  39. private let modernBiayaVal = UILabel()
  40. private let modernApprovalStack = UIStackView()
  41. private let modernKasiBadge = UIView()
  42. private let modernKasiLabel = UILabel()
  43. private let modernKasubBadge = UIView()
  44. private let modernKasubLabel = UILabel()
  45. private let modernDirutBadge = UIView()
  46. private let modernDirutLabel = UILabel()
  47. private let modernFooterCard = UIView()
  48. private let modernCalendarIcon = UIImageView()
  49. private let modernDateLabel = UILabel()
  50. private let modernAplIdLabel = UILabel()
  51. private var isModernLayoutBuilt = false
  52. override func awakeFromNib() {
  53. super.awakeFromNib()
  54. self.selectionStyle = .none
  55. self.backgroundColor = .clear
  56. setupCardVisuals()
  57. setupModernLayout()
  58. }
  59. private func setupCardVisuals() {
  60. guard let card = card else { return }
  61. card.cornerRadius = 16
  62. card.setShadowElevation(ShadowElevation(rawValue: 2), for: .normal)
  63. card.setShadowColor(UIColor.black.withAlphaComponent(0.06), for: .normal)
  64. card.layer.borderColor = UIColor(red: 228/255, green: 235/255, blue: 245/255, alpha: 1.0).cgColor
  65. card.layer.borderWidth = 1.0
  66. card.backgroundColor = .white
  67. }
  68. private func setupModernLayout() {
  69. guard let card = card, !isModernLayoutBuilt else { return }
  70. isModernLayoutBuilt = true
  71. for subview in card.subviews {
  72. subview.isHidden = true
  73. }
  74. modernContainer.translatesAutoresizingMaskIntoConstraints = false
  75. modernContainer.backgroundColor = .clear
  76. card.addSubview(modernContainer)
  77. NSLayoutConstraint.activate([
  78. modernContainer.topAnchor.constraint(equalTo: card.topAnchor, constant: 14),
  79. modernContainer.bottomAnchor.constraint(equalTo: card.bottomAnchor, constant: -14),
  80. modernContainer.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 14),
  81. modernContainer.trailingAnchor.constraint(equalTo: card.trailingAnchor, constant: -14)
  82. ])
  83. // 1. Header Bar
  84. let headerStack = UIStackView()
  85. headerStack.translatesAutoresizingMaskIntoConstraints = false
  86. headerStack.axis = .horizontal
  87. headerStack.alignment = .center
  88. headerStack.spacing = 10
  89. modernContainer.addSubview(headerStack)
  90. modernBadgeView.translatesAutoresizingMaskIntoConstraints = false
  91. modernBadgeView.backgroundColor = UIColor(red: 235/255, green: 242/255, blue: 252/255, alpha: 1.0)
  92. modernBadgeView.layer.cornerRadius = 8
  93. modernBadgeView.layer.masksToBounds = true
  94. modernBadgeIcon.translatesAutoresizingMaskIntoConstraints = false
  95. if #available(iOS 13.0, *) {
  96. modernBadgeIcon.image = UIImage(systemName: "doc.plaintext.fill")
  97. }
  98. modernBadgeIcon.tintColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  99. modernBadgeIcon.contentMode = .scaleAspectFit
  100. modernBadgeView.addSubview(modernBadgeIcon)
  101. let titleStack = UIStackView()
  102. titleStack.translatesAutoresizingMaskIntoConstraints = false
  103. titleStack.axis = .vertical
  104. titleStack.spacing = 2
  105. modernCategoryLabel.translatesAutoresizingMaskIntoConstraints = false
  106. modernCategoryLabel.font = UIFont.systemFont(ofSize: 10, weight: .bold)
  107. modernCategoryLabel.textColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  108. modernCategoryLabel.text = "SP2 SERTIFIKAT"
  109. modernNomorLabel.translatesAutoresizingMaskIntoConstraints = false
  110. modernNomorLabel.font = UIFont.systemFont(ofSize: 14, weight: .bold)
  111. modernNomorLabel.textColor = UIColor(red: 26/255, green: 32/255, blue: 44/255, alpha: 1.0)
  112. modernNomorLabel.numberOfLines = 1
  113. titleStack.addArrangedSubview(modernCategoryLabel)
  114. titleStack.addArrangedSubview(modernNomorLabel)
  115. modernBiayaPill.translatesAutoresizingMaskIntoConstraints = false
  116. modernBiayaPill.layer.cornerRadius = 12
  117. modernBiayaPill.layer.masksToBounds = true
  118. modernBiayaPill.backgroundColor = UIColor(red: 235/255, green: 242/255, blue: 252/255, alpha: 1.0)
  119. modernBiayaLabel.translatesAutoresizingMaskIntoConstraints = false
  120. modernBiayaLabel.font = UIFont.systemFont(ofSize: 11, weight: .bold)
  121. modernBiayaLabel.textColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  122. modernBiayaPill.addSubview(modernBiayaLabel)
  123. NSLayoutConstraint.activate([
  124. modernBiayaLabel.topAnchor.constraint(equalTo: modernBiayaPill.topAnchor, constant: 5),
  125. modernBiayaLabel.bottomAnchor.constraint(equalTo: modernBiayaPill.bottomAnchor, constant: -5),
  126. modernBiayaLabel.leadingAnchor.constraint(equalTo: modernBiayaPill.leadingAnchor, constant: 10),
  127. modernBiayaLabel.trailingAnchor.constraint(equalTo: modernBiayaPill.trailingAnchor, constant: -10)
  128. ])
  129. headerStack.addArrangedSubview(modernBadgeView)
  130. headerStack.addArrangedSubview(titleStack)
  131. headerStack.addArrangedSubview(modernBiayaPill)
  132. // 2. Equipment Name
  133. modernPerangkatLabel.translatesAutoresizingMaskIntoConstraints = false
  134. modernPerangkatLabel.font = UIFont.systemFont(ofSize: 15, weight: .bold)
  135. modernPerangkatLabel.textColor = UIColor(red: 26/255, green: 32/255, blue: 44/255, alpha: 1.0)
  136. modernPerangkatLabel.numberOfLines = 2
  137. modernContainer.addSubview(modernPerangkatLabel)
  138. // 3. Company Row
  139. let companyStack = UIStackView()
  140. companyStack.translatesAutoresizingMaskIntoConstraints = false
  141. companyStack.axis = .horizontal
  142. companyStack.spacing = 6
  143. companyStack.alignment = .center
  144. modernContainer.addSubview(companyStack)
  145. modernCompanyIcon.translatesAutoresizingMaskIntoConstraints = false
  146. if #available(iOS 13.0, *) {
  147. modernCompanyIcon.image = UIImage(systemName: "building.2.fill")
  148. }
  149. modernCompanyIcon.tintColor = UIColor(red: 113/255, green: 128/255, blue: 150/255, alpha: 1.0)
  150. modernCompanyIcon.contentMode = .scaleAspectFit
  151. modernCustLabel.translatesAutoresizingMaskIntoConstraints = false
  152. modernCustLabel.font = UIFont.systemFont(ofSize: 13, weight: .medium)
  153. modernCustLabel.textColor = UIColor(red: 74/255, green: 85/255, blue: 104/255, alpha: 1.0)
  154. modernCustLabel.numberOfLines = 1
  155. companyStack.addArrangedSubview(modernCompanyIcon)
  156. companyStack.addArrangedSubview(modernCustLabel)
  157. // 4. Spec Stack (Model | Biaya)
  158. modernSpecStack.translatesAutoresizingMaskIntoConstraints = false
  159. modernSpecStack.axis = .horizontal
  160. modernSpecStack.distribution = .fillEqually
  161. modernSpecStack.spacing = 8
  162. modernContainer.addSubview(modernSpecStack)
  163. func styleMiniCard(_ cardView: UIView, titleLabel: UILabel, valLabel: UILabel, title: String) {
  164. cardView.translatesAutoresizingMaskIntoConstraints = false
  165. cardView.backgroundColor = UIColor(red: 248/255, green: 250/255, blue: 253/255, alpha: 1.0)
  166. cardView.layer.cornerRadius = 8
  167. cardView.layer.borderColor = UIColor(red: 235/255, green: 240/255, blue: 248/255, alpha: 1.0).cgColor
  168. cardView.layer.borderWidth = 1
  169. titleLabel.translatesAutoresizingMaskIntoConstraints = false
  170. titleLabel.font = UIFont.systemFont(ofSize: 10, weight: .semibold)
  171. titleLabel.textColor = UIColor(red: 113/255, green: 128/255, blue: 150/255, alpha: 1.0)
  172. titleLabel.text = title
  173. valLabel.translatesAutoresizingMaskIntoConstraints = false
  174. valLabel.font = UIFont.systemFont(ofSize: 12, weight: .semibold)
  175. valLabel.textColor = UIColor(red: 45/255, green: 55/255, blue: 72/255, alpha: 1.0)
  176. valLabel.numberOfLines = 1
  177. let stack = UIStackView(arrangedSubviews: [titleLabel, valLabel])
  178. stack.translatesAutoresizingMaskIntoConstraints = false
  179. stack.axis = .vertical
  180. stack.spacing = 2
  181. cardView.addSubview(stack)
  182. NSLayoutConstraint.activate([
  183. stack.topAnchor.constraint(equalTo: cardView.topAnchor, constant: 6),
  184. stack.bottomAnchor.constraint(equalTo: cardView.bottomAnchor, constant: -6),
  185. stack.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 8),
  186. stack.trailingAnchor.constraint(equalTo: cardView.trailingAnchor, constant: -8)
  187. ])
  188. }
  189. styleMiniCard(modernModelCard, titleLabel: modernModelTitle, valLabel: modernModelVal, title: "MODEL")
  190. styleMiniCard(modernBiayaCard, titleLabel: modernBiayaTitle, valLabel: modernBiayaVal, title: "TOTAL BIAYA")
  191. modernSpecStack.addArrangedSubview(modernModelCard)
  192. modernSpecStack.addArrangedSubview(modernBiayaCard)
  193. // 5. Approval Flow Badges (Kasi, Kasub, Direktur)
  194. modernApprovalStack.translatesAutoresizingMaskIntoConstraints = false
  195. modernApprovalStack.axis = .horizontal
  196. modernApprovalStack.distribution = .fillEqually
  197. modernApprovalStack.spacing = 6
  198. modernContainer.addSubview(modernApprovalStack)
  199. func createStepBadge(_ container: UIView, label: UILabel, role: String) {
  200. container.translatesAutoresizingMaskIntoConstraints = false
  201. container.layer.cornerRadius = 6
  202. container.layer.masksToBounds = true
  203. label.translatesAutoresizingMaskIntoConstraints = false
  204. label.font = UIFont.systemFont(ofSize: 10, weight: .bold)
  205. label.textAlignment = .center
  206. label.text = role
  207. container.addSubview(label)
  208. NSLayoutConstraint.activate([
  209. label.topAnchor.constraint(equalTo: container.topAnchor, constant: 4),
  210. label.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: -4),
  211. label.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 4),
  212. label.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -4)
  213. ])
  214. }
  215. createStepBadge(modernKasiBadge, label: modernKasiLabel, role: "Kasi")
  216. createStepBadge(modernKasubBadge, label: modernKasubLabel, role: "Kasub")
  217. createStepBadge(modernDirutBadge, label: modernDirutLabel, role: "Direktur")
  218. modernApprovalStack.addArrangedSubview(modernKasiBadge)
  219. modernApprovalStack.addArrangedSubview(modernKasubBadge)
  220. modernApprovalStack.addArrangedSubview(modernDirutBadge)
  221. // 6. Footer Bar
  222. modernFooterCard.translatesAutoresizingMaskIntoConstraints = false
  223. modernFooterCard.backgroundColor = UIColor(red: 244/255, green: 248/255, blue: 254/255, alpha: 1.0)
  224. modernFooterCard.layer.cornerRadius = 10
  225. modernContainer.addSubview(modernFooterCard)
  226. modernCalendarIcon.translatesAutoresizingMaskIntoConstraints = false
  227. if #available(iOS 13.0, *) {
  228. modernCalendarIcon.image = UIImage(systemName: "calendar")
  229. }
  230. modernCalendarIcon.tintColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  231. modernCalendarIcon.contentMode = .scaleAspectFit
  232. modernDateLabel.translatesAutoresizingMaskIntoConstraints = false
  233. modernDateLabel.font = UIFont.systemFont(ofSize: 11, weight: .medium)
  234. modernDateLabel.textColor = UIColor(red: 74/255, green: 85/255, blue: 104/255, alpha: 1.0)
  235. modernAplIdLabel.translatesAutoresizingMaskIntoConstraints = false
  236. modernAplIdLabel.font = UIFont.systemFont(ofSize: 10, weight: .bold)
  237. modernAplIdLabel.textColor = UIColor(red: 0/255, green: 82/255, blue: 204/255, alpha: 1.0)
  238. let dateContentStack = UIStackView(arrangedSubviews: [modernCalendarIcon, modernDateLabel])
  239. dateContentStack.translatesAutoresizingMaskIntoConstraints = false
  240. dateContentStack.axis = .horizontal
  241. dateContentStack.spacing = 6
  242. dateContentStack.alignment = .center
  243. let footerStack = UIStackView(arrangedSubviews: [dateContentStack, modernAplIdLabel])
  244. footerStack.translatesAutoresizingMaskIntoConstraints = false
  245. footerStack.axis = .horizontal
  246. footerStack.distribution = .equalSpacing
  247. footerStack.alignment = .center
  248. modernFooterCard.addSubview(footerStack)
  249. // Constraints
  250. NSLayoutConstraint.activate([
  251. headerStack.topAnchor.constraint(equalTo: modernContainer.topAnchor),
  252. headerStack.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  253. headerStack.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  254. modernBadgeView.widthAnchor.constraint(equalToConstant: 34),
  255. modernBadgeView.heightAnchor.constraint(equalToConstant: 34),
  256. modernBadgeIcon.centerXAnchor.constraint(equalTo: modernBadgeView.centerXAnchor),
  257. modernBadgeIcon.centerYAnchor.constraint(equalTo: modernBadgeView.centerYAnchor),
  258. modernBadgeIcon.widthAnchor.constraint(equalToConstant: 18),
  259. modernBadgeIcon.heightAnchor.constraint(equalToConstant: 18),
  260. modernPerangkatLabel.topAnchor.constraint(equalTo: headerStack.bottomAnchor, constant: 10),
  261. modernPerangkatLabel.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  262. modernPerangkatLabel.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  263. companyStack.topAnchor.constraint(equalTo: modernPerangkatLabel.bottomAnchor, constant: 6),
  264. companyStack.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  265. companyStack.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  266. modernCompanyIcon.widthAnchor.constraint(equalToConstant: 14),
  267. modernCompanyIcon.heightAnchor.constraint(equalToConstant: 14),
  268. modernSpecStack.topAnchor.constraint(equalTo: companyStack.bottomAnchor, constant: 10),
  269. modernSpecStack.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  270. modernSpecStack.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  271. modernApprovalStack.topAnchor.constraint(equalTo: modernSpecStack.bottomAnchor, constant: 10),
  272. modernApprovalStack.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  273. modernApprovalStack.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  274. modernFooterCard.topAnchor.constraint(equalTo: modernApprovalStack.bottomAnchor, constant: 10),
  275. modernFooterCard.leadingAnchor.constraint(equalTo: modernContainer.leadingAnchor),
  276. modernFooterCard.trailingAnchor.constraint(equalTo: modernContainer.trailingAnchor),
  277. modernFooterCard.bottomAnchor.constraint(equalTo: modernContainer.bottomAnchor),
  278. modernCalendarIcon.widthAnchor.constraint(equalToConstant: 13),
  279. modernCalendarIcon.heightAnchor.constraint(equalToConstant: 13),
  280. footerStack.topAnchor.constraint(equalTo: modernFooterCard.topAnchor, constant: 8),
  281. footerStack.bottomAnchor.constraint(equalTo: modernFooterCard.bottomAnchor, constant: -8),
  282. footerStack.leadingAnchor.constraint(equalTo: modernFooterCard.leadingAnchor, constant: 10),
  283. footerStack.trailingAnchor.constraint(equalTo: modernFooterCard.trailingAnchor, constant: -10)
  284. ])
  285. }
  286. private func updateBadgeState(_ container: UIView, label: UILabel, role: String, approved: Bool) {
  287. if approved {
  288. container.backgroundColor = UIColor(red: 232/255, green: 248/255, blue: 240/255, alpha: 1.0)
  289. label.textColor = UIColor(red: 16/255, green: 124/255, blue: 65/255, alpha: 1.0)
  290. label.text = "✓ \(role)"
  291. } else {
  292. container.backgroundColor = UIColor(red: 241/255, green: 245/255, blue: 249/255, alpha: 1.0)
  293. label.textColor = UIColor(red: 148/255, green: 163/255, blue: 184/255, alpha: 1.0)
  294. label.text = "○ \(role)"
  295. }
  296. }
  297. func updateViews(sp2Sertifikat: Sp2Sertifikat) {
  298. card?.isInteractable = false
  299. setupModernLayout()
  300. modernAplIdLabel.text = "ID: \(sp2Sertifikat.apl_id)"
  301. lblAplId?.text = "\(sp2Sertifikat.apl_id)"
  302. let sp2No = sp2Sertifikat.sp2_no.isEmpty ? "-" : sp2Sertifikat.sp2_no
  303. modernNomorLabel.text = sp2No
  304. lblNo?.text = sp2No
  305. let datePrefix = String(sp2Sertifikat.sp2_date.prefix(19))
  306. let dateFormatted = CommonHelper.formatDate(from: datePrefix)
  307. modernDateLabel.text = "Tanggal: \(dateFormatted)"
  308. lblTgl?.text = dateFormatted
  309. let cust = sp2Sertifikat.custs.isEmpty ? "-" : sp2Sertifikat.custs
  310. modernCustLabel.text = cust
  311. lblCustName?.text = cust
  312. var eqpName = "-"
  313. var model = "-"
  314. let eqpValue = sp2Sertifikat.eqp_name
  315. let values = eqpValue.split(separator: "&")
  316. if values.count > 0 {
  317. eqpName = String(values[0]).trimmingCharacters(in: .whitespacesAndNewlines)
  318. }
  319. if values.count > 1 {
  320. model = String(values[1]).trimmingCharacters(in: .whitespacesAndNewlines)
  321. }
  322. modernPerangkatLabel.text = eqpName
  323. lblEqpName?.text = eqpName
  324. modernModelVal.text = model
  325. lblModels?.text = model
  326. let formattedBiaya = formatCurrency(sp2Sertifikat.biaya)
  327. modernBiayaLabel.text = formattedBiaya
  328. modernBiayaVal.text = formattedBiaya
  329. lblBiaya?.text = formattedBiaya
  330. let isKasi = sp2Sertifikat.kasiCetak()
  331. let isKasub = sp2Sertifikat.kasubCetak()
  332. let isDirut = sp2Sertifikat.dirutCetak()
  333. updateBadgeState(modernKasiBadge, label: modernKasiLabel, role: "Kasi", approved: isKasi)
  334. updateBadgeState(modernKasubBadge, label: modernKasubLabel, role: "Kasub", approved: isKasub)
  335. updateBadgeState(modernDirutBadge, label: modernDirutLabel, role: "Direktur", approved: isDirut)
  336. cbKasi?.image = UIImage(named: isKasi ? "checked-box" : "unchecked-box")
  337. cbKasub?.image = UIImage(named: isKasub ? "checked-box" : "unchecked-box")
  338. cbDirektur?.image = UIImage(named: isDirut ? "checked-box" : "unchecked-box")
  339. }
  340. private func formatCurrency(_ value: String) -> String {
  341. if let dbl = Double(value) {
  342. let formatter = NumberFormatter()
  343. formatter.numberStyle = .currency
  344. formatter.locale = Locale(identifier: "id_ID")
  345. formatter.currencySymbol = "Rp "
  346. formatter.maximumFractionDigits = 0
  347. if let str = formatter.string(from: NSNumber(value: dbl)) {
  348. return str
  349. }
  350. }
  351. return value.isEmpty ? "-" : "Rp \(value)"
  352. }
  353. }