Bladeren bron

menu sertifikat

Hendi 3 jaren geleden
bovenliggende
commit
23f73f1e5e

+ 68 - 0
Sirani.xcodeproj/project.pbxproj

@@ -7,6 +7,17 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		0485C69C2A4193A90072B449 /* LabelVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0485C69B2A4193A90072B449 /* LabelVC.swift */; };
+		0485C69E2A4193D20072B449 /* LabelPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0485C69D2A4193D20072B449 /* LabelPresenter.swift */; };
+		0485C6A02A4193E80072B449 /* SearchLabelVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0485C69F2A4193E80072B449 /* SearchLabelVC.swift */; };
+		0485C6A22A4194030072B449 /* LabelCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0485C6A12A4194030072B449 /* LabelCell.swift */; };
+		0485C6A42A41941B0072B449 /* LabelViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0485C6A32A41941B0072B449 /* LabelViewDelegate.swift */; };
+		0485C6A62A4195B30072B449 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0485C6A52A4195B30072B449 /* Label.swift */; };
+		04CAAAD12A4007B9005DBD04 /* SertifikatNewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04CAAAD02A4007B9005DBD04 /* SertifikatNewCell.swift */; };
+		04CAAAD42A4042C4005DBD04 /* SearchSertifikatNewVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04CAAAD32A4042C4005DBD04 /* SearchSertifikatNewVC.swift */; };
+		04D0FD7E2A31B3EF00DC89D1 /* SertifikatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04D0FD7D2A31B3EF00DC89D1 /* SertifikatViewController.swift */; };
+		04D0FD832A32E42D00DC89D1 /* SertifikatPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04D0FD822A32E42D00DC89D1 /* SertifikatPresenter.swift */; };
+		04D0FD852A33027E00DC89D1 /* SertifikatViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04D0FD842A33027E00DC89D1 /* SertifikatViewDelegate.swift */; };
 		1765ADEEAA576B3B80836335 /* Pods_Sirani.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63B2C265FB9236074BCFE50D /* Pods_Sirani.framework */; };
 		D8164C2B255FD62C00A3AE48 /* FaqContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8164C2A255FD62C00A3AE48 /* FaqContent.swift */; };
 		D8854A08255F90D500D581DF /* FaqCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8854A07255F90D500D581DF /* FaqCategory.swift */; };
@@ -217,6 +228,17 @@
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
+		0485C69B2A4193A90072B449 /* LabelVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelVC.swift; sourceTree = "<group>"; };
+		0485C69D2A4193D20072B449 /* LabelPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelPresenter.swift; sourceTree = "<group>"; };
+		0485C69F2A4193E80072B449 /* SearchLabelVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchLabelVC.swift; sourceTree = "<group>"; };
+		0485C6A12A4194030072B449 /* LabelCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelCell.swift; sourceTree = "<group>"; };
+		0485C6A32A41941B0072B449 /* LabelViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelViewDelegate.swift; sourceTree = "<group>"; };
+		0485C6A52A4195B30072B449 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
+		04CAAAD02A4007B9005DBD04 /* SertifikatNewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SertifikatNewCell.swift; sourceTree = "<group>"; };
+		04CAAAD32A4042C4005DBD04 /* SearchSertifikatNewVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSertifikatNewVC.swift; sourceTree = "<group>"; };
+		04D0FD7D2A31B3EF00DC89D1 /* SertifikatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SertifikatViewController.swift; sourceTree = "<group>"; };
+		04D0FD822A32E42D00DC89D1 /* SertifikatPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SertifikatPresenter.swift; sourceTree = "<group>"; };
+		04D0FD842A33027E00DC89D1 /* SertifikatViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SertifikatViewDelegate.swift; sourceTree = "<group>"; };
 		63B2C265FB9236074BCFE50D /* Pods_Sirani.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Sirani.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		B35682048376C184CFE92DBC /* Pods-Sirani.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sirani.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sirani/Pods-Sirani.debug.xcconfig"; sourceTree = "<group>"; };
 		C6195E138986840DC40227B6 /* Pods-Sirani.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sirani.release.xcconfig"; path = "Pods/Target Support Files/Pods-Sirani/Pods-Sirani.release.xcconfig"; sourceTree = "<group>"; };
@@ -447,6 +469,34 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		0485C69A2A41936E0072B449 /* Label */ = {
+			isa = PBXGroup;
+			children = (
+				0485C69B2A4193A90072B449 /* LabelVC.swift */,
+				0485C6A32A41941B0072B449 /* LabelViewDelegate.swift */,
+				0485C69D2A4193D20072B449 /* LabelPresenter.swift */,
+				0485C6A12A4194030072B449 /* LabelCell.swift */,
+				0485C69F2A4193E80072B449 /* SearchLabelVC.swift */,
+			);
+			path = Label;
+			sourceTree = "<group>";
+		};
+		04CAAAD22A404294005DBD04 /* Search */ = {
+			isa = PBXGroup;
+			children = (
+				04CAAAD32A4042C4005DBD04 /* SearchSertifikatNewVC.swift */,
+			);
+			path = Search;
+			sourceTree = "<group>";
+		};
+		04D0FD812A32E38000DC89D1 /* SertifikatPrivate */ = {
+			isa = PBXGroup;
+			children = (
+				04D0FD7D2A31B3EF00DC89D1 /* SertifikatViewController.swift */,
+			);
+			path = SertifikatPrivate;
+			sourceTree = "<group>";
+		};
 		1FD17C9EA3F553643CC5DF6D /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
