2026-02-19 08:53:25 +07:00
< ? = $this -> extend ( 'layouts/main.php' ) ?>
< ? = $this -> section ( 'content' ) ?>
< div class = " page-wrapper " >
< div class = " container-fluid " >
< div class = " row page-titles " >
< div class = " col-md-5 align-self-center " >
< h4 class = " text-themecolor " > Certificates Maintenance Management </ h4 >
</ div >
</ div >
< div class = " row " >
< div class = " col-12 " >
< div class = " card " >
< div class = " card-body " >
< div class = " row mb-3 " >
< div class = " col-12 mb-3 " >
< div class = " input-group input-group-sm " >
< span class = " input-group-text " >< i class = " fas fa-search " ></ i ></ span >
< input type = " text " id = " searchInput " class = " form-control "
placeholder = " Search certificates by name, product, type, vendor, or dates... " >
</ div >
</ div >
< div class = " col-md-4 mb-2 " >
< select id = " statusFilter " class = " form-select form-select-sm " >
< option value = " " > All Status </ option >
< option value = " active " > Active </ option >
< option value = " expired " > Expired </ option >
< option value = " expiring " > Expiring Soon </ option >
2026-02-24 08:41:04 +07:00
< option value = " isval " > Need Validation </ option >
2026-02-19 08:53:25 +07:00
</ select >
</ div >
< div class = " col-md-4 mb-2 " >
< select id = " typeFilter " class = " form-select form-select-sm " >
< option value = " " > All Types </ option >
< option value = " tms " > TMS </ option >
< option value = " joko " > Jokoh </ option >
< option value = " boeki " > Tokyo Boeki </ option >
</ select >
</ div >
< div class = " col-md-4 mb-2 " >
< button onclick = " resetFilters() " class = " btn btn-secondary btn-sm w-100 " >
< i class = " fas fa-redo " ></ i > Reset Filters
</ button >
</ div >
</ div >
2026-02-24 08:41:04 +07:00
<!-- TABLE -->
< div class = " table-responsive " style = " width: 100%; " >
< table id = " certificatesTable " class = " table table-striped table-hover border " style = " width: 100%; " >
< thead class = " table-primary " >
< tr >
< th style = " width:20% " > Certificate Name </ th >
< th style = " width:20% " > Product / Equipment </ th >
< th style = " width:20% " > Activity Report </ th >
< th style = " width:10% " > Issue Date </ th >
< th style = " width:10% " > Expiry Date </ th >
< th style = " width:10% " > Status </ th >
< th class = " text-center " style = " width:10% " > Action </ th >
</ tr >
</ thead >
< tbody >
</ tbody >
</ table >
2026-02-19 08:53:25 +07:00
</ div >
</ div >
</ div >
</ div >
</ div >
</ div >
</ div >
2026-02-24 08:41:04 +07:00
<!-- Validate Modal -->
< div class = " modal fade " id = " validateModal " tabindex = " -1 " aria - labelledby = " validateModalLabel " aria - hidden = " true " >
2026-02-19 08:53:25 +07:00
< div class = " modal-dialog modal-xl modal-dialog-centered " >
< div class = " modal-content " >
2026-02-24 08:41:04 +07:00
< div class = " modal-header bg-warning text-dark " >
< h5 class = " modal-title " id = " validateModalLabel " >
< i class = " fa-solid fa-check-double " ></ i > & nbsp ; Validate Certificate
2026-02-19 08:53:25 +07:00
</ h5 >
2026-02-24 08:41:04 +07:00
< button type = " button " class = " btn-close " data - bs - dismiss = " modal "
2026-02-19 08:53:25 +07:00
aria - label = " Close " ></ button >
</ div >
2026-02-24 08:41:04 +07:00
< div class = " modal-body " >
< div class = " row " >
< div class = " col-md-6 mb-3 " >
< label class = " form-label fw-bold " > Certificate ID </ label >
< p id = " modalCertId " class = " form-control-plaintext " >-</ p >
2026-02-19 08:53:25 +07:00
</ div >
2026-02-24 08:41:04 +07:00
< div class = " col-md-6 mb-3 " >
< label class = " form-label fw-bold " > Certificate Name </ label >
< p id = " modalCertName " class = " form-control-plaintext " >-</ p >
2026-02-19 08:53:25 +07:00
</ div >
2026-02-24 08:41:04 +07:00
</ div >
< div class = " row " >
< div class = " col-md-6 mb-3 " >
< label class = " form-label fw-bold " > Product / Equipment </ label >
< p id = " modalProductName " class = " form-control-plaintext " >-</ p >
</ div >
< div class = " col-md-6 mb-3 " >
< label class = " form-label fw-bold " > Serial Number </ label >
< p id = " modalProductNumber " class = " form-control-plaintext " >-</ p >
</ div >
</ div >
< div class = " row " >
< div class = " col-md-6 mb-3 " >
< label class = " form-label fw-bold " > Issue Date </ label >
< p id = " modalIssueDate " class = " form-control-plaintext " >-</ p >
</ div >
< div class = " col-md-6 mb-3 " >
< label class = " form-label fw-bold " > Expiry Date </ label >
< p id = " modalExpiryDate " class = " form-control-plaintext " >-</ p >
</ div >
</ div >
< div class = " row " >
2026-02-25 09:35:41 +07:00
< div class = " col-md-6 mb-3 " >
2026-02-24 08:41:04 +07:00
< label class = " form-label fw-bold " > Vendor </ label >
< p id = " modalVendor " class = " form-control-plaintext " >-</ p >
</ div >
2026-02-25 09:35:41 +07:00
< div class = " col-md-6 mb-3 " >
< label class = " form-label fw-bold " > Activity Report </ label >
< p id = " modalExpiryDate " class = " form-control-plaintext " >
< a href = " javascript:void(0) " class = " activity-report-link text-decoration-none " data - certid = " ${ certid } " style = " color:#d43215b0; " > Act ID - Nama AR - Nama User < i class = " fa-solid fa-up-right-from-square " ></ i ></ a >
</ p >
</ div >
2026-02-24 08:41:04 +07:00
</ div >
< div class = " alert alert-warning " >
< i class = " fa-solid fa-info-circle " ></ i >
< strong > Validation Information :</ strong > Please review the certificate details above before validating . Once validated , the certificate status will change from " Need Validation " to " Active " .
</ div >
2026-02-19 08:53:25 +07:00
2026-02-24 08:41:04 +07:00
< div class = " row " >
< div class = " col-md-12 mb-3 " >
< label class = " form-label fw-bold " > Certificate Preview </ label >
< div class = " border rounded p-2 " style = " height: 500px; overflow: hidden; " >
< iframe id = " certificatePreview " src = " " style = " width: 100%; height: 100%; border: none; " ></ iframe >
2026-02-19 08:53:25 +07:00
</ div >
</ div >
</ div >
2026-02-24 08:41:04 +07:00
</ div >
< div class = " modal-footer " >
< button type = " button " class = " btn btn-secondary " data - bs - dismiss = " modal " >
< i class = " fa-solid fa-times " ></ i > Cancel
</ button >
< button type = " button " class = " btn btn-warning text-dark " id = " confirmValidateBtn " >
< i class = " fa-solid fa-check " ></ i > Validate Certificate
</ button >
</ div >
2026-02-19 08:53:25 +07:00
</ div >
</ div >
</ div >
< ? = $this -> endSection () ?>
2026-02-24 08:41:04 +07:00
< ? = $this -> section ( 'style' ) ?>
< style >
#certificatesTable {
width : 100 % ! important ;
}
#certificatesTable_wrapper {
width : 100 % ! important ;
}
</ style >
< ? = $this -> endSection () ?>
2026-02-19 08:53:25 +07:00
< ? = $this -> section ( 'script' ) ?>
< script >
2026-02-24 08:41:04 +07:00
$ ( function () {
let table = $ ( '#certificatesTable' ) . DataTable ({
order : [[ 5 , 'asc' ]],
pageLength : 25 ,
dom : '<"row"<"col-md-6"l>>rtip' ,
responsive : true ,
serverSide : false ,
autoWidth : false ,
ajax : function ( data , callback , settings ) {
fetch ( '<?= base_url(' certificates / api / getindexmaintenance ') ?>' )
. then ( response => response . json ())
. then ( result => {
callback ({
data : result . map ( cert => {
let certid = cert . certid || '' ;
let certname = cert . certname || '-' ;
let productname = cert . productname || '-' ;
let productnumber = cert . productnumber || '' ;
let issuedateRaw = cert . issuedate || '' ;
let expirydateRaw = cert . expirydate || '' ;
let vendor = cert . vendor || '-' ;
let isval = cert . isval || null ;
let issuedate = '-' ;
let expirydate = '-' ;
let statusBadge = '<span class="badge bg-warning text-dark">Need Validation</span>' ;
if ( isval != null ) {
if ( issuedateRaw && issuedateRaw !== '0000-00-00' ) {
issuedate = new Date ( issuedateRaw ) . toLocaleDateString ( 'en-US' , { month : 'short' , day : '2-digit' , year : 'numeric' });
}
if ( expirydateRaw && expirydateRaw !== '0000-00-00' ) {
expirydate = new Date ( expirydateRaw ) . toLocaleDateString ( 'en-US' , { month : 'short' , day : '2-digit' , year : 'numeric' });
let today = new Date ();
let expiryDate = new Date ( expirydateRaw );
let days = Math . ceil (( expiryDate - today ) / ( 1000 * 60 * 60 * 24 ));
if ( days < 0 ) {
statusBadge = '<span class="badge bg-danger">Expired</span>' ;
} else if ( days <= 30 ) {
statusBadge = '<span class="badge bg-info">Expiring Soon</span>' ;
} else {
statusBadge = '<span class="badge bg-success">Active</span>' ;
}
} else {
statusBadge = '<span class="badge bg-secondary">N/A</span>' ;
}
}
return [
`<strong>${certname}</strong><br><small class="text-muted">ID: ${certid}</small>` ,
`${productname}${productnumber ? '<br><small class="text-muted">SN: ' + productnumber + '</small>' : ''}` ,
`<a href="javascript:void(0)" class="activity-report-link text-decoration-none" data-certid="${certid}" style="color:#d43215b0;">Act ID - Nama AR - Nama User <i class="fa-solid fa-up-right-from-square"></i></a>` ,
issuedate ,
expirydate ,
statusBadge ,
isval == null
2026-02-25 09:35:41 +07:00
? `<div class="text-center"><button type="button" class="btn btn-warning text-dark btn-validate" data-certid="${certid}" data-certname="${certname}" data-productname="${productname}" data-productnumber="${productnumber}" data-issuedate="${issuedate}" data-expirydate="${expirydate}" data-vendor="${vendor}"><i class="fa-solid fa-check-double"></i></button></div>`
: `<div class="text-center"><button type="button" class="btn btn-success btn-view" data-certid="${certid}"><i class="fa-regular fa-file-pdf"></i></button></div>`
2026-02-24 08:41:04 +07:00
];
})
});
})
. catch ( error => {
console . error ( 'Error fetching data:' , error );
callback ({ data : [] });
});
},
columnDefs : [{
targets : 5 ,
render : function ( data , type ) {
if ( type === 'sort' ) {
if ( data . includes ( 'Need Validation' )) return 1 ;
if ( data . includes ( 'Expired' )) return 2 ;
if ( data . includes ( 'Expiring Soon' )) return 3 ;
if ( data . includes ( 'Active' )) return 4 ;
return 5 ;
}
return data ;
}
}]
});
$ ( '#certificatesTable_filter' ) . hide ();
// Search
$ ( '#searchInput' ) . on ( 'keyup' , function () {
table . search ( this . value ) . draw ();
});
2026-02-25 09:35:41 +07:00
// Type filter using DataTables column filter
$ ( '#typeFilter' ) . on ( 'change' , function () {
let type = $ ( this ) . val ();
// Filter by type column (index 1 - Certificate Name contains type info)
if ( type === '' ) {
table . column ( 1 ) . search ( '' ) . draw ();
} else {
// Capitalize first letter for search
let typeText = type . charAt ( 0 ) . toUpperCase () + type . slice ( 1 );
table . column ( 1 ) . search ( typeText ) . draw ();
}
});
2026-02-24 08:41:04 +07:00
// Status filter
$ ( '#statusFilter' ) . on ( 'change' , function () {
let map = {
active : 'Active' ,
expired : 'Expired' ,
expiring : 'Expiring Soon' ,
isval : 'Need Validation'
};
table . column ( 5 ) . search ( map [ this . value ] || '' ) . draw ();
});
// Reset
window . resetFilters = function () {
$ ( '#searchInput, #statusFilter' ) . val ( '' );
table . search ( '' ) . columns () . search ( '' ) . order ([ 5 , 'asc' ]) . draw ();
};
// View PDF
$ ( document ) . on ( 'click' , '.btn-view' , function () {
let certid = $ ( this ) . data ( 'certid' );
window . open ( '<?= base_url(' certificates / maintenance / show / ') ?>' + certid , '_blank' );
});
// Activity report
$ ( document ) . on ( 'click' , '.activity-report-link' , function () {
let certid = $ ( this ) . data ( 'certid' );
window . open (
'<?= base_url(' certificates / maintenance / activity / ') ?>' + certid ,
'_blank' ,
'width=1200,height=800,scrollbars=yes,resizable=yes'
);
});
// Open modal
$ ( document ) . on ( 'click' , '.btn-validate' , function () {
let btn = $ ( this );
$ ( '#modalCertId' ) . text ( btn . data ( 'certid' ));
$ ( '#modalCertName' ) . text ( btn . data ( 'certname' ));
$ ( '#modalProductName' ) . text ( btn . data ( 'productname' ));
$ ( '#modalProductNumber' ) . text ( btn . data ( 'productnumber' ));
$ ( '#modalIssueDate' ) . text ( btn . data ( 'issuedate' ));
$ ( '#modalExpiryDate' ) . text ( btn . data ( 'expirydate' ));
$ ( '#modalVendor' ) . text ( btn . data ( 'vendor' ));
$ ( '#confirmValidateBtn' ) . data ( 'certid' , btn . data ( 'certid' ));
$ ( '#certificatePreview' ) . attr (
'src' ,
'<?= base_url(' certificates / maintenance / show / ') ?>' + btn . data ( 'certid' )
);
$ ( '#validateModal' ) . modal ( 'show' );
});
// Confirm validate
$ ( '#confirmValidateBtn' ) . on ( 'click' , function () {
let certid = $ ( this ) . data ( 'certid' );
let certificateType = 'maintenance' ;
if ( ! confirm ( 'Are you sure?' )) return ;
$ . post (
2026-02-25 09:35:41 +07:00
'<?= base_url(' certificates / api / validateCertificate ') ?>' ,
{ certid , certificateType },
2026-02-24 08:41:04 +07:00
function ( response ) {
if ( response . success ) {
$ ( '#validateModal' ) . modal ( 'hide' );
2026-02-25 09:35:41 +07:00
alert ( response . message );
// Generate and save PDF after successful validation
$ . post (
'<?= base_url(' certificates / api / generatepdf ') ?>' ,
{ certid , certificateType },
function ( pdfResponse ) {
if ( pdfResponse . success ) {
alert ( 'PDF generated and saved successfully!' );
location . reload ();
} else {
alert ( 'Validation successful but PDF generation failed: ' + ( pdfResponse . message || 'Unknown error' ));
location . reload ();
}
},
'json'
) . fail ( function () {
alert ( 'Validation successful but failed to generate PDF' );
location . reload ();
});
2026-02-24 08:41:04 +07:00
} else {
alert ( response . message || 'Validation failed' );
}
}, 'json'
) . fail ( function () {
$ ( '#validateModal' ) . modal ( 'hide' );
alert ( 'Server error.' );
});
});
2026-02-19 08:53:25 +07:00
2026-02-24 08:41:04 +07:00
});
2026-02-19 08:53:25 +07:00
</ script >
< ? = $this -> endSection () ?>