SetInternalCSAccount.swift 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. //
  2. // SetInternalAccount.swift
  3. // NexilisLite
  4. //
  5. // Created by Akhmad Al Qindi Irsyam on 23/02/23.
  6. //
  7. import UIKit
  8. import NotificationBannerSwift
  9. public class SetInternalCSAccount: UITableViewController {
  10. private var searchController: UISearchController!
  11. public var isSetCS = false
  12. var fromNotification = false
  13. private var availableUser: [User] = []
  14. private var fillteredUser: [User] = []
  15. private var isSearchBarEmpty: Bool {
  16. return searchController.searchBar.text!.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
  17. }
  18. private var isFilltering: Bool {
  19. return searchController.isActive && !isSearchBarEmpty
  20. }
  21. public override func viewDidLoad() {
  22. super.viewDidLoad()
  23. navigationController?.navigationBar.topItem?.backButtonTitle = ""
  24. tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellCSInternal")
  25. searchController = UISearchController(searchResultsController: nil)
  26. searchController.delegate = self
  27. searchController.searchResultsUpdater = self
  28. searchController.searchBar.autocapitalizationType = .none
  29. searchController.searchBar.delegate = self
  30. searchController.obscuresBackgroundDuringPresentation = false
  31. searchController.searchBar.updateHeight(height: 36, radius: 18)
  32. searchController.searchBar.searchTextField.attributedPlaceholder = NSAttributedString(string: "Search".localized(), attributes: [NSAttributedString.Key.foregroundColor: UIColor.gray, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16)])
  33. definesPresentationContext = true
  34. navigationItem.searchController = searchController
  35. navigationItem.hidesSearchBarWhenScrolling = true
  36. if fromNotification {
  37. let imageButton = UIImageView(frame: CGRect(x: -16, y: 0, width: 20, height: 44))
  38. imageButton.image = UIImage(systemName: "chevron.backward", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular, scale: .default))?.withTintColor(.white)
  39. imageButton.contentMode = .left
  40. let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapExit))
  41. imageButton.isUserInteractionEnabled = true
  42. imageButton.addGestureRecognizer(tapGestureRecognizer)
  43. let leftItem = UIBarButtonItem(customView: imageButton)
  44. self.navigationItem.leftBarButtonItem = leftItem
  45. }
  46. if #available(iOS 15.0, *) {
  47. tableView.sectionHeaderTopPadding = 0
  48. }
  49. getData { users in
  50. self.availableUser.append(contentsOf: users)
  51. DispatchQueue.main.async {
  52. self.tableView.reloadData()
  53. }
  54. }
  55. }
  56. @objc func didTapExit() {
  57. self.dismiss(animated: true, completion: nil)
  58. }
  59. public override func viewDidAppear(_ animated: Bool) {
  60. self.navigationController?.navigationBar.topItem?.title = isSetCS ? "Set CS Account".localized() :"Set Internal Account".localized()
  61. self.navigationController?.navigationBar.setNeedsLayout()
  62. self.title = isSetCS ? "Set CS Account".localized() :"Set Internal Account".localized()
  63. }
  64. func getData(completion: @escaping ([User]) -> ()) {
  65. DispatchQueue.global().async {
  66. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  67. do {
  68. var r: [User] = []
  69. let query = "SELECT u.f_pin, u.first_name, u.last_name, u.image_id, u.user_type FROM BUDDY u where u.f_pin <> '\(User.getMyPin()!)' and u.official_account <> '1' and u.official_account <> '2' and u.official_account <> '3' order by 2 collate nocase asc"
  70. if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
  71. while cursorData.next() {
  72. let user = User(pin: cursorData.string(forColumnIndex: 0) ?? "",
  73. firstName: cursorData.string(forColumnIndex: 1) ?? "",
  74. lastName: cursorData.string(forColumnIndex: 2) ?? "",
  75. thumb: cursorData.string(forColumnIndex: 3) ?? "",
  76. userType: cursorData.string(forColumnIndex: 4) ?? "")
  77. if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
  78. continue
  79. }
  80. if r.first(where: {$0.pin == user.pin}) == nil {
  81. r.append(user)
  82. }
  83. }
  84. cursorData.close()
  85. }
  86. completion(r)
  87. } catch {
  88. rollback.pointee = true
  89. print("Access database error: \(error.localizedDescription)")
  90. }
  91. })
  92. }
  93. }
  94. private func setInternalCS(user: User) {
  95. let alert = LibAlertController(title: "", message: "Are you sure want to set".localized() + " \(user.fullName) " + (isSetCS ? "become CS Account?".localized() : "become Internal Account?".localized()), preferredStyle: .alert)
  96. alert.addAction(UIAlertAction(title: "No".localized(), style: .default, handler: nil))
  97. alert.addAction(UIAlertAction(title: "Yes".localized(), style: .default, handler: {(_) in
  98. Nexilis.showLoader()
  99. Database.shared.database?.inTransaction({ fmdb, rollback in
  100. do {
  101. if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.getManagementContactCenter(user_type: (self.isSetCS ? "1" : "3"), l_pin: user.pin), timeout: 5000) {
  102. if result.isOk() {
  103. DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
  104. let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
  105. imageView.tintColor = .white
  106. let banner = FloatingNotificationBanner(title: "Successfully changed".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
  107. banner.show()
  108. self.getData { users in
  109. self.availableUser.removeAll()
  110. self.availableUser.append(contentsOf: users)
  111. DispatchQueue.main.async {
  112. self.tableView.reloadData()
  113. }
  114. }
  115. Nexilis.hideLoader {}
  116. })
  117. } else {
  118. DispatchQueue.main.async {
  119. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  120. imageView.tintColor = .white
  121. let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
  122. banner.show()
  123. Nexilis.hideLoader {}
  124. }
  125. }
  126. } else {
  127. DispatchQueue.main.async {
  128. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  129. imageView.tintColor = .white
  130. let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
  131. banner.show()
  132. }
  133. }
  134. } catch {
  135. rollback.pointee = true
  136. print("Access database error: \(error.localizedDescription)")
  137. }
  138. })
  139. }))
  140. self.present(alert, animated: true, completion: nil)
  141. }
  142. private func unsetInternalCS(user: User) {
  143. let alert = LibAlertController(title: "", message: "Are you sure want to unset".localized() + " \(user.fullName) " + (isSetCS ? "from CS Account?".localized() : "from Internal Account?".localized()), preferredStyle: .alert)
  144. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: nil))
  145. alert.addAction(UIAlertAction(title: "Yes".localized(), style: .destructive, handler: {(_) in
  146. Nexilis.showLoader()
  147. Database.shared.database?.inTransaction({ fmdb, rollback in
  148. do {
  149. if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.getManagementContactCenter(user_type: (self.isSetCS ? "0" : "2"), l_pin: user.pin), timeout: 5000) {
  150. if result.isOk() {
  151. DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
  152. let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
  153. imageView.tintColor = .white
  154. let banner = FloatingNotificationBanner(title: "Successfully changed".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
  155. banner.show()
  156. self.getData { users in
  157. self.availableUser.removeAll()
  158. self.availableUser.append(contentsOf: users)
  159. DispatchQueue.main.async {
  160. self.tableView.reloadData()
  161. }
  162. }
  163. Nexilis.hideLoader {}
  164. })
  165. } else {
  166. DispatchQueue.main.async {
  167. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  168. imageView.tintColor = .white
  169. let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
  170. banner.show()
  171. Nexilis.hideLoader {}
  172. }
  173. }
  174. } else {
  175. DispatchQueue.main.async {
  176. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  177. imageView.tintColor = .white
  178. let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
  179. banner.show()
  180. }
  181. }
  182. } catch {
  183. rollback.pointee = true
  184. print("Access database error: \(error.localizedDescription)")
  185. }
  186. })
  187. }))
  188. self.present(alert, animated: true, completion: nil)
  189. }
  190. func filterContentForSearchText(_ searchText: String) {
  191. fillteredUser = availableUser.filter({ d in
  192. let name = "\(d.firstName) \(d.lastName)".trimmingCharacters(in: .whitespaces)
  193. return name.lowercased().contains(searchText.lowercased())
  194. })
  195. tableView.reloadData()
  196. }
  197. // MARK: - Table view data source
  198. public override func numberOfSections(in tableView: UITableView) -> Int {
  199. return 1
  200. }
  201. public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  202. return availableUser.count
  203. }
  204. public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  205. let cell = tableView.dequeueReusableCell(withIdentifier: "cellCSInternal", for: indexPath as IndexPath)
  206. var content = cell.defaultContentConfiguration()
  207. let user: User
  208. if isFilltering {
  209. user = fillteredUser[indexPath.row]
  210. } else {
  211. user = availableUser[indexPath.row]
  212. }
  213. content.imageProperties.maximumSize = CGSize(width: 40, height: 40)
  214. getImage(name: user.thumb, placeholderImage: UIImage(named: "Profile---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), isCircle: true, tableView: tableView, indexPath: indexPath) { result, isDownloaded, image in
  215. content.image = image
  216. if !result {
  217. content.imageProperties.tintColor = .mainColor
  218. }
  219. }
  220. if user.userType == "23" {
  221. content.attributedText = self.set(image: UIImage(named: "ic_internal", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " " + (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces), size: 15, y: -4)
  222. } else if user.userType == "24" {
  223. content.attributedText = self.set(image: UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " " + (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces), size: 15, y: -4)
  224. } else {
  225. content.text = (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces)
  226. }
  227. cell.contentConfiguration = content
  228. cell.accessoryType = user.isSelected ? .checkmark : .none
  229. return cell
  230. }
  231. public override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  232. tableView.deselectRow(at: indexPath, animated: true)
  233. if !CheckConnection.isConnectedToNetwork() {
  234. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  235. imageView.tintColor = .white
  236. let banner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
  237. banner.show()
  238. return
  239. }
  240. let user: User
  241. if isFilltering {
  242. user = fillteredUser[indexPath.row]
  243. } else {
  244. user = availableUser[indexPath.row]
  245. }
  246. if User.isCallCenter(userType: user.userType!) || (User.isInternal(userType: user.userType!) && !isSetCS) {
  247. unsetInternalCS(user: user)
  248. } else {
  249. if Utils.getDefaultCC() == "No" {
  250. let viewSetOfficer = SetOfficerBNI()
  251. viewSetOfficer.f_pin = user.pin
  252. viewSetOfficer.name = user.fullName
  253. viewSetOfficer.modalTransitionStyle = .crossDissolve
  254. viewSetOfficer.modalPresentationStyle = .custom
  255. self.present(viewSetOfficer, animated: true)
  256. } else {
  257. setInternalCS(user: user)
  258. }
  259. }
  260. }
  261. }
  262. extension SetInternalCSAccount: UISearchControllerDelegate, UISearchBarDelegate, UISearchResultsUpdating {
  263. public func updateSearchResults(for searchController: UISearchController) {
  264. filterContentForSearchText(searchController.searchBar.text!.trimmingCharacters(in: .whitespacesAndNewlines))
  265. }
  266. func set(image: UIImage, with text: String, size: CGFloat, y: CGFloat, colorText: UIColor = UIColor.black) -> NSAttributedString {
  267. let attachment = NSTextAttachment()
  268. attachment.image = image
  269. attachment.bounds = CGRect(x: 0, y: y, width: size, height: size)
  270. let attachmentStr = NSAttributedString(attachment: attachment)
  271. let mutableAttributedString = NSMutableAttributedString()
  272. mutableAttributedString.append(attachmentStr)
  273. let attributedStringColor = [NSAttributedString.Key.foregroundColor : colorText]
  274. let textString = NSAttributedString(string: text, attributes: attributedStringColor)
  275. mutableAttributedString.append(textString)
  276. return mutableAttributedString
  277. }
  278. }