@@ -471,6 +521,11 @@
 		FC06F76A226E0C2E00B574E4 /* Sertifikat */ = {
 			isa = PBXGroup;
 			children = (
+				04CAAAD22A404294005DBD04 /* Search */,
+				04D0FD822A32E42D00DC89D1 /* SertifikatPresenter.swift */,
+				04D0FD842A33027E00DC89D1 /* SertifikatViewDelegate.swift */,
+				04CAAAD02A4007B9005DBD04 /* SertifikatNewCell.swift */,
+				04D0FD812A32E38000DC89D1 /* SertifikatPrivate */,
 				FC06F76B226E0C3C00B574E4 /* SertifikatSementara */,
 				FC06F778226E208F00B574E4 /* SertifikatBerlaku */,
 				FC6A5D822272992E0096664E /* SertifikatTIdakBerlaku */,
@@ -819,6 +874,7 @@
 				FCD5F1DB255CD9B7008B42F7 /* NotificationDetail.swift */,
 				D8854A07255F90D500D581DF /* FaqCategory.swift */,
 				D8164C2A255FD62C00A3AE48 /* FaqContent.swift */,
+				0485C6A52A4195B30072B449 /* Label.swift */,
 			);
 			path = Model;
 			sourceTree = "<group>";
@@ -826,6 +882,7 @@
 		FCADBBE62247114800F0B4C6 /* View */ = {
 			isa = PBXGroup;
 			children = (
+				0485C69A2A41936E0072B449 /* Label */,
 				FC3A3270224BDF3800AD6393 /* Home */,
 				FCB5EA232254A0B8003EFEE4 /* ScanQR */,
 				FC3A3271224BDF5600AD6393 /* Help */,
@@ -1297,6 +1354,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				FCF7BAEE2263136B00532DC2 /* OdsSp2Print.swift in Sources */,
+				04D0FD7E2A31B3EF00DC89D1 /* SertifikatViewController.swift in Sources */,
 				FCE9CA0F226C3BAA0023F6A6 /* AplikasiDitolakVC.swift in Sources */,
 				FCBAA3FA2274158C008AC73C /* DaftarRhuCell.swift in Sources */,
 				FCBAA3D92273F978008AC73C /* DaftarRhu.swift in Sources */,
@@ -1307,6 +1365,7 @@
 				FC857927226ABAB300A9C27E /* OdsDaftarRhuPresenter.swift in Sources */,
 				FC67D374224FCD7300E456FB /* DaftarSertifikatCell.swift in Sources */,
 				FCEE081C255F995D006DFDF5 /* FaqCategoryCell.swift in Sources */,
+				0485C6A42A41941B0072B449 /* LabelViewDelegate.swift in Sources */,
 				FCADBBEE2247127700F0B4C6 /* FaqVC.swift in Sources */,
 				FC6A5D812271DC8F0096664E /* SearchNewsVC.swift in Sources */,
 				FCF7BB0B22636F0100532DC2 /* SertifikatSudahUploadPresenter.swift in Sources */,
@@ -1327,6 +1386,7 @@
 				FC3A3275224BE26300AD6393 /* HomeViewDelegate.swift in Sources */,
 				FC56CC8625601F75008B87F4 /* FaqDetail.swift in Sources */,
 				FC74C510226B1E9A00E55F29 /* SearchOdsSp2AfterVC.swift in Sources */,
+				04D0FD852A33027E00DC89D1 /* SertifikatViewDelegate.swift in Sources */,
 				FCF7BB0522636E7E00532DC2 /* SertifikatSudahUploadVC.swift in Sources */,
 				FCD5F1D6255CD820008B42F7 /* NotificationDetailVC.swift in Sources */,
 				FCF7BAE42262FCAF00532DC2 /* OdsSp2OtorasiVC.swift in Sources */,
@@ -1354,9 +1414,11 @@
 				FC74C505226B1DE500E55F29 /* OdsSp2After.swift in Sources */,
 				FCEE51E7225E57DB000AE43B /* ResultQrCode.swift in Sources */,
 				FCEE51E5225E40FC000AE43B /* QRScannerVC.swift in Sources */,
+				0485C6A22A4194030072B449 /* LabelCell.swift in Sources */,
 				FCE76AE22267528B00DAD3CC /* SearchOdsAplikasiEntryVC.swift in Sources */,
 				FCADBBF02247128700F0B4C6 /* LoginVC.swift in Sources */,
 				FCD23BCD2261FE730090B157 /* AplikasiEntryCell.swift in Sources */,
+				04D0FD832A32E42D00DC89D1 /* SertifikatPresenter.swift in Sources */,
 				FCECB8192254F55300A8F5A8 /* BalaiUji.swift in Sources */,
 				FC74C50C226B1E7300E55F29 /* OdsSp2AfterPresenter.swift in Sources */,
 				FCEE596D2256C10800071B89 /* LokasiBalaiUjiVC.swift in Sources */,
@@ -1365,8 +1427,10 @@
 				FC56AD6C22585B9700D0EAE0 /* HomeNewsCell.swift in Sources */,
 				FCBAA3E02273FA15008AC73C /* Sp2SertifikatViewDelegate.swift in Sources */,
 				FC74C4FF226AF89F00E55F29 /* OdsSp2BeforeViewDelegate.swift in Sources */,
+				04CAAAD42A4042C4005DBD04 /* SearchSertifikatNewVC.swift in Sources */,
 				FCF7BB0922636EF600532DC2 /* SertifikatSudahUploadViewDelegate.swift in Sources */,
 				FC8568ED2250F7410012F927 /* TarifSertifikatPresenter.swift in Sources */,
+				0485C69C2A4193A90072B449 /* LabelVC.swift in Sources */,
 				FC74C512226B49C200E55F29 /* SearchSertifikatBelumUploadVC.swift in Sources */,
 				FCF399E5224D0D2200A73D5B /* MenuCell.swift in Sources */,
 				FCD5F1E2255D0310008B42F7 /* NotificationDetailPresenter.swift in Sources */,
@@ -1399,6 +1463,7 @@
 				FCF468F2225A2E1D00B9227A /* UserState.swift in Sources */,
 				FCD23BC92261EC950090B157 /* OdsAplikasiEntryViewDelegate.swift in Sources */,
 				FCF7BAF92263324200532DC2 /* SurveyList.swift in Sources */,
+				0485C69E2A4193D20072B449 /* LabelPresenter.swift in Sources */,
 				FC6A5D8E227299F40096664E /* SertifikatTidakBerlaku.swift in Sources */,
 				FCE76AE42267650D00DAD3CC /* SearchOdsSp2OtorisasiVC.swift in Sources */,
 				FC6B67972268973A0042656E /* SearchOdsSp2BaruVC.swift in Sources */,
@@ -1415,6 +1480,8 @@
 				FCBAA3D52273F77E008AC73C /* Sp2Sertifikat.swift in Sources */,
 				FCADBBEC2247126100F0B4C6 /* HelpVC.swift in Sources */,
 				FCEE51F6225FF675000AE43B /* HasilSurveyPresenter.swift in Sources */,
+				0485C6A02A4193E80072B449 /* SearchLabelVC.swift in Sources */,
+				04CAAAD12A4007B9005DBD04 /* SertifikatNewCell.swift in Sources */,
 				FC19C27D255AE3DA004E0912 /* NotificationCell.swift in Sources */,
 				FC67D368224F94E000E456FB /* ViewExtensions.swift in Sources */,
 				FCF468EC225A1AC700B9227A /* User.swift in Sources */,
@@ -1432,6 +1499,7 @@
 				FC8568E72250EF330012F927 /* TarifSertifikatVC.swift in Sources */,
 				FCFCEBC022660F5D0057DEC6 /* SertifikatBelumUpload.swift in Sources */,
 				FCF7BAEC2262FCE400532DC2 /* OdsSp2Otorasi.swift in Sources */,
+				0485C6A62A4195B30072B449 /* Label.swift in Sources */,
 				FCE9CA26226CCFB90023F6A6 /* AplikasiStatus.swift in Sources */,
 				FCBAA3D1227327A5008AC73C /* SertifikatDaftarPencabutanVC.swift in Sources */,
 				D8164C2B255FD62C00A3AE48 /* FaqContent.swift in Sources */,

BIN
Sirani.xcworkspace/xcuserdata/mac.xcuserdatad/UserInterfaceState.xcuserstate


+ 32 - 7
Sirani/ApiServices/SiraniApiServices.swift

@@ -42,13 +42,6 @@ class SiraniApiServices {
     
     // News -> Home, NewsVC
     func postToGetNews(cursor: Int, prev: Int, jenis: String, columns: String, keyword: String) -> DataRequest {
-        print("CEK 123")
-        print("cursor \(cursor)")
-        print("prev \(prev)")
-        print("jenis \(jenis)")
-        print("columns \(columns)")
-        print("keyword \(keyword)")
-
         let headers: HTTPHeaders = ["Accept" : "Application/json; charset=utf-8"]
         let body: Parameters = [
             "limit" : String(cursor),
@@ -672,4 +665,36 @@ class SiraniApiServices {
         return AF.request(url, method: .get, encoding: URLEncoding.default, headers: headers)
     }
     
+//    ------------------------------------------- NEW FUNCTION -------------------------------------------
+    
+    func postToGetSertifikatPublic(user_id: Int, cust_id: Int, role_id: String, jenis: String, columns: String, limit: Int, page: Int, search: String) -> DataRequest {
+        let headers: HTTPHeaders = ["Accept" : "Application/json; charset=utf-8"]
+        let body: Parameters = [
+            "user_id" : String(user_id),
+            "cust_id" : String(cust_id),
+            "role_id" : role_id,
+            "jenis" : jenis,
+            "columns" : columns,
+            "limit" : String(limit),
+            "page" : String(page),
+            "search" : search
+        ]
+        
+        return AF.request(METHOD_GET_SERTIFIKAT_PUBLIC, method: .post, parameters: body, encoding: URLEncoding.default, headers: headers)
+    }
+    
+    func postToGetSertifikatPrivate(user_id: Int, cust_id: Int, role_id: String, status: String, limit: Int, page: Int, search: String) -> DataRequest {
+        let headers: HTTPHeaders = ["Accept" : "Application/json; charset=utf-8"]
+        let body: Parameters = [
+            "user_id" : String(user_id),
+            "cust_id" : String(cust_id),
+            "role_id" : role_id,
+            "status" : status,
+            "limit" : String(limit),
+            "page" : String(page),
+            "search" : search
+        ]
+        
+        return AF.request(METHOD_GET_SERTIFIKAT_PRIVATE, method: .post, parameters: body, encoding: URLEncoding.default, headers: headers)
+    }
 }

+ 18 - 11
Sirani/ApiServices/UriConstants.swift

@@ -14,16 +14,9 @@ let HOST_API = "https://sertifikasi.postel.go.id/esertifikasi_mobile/"
 let API = "api/"
 let VERSION = "v1/"
 
-// BASE URL NEW
-let HOST_API_NEW = "https://sertifikasi.postel.go.id/sirani_sertifikasi/"
-let SIMPONI = "simponi/"
-
 // AUTH
 let METHOD_LOGIN = "\(HOST_API)\(API)\(VERSION)Auth_login"
 
-// AUTH NEW
-let METHOD_LOGIN_NEW = "\(HOST_API_NEW)\(API)\(VERSION)\(SIMPONI)Auth_login"
-
 // HOME
 let METHOD_GET_TOTAL_UNREAD_NOTIF = "\(HOST_API)\(API)\(VERSION)NotifikasiRealtime"
 let METHOD_GET_TOTAL_NOTIFIKASI = "\(HOST_API)\(API)\(VERSION)Notifikasi"
@@ -33,10 +26,6 @@ let METHOD_GET_NEWS_DETAIL = "\(HOST_API)\(API)\(VERSION)Flashnewsdetail"
 let METHOD_GET_FAQ_CATEGORY = "\(HOST_API)\(API)\(VERSION)Faq/Category"
 let METHOD_GET_FAQ_CONTENT = "\(HOST_API)\(API)\(VERSION)Faq/Content"
 
-//HOME NEW
-let METHOD_GET_NEWS_NEW = "\(HOST_API_NEW)\(API)\(VERSION)Flashnews"
-let METHOD_GET_NEWS_DETAIL_NEW = "\(HOST_API_NEW)\(API)\(VERSION)Flashnewsdetail"
-
 // NOTIFICATIONS
 let METHOD_GET_PUSH_NOTIF_LIST = "\(HOST_API)\(API)\(VERSION)NotifikasiRealtime/list"
 let METHOD_GET_PUSH_NOTIF_DETAIL = "\(HOST_API)\(API)\(VERSION)NotifikasiRealtime/detail"
@@ -99,3 +88,21 @@ let METHOD_DOWNLOAD_USER_MANUAL = "\(HOST_URL)uploads/file/user_manual.pdf"
 let METHOD_DOWNLOAD_USER_MANUAL_SDOC = "\(HOST_URL)uploads/file/user_manual_sdoc.pdf"
 let METHOD_DOWNLOAD_H2H_MANDIRI = "\(HOST_URL)uploads/file/h2h_mandiri.pdf"
 let METHOD_DOWNLOAD_H2H_BNI = "\(HOST_URL)uploads/file/h2h_bni.pdf"
+
+// ------------------------------- NEW URI -------------------------------------- //
+
+// BASE URL NEW
+let HOST_API_NEW = "https://sertifikasi.postel.go.id/sirani_sertifikasi/"
+let SIMPONI = "simponi/"
+
+// AUTH NEW
+let METHOD_LOGIN_NEW = "\(HOST_API_NEW)\(API)\(VERSION)Auth_login"
+
+// HOME NEW
+let METHOD_GET_NEWS_NEW = "\(HOST_API_NEW)\(API)\(VERSION)Flashnews"
+let METHOD_GET_NEWS_DETAIL_NEW = "\(HOST_API_NEW)\(API)\(VERSION)Flashnewsdetail"
+
+// SERTIFIKAT
+let METHOD_GET_SERTIFIKAT_PRIVATE = "\(HOST_API_NEW)\(API)\(VERSION)SertifikatPrivate"
+let METHOD_GET_SERTIFIKAT_PUBLIC = "\(HOST_API_NEW)\(API)\(VERSION)SertifikatPublic"
+

File diff suppressed because it is too large
+ 889 - 58
Sirani/Base.lproj/Main.storyboard


+ 9 - 1
Sirani/Model/CertificateData.swift

@@ -20,8 +20,12 @@ struct CertificateData {
     private(set) public var models: String
     private(set) public var plg_id: Int
     private(set) public var apl_id: Int
+    private(set) public var negara: String
+    private(set) public var model: String
+    private(set) public var merk: String
+    private(set) public var berlaku: String
     
-    init (nomor: String, cust_name: String, eqp_name: String, lic_id: Int, brand: String, lic_date: String, lic_no: String, exp_date: String, models: String, plg_id: Int, apl_id: Int) {
+    init (nomor: String, cust_name: String, eqp_name: String, lic_id: Int, brand: String, lic_date: String, lic_no: String, exp_date: String, models: String, plg_id: Int, apl_id: Int, negara: String, model: String, merk: String, berlaku: String) {
         self.nomor = nomor
         self.cust_name = cust_name
         self.eqp_name = eqp_name
@@ -33,5 +37,9 @@ struct CertificateData {
         self.models = models
         self.plg_id = plg_id
         self.apl_id = apl_id
+        self.merk = merk
+        self.model = model
+        self.negara = negara
+        self.berlaku = berlaku
     }
 }

+ 6 - 0
Sirani/Utils/Constants.swift

@@ -17,4 +17,10 @@ class Constants {
     public let KEPALA_SEKSI_ROLE_ID = "7"
     public let KEPALA_SUB_DIREKTORAT_ROLE_ID = "11"
     public let DIREKTUR_ROLE_ID = "8"
+    
+    
+    // ALERT CONNECTION
+    public let ALERT_NO_CONNECTION_TITLE = "Informasi"
+    public let ALERT_NO_CONNECTION_MSG = "Sepertinya Anda sedang tidak tersambung pada koneksi internet"
+    public let ALERT_NO_CONNECTION_YESS = "OK"
 }

+ 13 - 1
Sirani/Utils/MenuListData.swift

@@ -18,7 +18,19 @@ class MenuListData {
     private let KEPALA_SUB_DIREKTORAT_ROLE_ID = Constants.instance.KEPALA_SUB_DIREKTORAT_ROLE_ID
     private let DIREKTUR_ROLE_ID = Constants.instance.DIREKTUR_ROLE_ID
     
-    // MENU UTAMA
+    // MENU UTAMA NEW
+    let menuUtamaCellNewId = "menuUtamaNewCellId"
+    let moreMenuUtamaNewCellId = "moreMenuUtamaNewCellId"
+    private let menuUtamaNewItems = [
+        MenuItem(segueId: "SertifikatSegueId", icon: "menu-utama-daftar-sertifikat.png", name: "Sertifikat", totalNotif: 0),
+        MenuItem(segueId: "TarifSertifikatSegueId", icon: "menu-utama-tarif-sertifikat.png", name: "Aplikasi", totalNotif: 0),
+        MenuItem(segueId: "InformasiSertifikasiSegueId", icon: "menu-utama-informasi-sertifikat.png", name: "Label", totalNotif: 0)
+    ]
+    func getMenuUtamaNewData(userRoleId: String) -> [MenuItem] {
+        return menuUtamaNewItems
+    }
+    
+    // MENU UTAMA OLD
     let menuUtamaCellId = "menuUtamaCellId"
     let moreMenuUtamaCellId = "moreMenuUtamaCellId"
     private let menuUtamaItems = [

+ 5 - 1
Sirani/View/DaftarSertifikat/Index/DaftarSertifikatPresenter.swift

@@ -48,7 +48,11 @@ class DaftarSertifikatPresenter {
                                     exp_date: item["exp_date"].stringValue,
                                     models: item["models"].stringValue,
                                     plg_id: item["plg_id"].intValue,
-                                    apl_id: item["apl_id"].intValue
+                                    apl_id: item["apl_id"].intValue,
+                                    negara: item["negara"].stringValue,
+                                    model: item["model"].stringValue,
+                                    merk: item["merk"].stringValue,
+                                    berlaku: item["berlaku"].stringValue
                                 )
                                 certificates.append(certificateData)
                             }

+ 50 - 3
Sirani/View/Home/HomeVC.swift

@@ -30,6 +30,12 @@ class HomeVC: UIViewController {
     @IBOutlet weak var homeNewsTV: UITableView!
     @IBOutlet weak var moreMenuUtamaCV: UICollectionView!
     
+    @IBOutlet weak var moreMenuNewTitleLayout: UIView!
+    @IBOutlet weak var moreMenuNewNotif: UIView!
+    @IBOutlet weak var lblMoreMenuUtamaNewNotif: UILabel!
+    @IBOutlet weak var moreMenuUtamaNewCV: UICollectionView!
+    @IBOutlet weak var marginMoreMenuUtamaNew: UIView!
+    
     @IBOutlet weak var moreMenuAplikasiODSTitleLayout: UIView!
     @IBOutlet weak var moreMenuOdsNotif: UIView!
     @IBOutlet weak var lblMoreMenuAplikasiODSNotif: UILabel!
@@ -87,6 +93,7 @@ class HomeVC: UIViewController {
     // data list
     private var listNews = [News]()
     private let listMenuUtama = MenuListData.instance.getMenuUtamaData()
+    private var listMenuUtamaNew = [MenuItem]()
     private var listMenuAplikasiODS = [MenuItem]()
     private var listMenuFotoLabel = [MenuItem]()
     private var listMenuAplikasi = [MenuItem]()
@@ -169,6 +176,7 @@ class HomeVC: UIViewController {
         
         userRoleId = UserState.instance.getRoleId()
         if !userRoleId.isEmpty {
+            setMoreMenuUtamaNew(userRoleId: userRoleId)
             setMoreMenuAplikasiODS(userRoleId: userRoleId)
             setMoreMenuFotoLabel(userRoleId: userRoleId)
             setMoreMenuAplikasi(userRoleId: userRoleId)
@@ -201,6 +209,7 @@ class HomeVC: UIViewController {
 //
             if !userRoleId.isEmpty {
                 clearMoreMenu()
+                setMoreMenuUtamaNew(userRoleId: userRoleId)
                 setMoreMenuAplikasiODS(userRoleId: userRoleId)
                 setMoreMenuFotoLabel(userRoleId: userRoleId)
                 setMoreMenuAplikasi(userRoleId: userRoleId)
@@ -574,6 +583,29 @@ class HomeVC: UIViewController {
         }
     }
     
+    private func setMoreMenuUtamaNew(userRoleId: String) {
+        // notif
+        moreMenuNewNotif.layer.cornerRadius = 5
+        // menus
+        let flowLayout = UICollectionViewFlowLayout()
+        flowLayout.sectionInset = .init(top: 0, left: 0, bottom: 0, right: 0)
+        flowLayout.itemSize = CGSize(width: menuItemSize, height: menuItemSize)
+        flowLayout.minimumInteritemSpacing = 0
+        flowLayout.minimumLineSpacing = 0
+        moreMenuUtamaNewCV.collectionViewLayout = flowLayout
+        moreMenuUtamaNewCV.delegate = self
+        moreMenuUtamaNewCV.dataSource = self
+        moreMenuUtamaNewCV.register(MenuCell.self, forCellWithReuseIdentifier: MenuListData.instance.menuUtamaCellNewId)
+        
+        listMenuUtamaNew = MenuListData.instance.getMenuUtamaNewData(userRoleId: userRoleId)
+        if listMenuUtamaNew.count > 0 {
+            moreMenuUtamaNewCV.reloadData()
+            moreMenuNewTitleLayout.show()
+            moreMenuUtamaNewCV.show()
+            marginMoreMenuUtamaNew.show()
+        }
+    }
+    
     // IB Actions
     @IBAction func unwindToHome(segue: UIStoryboardSegue) {}
     
@@ -856,7 +888,10 @@ extension HomeVC: HomeViewDelegate {
 // CollectionView functions
 extension HomeVC : UICollectionViewDelegate, UICollectionViewDataSource {
     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        if collectionView == self.mainMenuCV {
+        if collectionView == self.moreMenuUtamaNewCV {
+            return listMenuUtamaNew.count
+        }
+        else if collectionView == self.mainMenuCV {
             return listMenuUtama.count
         } else if collectionView == self.moreMenuUtamaCV {
             return listMenuUtama.count
@@ -882,7 +917,17 @@ extension HomeVC : UICollectionViewDelegate, UICollectionViewDataSource {
     }
     
     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-        if collectionView == self.mainMenuCV {
+        
+        if collectionView == self.moreMenuUtamaNewCV {
+            if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MenuListData.instance.menuUtamaCellNewId, for: indexPath) as? MenuCell {
+                let menu = listMenuUtamaNew[indexPath.row]
+                cell.updateViews(menu: menu)
+                return cell
+            } else {
+                return MenuCell()
+            }
+            
+        } else if collectionView == self.mainMenuCV {
             if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MenuListData.instance.menuUtamaCellId, for: indexPath) as? MenuCell {
                 let menu = listMenuUtama[indexPath.row]
                 cell.updateViews(menu: menu)
@@ -969,7 +1014,9 @@ extension HomeVC : UICollectionViewDelegate, UICollectionViewDataSource {
     
     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
         var segueId = ""
-        if collectionView == self.mainMenuCV {
+        if collectionView == self.moreMenuUtamaNewCV {
+            segueId = listMenuUtamaNew[indexPath.row].segueId
+        } else if collectionView == self.mainMenuCV {
             segueId = listMenuUtama[indexPath.row].segueId
         } else if collectionView == self.moreMenuUtamaCV {
             segueId = listMenuUtama[indexPath.row].segueId

+ 9 - 0
Sirani/View/Label/SearchLabelVC.swift

@@ -0,0 +1,9 @@
+//
+//  SearchLabelVC.swift
+//  Sirani
+//
+//  Created by Hendi on 20/06/23.
+//  Copyright © 2023 PT. Mitra Sinerji Teknoindo. All rights reserved.
+//
+
+import Foundation

+ 11 - 2
Sirani/View/ScanQR/Scanner/QRScannerVC.swift

@@ -68,6 +68,7 @@ class QRScannerVC: UIViewController {
     // variables
     private var loading = false
     var kode : Int?
+    var isSertifikatNew = false
     
     // View Lifecycles
     override var preferredStatusBarStyle: UIStatusBarStyle {
@@ -193,7 +194,11 @@ class QRScannerVC: UIViewController {
     @IBAction func onBtnBackTap(_ sender: Any) {
         if(kode != nil)
         {
-            performSegue(withIdentifier: "unwindToDaftarSertifikatSegueId", sender: self)
+            if(isSertifikatNew){
+                performSegue(withIdentifier: "unwindToSertifikatSegueId", sender: self)
+            }else{
+                performSegue(withIdentifier: "unwindToDaftarSertifikatSegueId", sender: self)
+            }
         }
         else
         {
@@ -204,7 +209,11 @@ class QRScannerVC: UIViewController {
     @IBAction func onBtnCloseScannerTap(_ sender: Any) {
         if(kode != nil)
         {
-            performSegue(withIdentifier: "unwindToDaftarSertifikatSegueId", sender: self)
+            if(isSertifikatNew){
+                performSegue(withIdentifier: "unwindToSertifikatSegueId", sender: self)
+            }else{
+                performSegue(withIdentifier: "unwindToDaftarSertifikatSegueId", sender: self)
+            }
         }
         else
         {

+ 156 - 0
Sirani/View/Sertifikat/Search/SearchSertifikatNewVC.swift

@@ -0,0 +1,156 @@
+//
+//  SearchSertifikatNewVC.swift
+//  Sirani
+//
+//  Created by Hendi on 19/06/23.
+//  Copyright © 2023 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?
+    
+    // constants vallue data
+    private let jenisSertifikatOptionItems = [
+        OptionItem(label: "Semua", value: ""),
+        OptionItem(label: "Berlaku", value: "sertifkat_berlaku"),
+        OptionItem(label: "Tidak Berlaku", value: "sertifikat_tidak_berlaku"),
+        OptionItem(label: "Revisi", value: "sertifikat_revisi")
+    ]
+    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"
+    
+    // View Lifecycles
+    override var preferredStatusBarStyle: UIStatusBarStyle {
+        return .lightContent
+    }
+    
+    override func viewWillAppear(_ animated: Bool) {
+        btnStatusOptions.layer.masksToBounds = false
+        btnStatusOptions.layer.shadowColor = #colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)
+        btnStatusOptions.layer.shadowOpacity = 0.5
+        btnStatusOptions.layer.shadowOffset = CGSize(width: 1, height: 1)
+        btnStatusOptions.layer.shadowRadius = 1
+        status = jenisSertifikatOptionItems[0].value as! String
+        jenisLabel = jenisSertifikatOptionItems[0].label
+        btnStatusOptions.setTitle(jenisLabel, for: .normal)
+        
+        hideOptions()
+        optionsLayoutTV.bringSubviewToFront(optionsBg)
+        let onOptionsBgTapped = UITapGestureRecognizer(target: self, action: #selector(hideOptions))
+        optionsBg.addGestureRecognizer(onOptionsBgTapped)
+    }
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        
+        optionsLayoutTV.delegate = self
+        optionsLayoutTV.dataSource = self
+        optionsLayoutTV.tableFooterView = UIView()
+    }
+    
+    @IBAction func onInputSearchKeyTap(_ sender: Any) {
+        view.endEditing(true)
+    }
+    
+    @IBAction func unwindToSertifikatNew(_ sender: Any) {
+        if optionsShown {
+            hideOptions()
+        } else {
+            performSegue(withIdentifier: "unwindSearchToSertifikatSegueId", sender: self)
+        }
+    }
+        
+    @IBAction func onJenisSertifikatOptionsTapped(_ sender: Any) {
+        selectedOptions = OPTION_JENIS_SERTIFIKAT_ID
+        selectedOptionItems.removeAll()
+        selectedOptionItems += jenisSertifikatOptionItems
+        optionsLayoutTV.reloadData()
+        showOptions()
+    }
+    
+    @IBAction func onResetTapped(_ sender: Any) {
+        search = ""
+        status = ""
+        jenisLabel = "Semua"
+        
+        inputSearch.text = ""
+        btnStatusOptions.setTitle(jenisLabel, for: .normal)
+    }
+    
+    @IBAction func onSearchTapped(_ sender: Any) {
+        if let searchText = inputSearch.getText() {
+            search = searchText
+        }
+        print("TEST : ")
+        print("SEARCH \(search)")
+        print("STATUS \(status)")
+        print("JENIS \(jenisLabel)")
+        
+        self.delegate?.onSearch(search: search, status: status, jenisLabel: jenisLabel)
+        performSegue(withIdentifier: "unwindSearchToSertifikatSegueId", 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)
+        }
+        
+        hideOptions()
+    }
+}
+

+ 112 - 0
Sirani/View/Sertifikat/SertifikatNewCell.swift

@@ -0,0 +1,112 @@
+//
+//  SertifikatNewCell.swift
+//  Sirani
+//
+//  Created by Hendi on 19/06/23.
+//  Copyright © 2023 PT. Mitra Sinerji Teknoindo. All rights reserved.
+//
+
+import UIKit
+import MaterialComponents.MaterialCards
+
+protocol SertifikatNewCellDelegate: NSObjectProtocol  {
+    func openSertifikatDetail(data : CertificateData?)
+}
+
+class SertifikatNewCell: UITableViewCell {
+    
+    @IBOutlet weak var card: MDCCard!
+    @IBOutlet weak var lblNomor: UILabel!
+    @IBOutlet weak var lblPemohon: UILabel!
+    @IBOutlet weak var lblPerangkat: UILabel!
+    @IBOutlet weak var lblMerk: UILabel!
+    @IBOutlet weak var lblModel: UILabel!
+    @IBOutlet weak var lblBrand: UILabel!
+    @IBOutlet weak var lblBerlakuDate: UILabel!
+    @IBOutlet weak var lblBerakhirDate: UILabel!
+    @IBOutlet weak var lblStatus: UILabel!
+
+    var cellDelegate: SertifikatNewCellDelegate?
+    var dataSertifikat: CertificateData?
+    
+    func updateViews(certificateData: CertificateData) {
+        card.isInteractable = true
+        
+        let gesture = UITapGestureRecognizer(target: self, action:  #selector(self.onItemTap))
+        card.addGestureRecognizer(gesture)
+        
+        lblNomor.text = certificateData.nomor
+        lblPemohon.text = certificateData.cust_name
+        lblPerangkat.text = certificateData.eqp_name
+        lblMerk.text = certificateData.merk
+        lblModel.text = certificateData.model
+        
+        var brand = ""
+        if certificateData.brand != "null" {
+            brand = certificateData.brand
+        }
+        lblBrand.text = brand
+        
+        var expDate = ""
+        
+        if (certificateData.exp_date == "null" || certificateData.exp_date.isEmpty) {
+            expDate = ""
+        } else {
+            let inputFormatter = DateFormatter()
+            inputFormatter.dateFormat = "yyyy-MM-dd"
+            let expDateString = String(certificateData.exp_date.prefix(10))
+            
+            if let output = inputFormatter.date(from: expDateString) {
+                let outputFormatter = DateFormatter()
+                outputFormatter.dateFormat = "dd MMM yyyy"
+                expDate = outputFormatter.string(from: output)
+            }
+        }
+        
+        lblBerakhirDate.text = expDate
+        
+        var licDate = ""
+        if (certificateData.lic_date == "null" || certificateData.lic_date.isEmpty) {
+            licDate = ""
+        } else {
+            let inputFormatter = DateFormatter()
+            inputFormatter.dateFormat = "yyyy-MM-dd"
+            let expDateString = String(certificateData.lic_date.prefix(10))
+            
+            if let output = inputFormatter.date(from: expDateString) {
+                let outputFormatter = DateFormatter()
+                outputFormatter.dateFormat = "dd MMM yyyy"
+                licDate = outputFormatter.string(from: output)
+            }
+        }
+        lblBerlakuDate.text = licDate
+        
+        var status = ""
+
+        lblStatus?.layer.cornerRadius = 6
+        lblStatus?.layer.masksToBounds = true
+        
+        switch certificateData.berlaku {
+            case "0":
+                status = "Tidak Berlaku"
+                lblStatus.backgroundColor = UIColor.red
+            case "1":
+                status = "Berlaku"
+                lblStatus.backgroundColor = UIColor.green
+            case "3":
+                status = "Revisi"
+                lblStatus.backgroundColor = UIColor.orange
+            default:
+                lblStatus.backgroundColor = UIColor.white
+        }
+        
+        lblStatus.text = status
+        
+        self.dataSertifikat = certificateData
+    }
+    
+    @objc func onItemTap(sender : UITapGestureRecognizer) {
+        cellDelegate?.openSertifikatDetail(data: dataSertifikat)
+    }
+
+}

+ 95 - 0
Sirani/View/Sertifikat/SertifikatPresenter.swift

@@ -0,0 +1,95 @@
+//
+//  SertifikatPresenter.swift
+//  Sirani
+//
+//  Created by Hendi on 09/06/23.
+//  Copyright © 2023 PT. Mitra Sinerji Teknoindo. All rights reserved.
+//
+
+import Foundation
+import SwiftyJSON
+
+class SertifikatPresenter {
+    private let siraniApiServices: SiraniApiServices
+    weak private var view: SertifikatViewDelegate?
+    
+    init(siraniApiServices: SiraniApiServices) {
+        self.siraniApiServices = siraniApiServices
+    }
+    
+    func attachView(view: SertifikatViewDelegate?) {
+        self.view = view
+    }
+    
+    func detachView() {
+        self.view = nil
+    }
+    
+    func loadPrivateCertificatesData(user_id: Int, cust_id: Int, role_id: String, status: String, limit: Int, page: Int, search: String) {
+        self.view?.hideNoDataLayout()
+        self.view?.showLoading()
+        
+        var certificates = [CertificateData]()
+        siraniApiServices.postToGetSertifikatPrivate(user_id: user_id, cust_id: cust_id, role_id: role_id, status: status, limit: limit, page: page, search: search).responseJSON { response in
+            if response.error == nil {
+                guard let data = response.data else { return }
+                if let json = try? JSON(data: data) {
+                    if let data = json["data"].array {
+                        if data.count > 0 {
+                            for item in data {
+                                let certificateData = CertificateData(
+                                    nomor: item["nomor"].stringValue,
+                                    cust_name: item["cust_name"].stringValue,
+                                    eqp_name: item["eqp_name"].stringValue,
+                                    lic_id: item["lic_id"].intValue,
+                                    brand: item["brand"].stringValue,
+                                    lic_date: item["lic_date"].stringValue,
+                                    lic_no: item["lic_no"].stringValue,
+                                    exp_date: item["exp_date"].stringValue,
+                                    models: item["models"].stringValue,
+                                    plg_id: item["plg_id"].intValue,
+                                    apl_id: item["apl_id"].intValue,
+                                    negara: item["negara"].stringValue,
+                                    model: item["model"].stringValue,
+                                    merk: item["merk"].stringValue,
+                                    berlaku: item["berlaku"].stringValue
+                                )
+                                certificates.append(certificateData)
+                            }
+                            
+                            self.setCertificates(certificates: certificates)
+                        } else {
+                            if page > 1 {
+                                self.setCertificates(certificates: certificates)
+                            } else {
+                                self.showNoData()
+                            }
+                        }
+                    } else {
+                        self.showNoData()
+                    }
+                } else {
+                    self.showNoData()
+                }
+            } else {
+                self.showNoData()
+            }
+        }
+    }
+    
+    // other functions
+    private func setCertificates(certificates: [CertificateData]) {
+        self.view?.setCertificates(certificates: certificates)
+        DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) {
+            self.view?.hideLoading()
+        }
+    }
+    
+    private func showNoData() {
+        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
+            self.view?.showNoDataLayout()
+            self.view?.hideLoading()
+        }
+    }
+}
+

+ 236 - 0
Sirani/View/Sertifikat/SertifikatPrivate/SertifikatViewController.swift

@@ -0,0 +1,236 @@
+//
+//  SertifikatViewController.swift
+//  Sirani
+//
+//  Created by Hendi on 08/06/23.
+//  Copyright © 2023 PT. Mitra Sinerji Teknoindo. All rights reserved.
+//
+
+import UIKit
+
+class SertifikatViewController: UIViewController {
+
+    // Outlets & Views
+    @IBOutlet weak var certificatesTV: UITableView!
+    @IBOutlet weak var progressLoading: UIView!
+    @IBOutlet weak var layoutNoData: UIView!
+    @IBOutlet weak var labelSubtitle: UILabel!
+    
+    // View Id
+    private let sertifikatPrivateCellId = "SertifikatPrivateCell"
+    
+    // Segue Id
+    private let sertifikatNewSearchSegueId = "searchSertifikatNewSegueId"
+    private let searchSegueId = "searchSertifikatNewSegueId"
+    
+    // Initialize
+    private var presenter: SertifikatPresenter!
+    private var certificates: [CertificateData] =  [CertificateData]()
+
+    // Request Params
+    private var limit: Int = 5
+    private var page: Int = 1
+    private var status: String = "sertifikat_all"
+    private var search: String = ""
+    
+    // Others
+    private var loading = false
+    private var lastDataLoadedEmpty = false
+    private var loadMore = false
+    private var kode: Int?
+    private var isSertifikatNew: Bool = true
+    private var userId: Int = 0
+    private var custId: Int = 0
+    private var userRoleId = ""
+    
+    // View Lifecycles
+    override var preferredStatusBarStyle: UIStatusBarStyle {
+        return .lightContent
+    }
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        
+        certificatesTV.delegate = self
+        certificatesTV.dataSource = self
+        
+        presenter = SertifikatPresenter(siraniApiServices: SiraniApiServices())
+        presenter.attachView(view: self)
+        loadCertificateData()
+    }
+    
+    override func viewWillAppear(_ animated: Bool) {
+        presenter.attachView(view: self)
+        
+        userRoleId = UserState.instance.getRoleId()
+        userId = UserState.instance.getUserId()
+        custId = UserState.instance.getCustId()
+        print("INFO USER")
+        print("userRoleId \(userRoleId)")
+        print("userId : \(userId)")
+        print("custId : \(custId)")
+
+    }
+    
+    override func viewDidDisappear(_ animated: Bool) {
+        presenter.detachView()
+    }
+    
+    // private functions
+    private func loadCertificateData() {
+        if !loading && !lastDataLoadedEmpty {
+            if ConnectionHelper.isConnectedToNetwork() {
+                presenter.loadPrivateCertificatesData(user_id: userId, cust_id: custId, role_id: userRoleId, status: status, limit: limit, page: page, search: search)
+            } else {
+                showNoConnection()
+            }
+        }
+    }
+    
+    // MARK: - Private Function
+    // Actions
+    
+    @IBAction func onBtnSearchTap(_ sender: Any) {
+        performSegue(withIdentifier: searchSegueId, sender: self)
+    }
+    
+    @IBAction func unwindToSertifikat(segue: UIStoryboardSegue) {}
+
+}
+
+// View Delegate Protocols
+extension SertifikatViewController: SertifikatViewDelegate {
+    func showNoConnection() {
+        let alertNoConnection = UIAlertController(
+            title: Constants.instance.ALERT_NO_CONNECTION_TITLE,
+            message: Constants.instance.ALERT_NO_CONNECTION_MSG,
+            preferredStyle: .alert
+        )
+        alertNoConnection.addAction(
+            UIAlertAction(title: Constants.instance.ALERT_NO_CONNECTION_YESS, style: .default, handler: nil)
+        )
+        self.present(alertNoConnection, animated: true, completion: nil)
+    }
+    
+    func showLoading() {
+        loading = true
+        progressLoading.show()
+    }
+    
+    func hideLoading() {
+        loading = false
+        progressLoading.hide()
+    }
+    
+    func showNoDataLayout() {
+        if page == 1 {
+            layoutNoData.show()
+        }
+    }
+    
+    func hideNoDataLayout() {
+        layoutNoData.hide()
+    }
+    
+    func setCertificates(certificates: [CertificateData]) {
+        if page == 1 {
+            layoutNoData.hide()
+        }
+        
+        if certificates.count > 0 {
+            
+            for certificate in certificates {
+                self.certificates.append(certificate)
+                certificatesTV.beginUpdates()
+                certificatesTV.insertRows(
+                    at: [IndexPath(row: self.certificates.count-1, section: 0)],
+                    with: .none
+                )
+                certificatesTV.endUpdates()
+            }
+            
+            page += 1
+            loadMore = true
+        } else {
+            lastDataLoadedEmpty = true
+            loadMore = false
+        }
+    }
+}
+
+// UITableController Protocols
+extension SertifikatViewController: UITableViewDelegate, UITableViewDataSource, UIScrollViewDelegate, SertifikatNewCellDelegate {
+
+    func openSertifikatDetail(data: CertificateData?) {
+        self.kode = data?.apl_id
+        performSegue(withIdentifier: "sertifikatNewDetailSegueId", sender: self)
+    }
+    
+    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return certificates.count
+    }
+    
+    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        if tableView == certificatesTV {
+            if let cell = tableView.dequeueReusableCell(withIdentifier: sertifikatPrivateCellId, for: indexPath) as? SertifikatNewCell {
+                
+                cell.cellDelegate = self
+                cell.card.tag = indexPath.row
+                let certificate = certificates[indexPath.row]
+                cell.updateViews(certificateData: certificate)
+                
+                return cell
+            } else {
+                return SertifikatNewCell()
+            }
+        } else {
+            return SertifikatNewCell()
+        }
+    }
+    
+    func scrollViewDidScroll(_ scrollView: UIScrollView) {
+        let threshold = -5
+        let contentOffset = scrollView.contentOffset.y
+        let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height;
+        
+        if loadMore && !loading && (Int(maximumOffset - contentOffset) <= threshold) {
+            loadCertificateData()
+        }
+    }
+    
+}
+
+// SearchSertifikatNewModal Delegate Protocols
+extension SertifikatViewController: SearchSertifikatNewDelegate {
+    func onSearch(search: String, status: String, jenisLabel: String) {
+        presenter.attachView(view: self)
+
+        loadMore = false
+        loading = false
+        lastDataLoadedEmpty = false
+
+        self.limit = 5
+        self.page = 1
+        self.search = search
+        self.status = status
+
+        certificates.removeAll()
+        certificatesTV.reloadData()
+        labelSubtitle.text = jenisLabel
+
+        loadCertificateData()
+    }
+
+    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
+        if segue.identifier == sertifikatNewSearchSegueId {
+            let destinationVC: SearchSertifikatNewVC = segue.destination as! SearchSertifikatNewVC
+            destinationVC.delegate = self
+        }
+
+        if let detailSertifikatVC = segue.destination as? QRScannerVC {
+            detailSertifikatVC.kode = kode
+            detailSertifikatVC.isSertifikatNew = isSertifikatNew
+        }
+    }
+
+}

+ 18 - 0
Sirani/View/Sertifikat/SertifikatViewDelegate.swift

@@ -0,0 +1,18 @@
+//
+//  SertifikatViewDelegate.swift
+//  Sirani
+//
+//  Created by Hendi on 09/06/23.
+//  Copyright © 2023 PT. Mitra Sinerji Teknoindo. All rights reserved.
+//
+
+import Foundation
+
+protocol SertifikatViewDelegate: NSObjectProtocol {
+    func showNoConnection()
+    func showLoading()
+    func hideLoading()
+    func showNoDataLayout()
+    func hideNoDataLayout()
+    func setCertificates(certificates: [CertificateData])
+}