Update Fitur Instalasi

This commit is contained in:
mikael-zakaria 2026-03-10 08:43:43 +07:00
parent d7bd75f5a5
commit 8078b32bbd
8 changed files with 431 additions and 1547 deletions

View File

@ -211,13 +211,13 @@ $routes->group('certificates', function($routes) {
// Untuk Index Tiap Menu
$routes->get('maintenance', 'Certificates::maintenanceIndex'); // OK
// $routes->get('installation', 'Certificates::installationIndex'); // OK
$routes->get('installation', 'Certificates::installationIndex'); // OK
// $routes->get('training', 'Certificates::trainingIndex'); // OK
// $routes->get('calibration', 'Certificates::calibrateIndex'); // OK
// Untuk Get API
$routes->get('api/getindexmaintenance', 'Certificates::getDataIndexMaintenance'); // OK
// $routes->get('api/getindexinstallation', 'Certificates::getDataIndexInstallation'); // OK
$routes->get('api/getindexinstallation', 'Certificates::getDataIndexInstallation'); // OK
// $routes->get('api/getindextraining', 'Certificates::getDataIndexTraining'); // OK
// $routes->get('api/getindexcalibrate', 'Certificates::getDataIndexCalibrate');

View File

@ -1666,6 +1666,7 @@ class Activities extends Controller {
return view('invtrans_index', $data);
}
// Untuk CRUD Sertifikat Maintenance
public function createCertificateMaintenance ($actid, $issuedDate, $userid_owner) {
$db = \Config\Database::connect();
@ -1789,4 +1790,6 @@ class Activities extends Controller {
$certificateModel->where('actid', $actid)->delete();
}
}

View File

@ -15,62 +15,54 @@ class Certificates extends BaseController {
protected array $data;
// Untuk Sertifikat Instalasi [1]
// Untuk Sertifikat Instalasi (BAI) [1]
public function installationIndex() { // Index
return view('certificate_installation_index');
}
public function getDataIndexInstallation() { // Untuk API Get Data
// $actid = $this->request->getVar('actid'); Siapa Tahu Buat
$userPosId = session()->get('userposid');
$userId = session()->get('userid');
$certificates = [
[
'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11914',
'certname' => 'Jokoh Calibration Certificate',
'productname' => 'Jokoh',
'productnumber' => 'SN-2024-001',
'issuedate' => '2024-01-15',
'expirydate' => '2025-01-15',
'vendor' => 'Summit Calibration Lab',
'isval' => null
],
[
'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11915',
'certname' => 'Electrical Safety Test',
'productname' => 'GE Healthcare VIVID',
'productnumber' => 'GE-VIV-Q992',
'issuedate' => '2024-06-12',
'expirydate' => '2026-03-01',
'vendor' => 'Pramita Medika Service',
'isval' => '2026-03-01'
],
[
'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11915',
'certname' => 'Electrical Safety Test',
'productname' => 'GE Healthcare VIVID',
'productnumber' => 'GE-VIV-Q992',
'issuedate' => '2024-06-12',
'expirydate' => '2026-10-01',
'vendor' => 'Pramita Medika Service',
'isval' => '2026-09-01'
],
[
'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11915',
'certname' => 'Electrical Safety Test',
'productname' => 'GE Healthcare VIVID',
'productnumber' => 'GE-VIV-Q992',
'issuedate' => '2024-06-12',
'expirydate' => '2026-01-01',
'vendor' => 'Pramita Medika Service',
'isval' => '2026-09-01'
],
];
$certificateModel = new CertificateModel();
// If no actid, return all certificates
if (empty($certificates)) {
return $this->response->setJSON(null);
// 1. Mulai Query Builder
$builder = $certificateModel->select('
certificates.cert_id,
certificates.cert_number,
certificates.cert_name,
certificates.cert_type,
certificates.actid,
certificates.issued_date,
certificates.expired_date,
certificates.status,
certificates.user_validation_at,
certificates.spv_validation_at,
certificates.manager_validation_at,
activities.subject as activity_subject,
CONCAT(users.firstname, " ", users.lastname) as fullname
')
->join('activities', 'activities.actid = certificates.actid', 'left')
->join('users', 'users.userid = certificates.user_id', 'left')
->where('certificates.cert_type', 'BAI');
// 2. Filter berdasarkan Role
if (in_array($userPosId, [1, 3, 5])) { // Manager & IT: Tidak perlu filter tambahan (lihat semua)
} else if ($userPosId == 2) { // SPV: Melihat data user yang "reportto"-nya adalah ID supervisor ini
$builder->where('users.reportto', $userId);
} else if ($userPosId == 4) { // TSOIVD: Hanya melihat data milik sendiri
$builder->where('certificates.user_id', $userId);
} else {// Role lain: Tidak diberi akses
return $this->response->setJSON([]);
}
return $this->response->setJSON($certificates);
// 3. Eksekusi Query
$allData = $builder->findAll();
if (empty($allData)) {
return $this->response->setJSON([]); // Kembalikan array kosong agar frontend tidak error
}
return $this->response->setJSON($allData);
}
public function createinstallationPreview($certid = null) { // Untuk Preview Sertifikat
//Melakukan search data dari database
@ -126,7 +118,8 @@ class Certificates extends BaseController {
CONCAT(users.firstname, " ", users.lastname) as fullname
')
->join('activities', 'activities.actid = certificates.actid', 'left')
->join('users', 'users.userid = certificates.user_id', 'left');
->join('users', 'users.userid = certificates.user_id', 'left')
->where('certificates.cert_type', 'MC');;
// 2. Filter berdasarkan Role
if (in_array($userPosId, [1, 3, 5])) { // Manager & IT: Tidak perlu filter tambahan (lihat semua)
@ -268,133 +261,133 @@ class Certificates extends BaseController {
// Untuk Sertifikat Training [3]
public function trainingIndex() {
return view('certificate_training_index');
}
public function getDataIndexTraining() {
// $actid = $this->request->getVar('actid');
// public function trainingIndex() {
// return view('certificate_training_index');
// }
// public function getDataIndexTraining() {
// // $actid = $this->request->getVar('actid');
// Sample data - replace with actual database query
$certificates = [
[
'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919',
'certname' => 'Jokoh Calibration Certificate',
'productname' => 'Jokoh',
'productnumber' => 'SN-2024-001',
'issuedate' => '2024-01-15',
'expirydate' => '2025-01-15',
'vendor' => 'Summit Calibration Lab',
'isval' => null
],
[
'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919',
'certname' => 'Electrical Safety Test',
'productname' => 'GE Healthcare VIVID',
'productnumber' => 'GE-VIV-Q992',
'issuedate' => '2024-06-12',
'expirydate' => '2026-10-01',
'vendor' => 'Pramita Medika Service',
'isval' => '2026-03-01'
]
];
// // Sample data - replace with actual database query
// $certificates = [
// [
// 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919',
// 'certname' => 'Jokoh Calibration Certificate',
// 'productname' => 'Jokoh',
// 'productnumber' => 'SN-2024-001',
// 'issuedate' => '2024-01-15',
// 'expirydate' => '2025-01-15',
// 'vendor' => 'Summit Calibration Lab',
// 'isval' => null
// ],
// [
// 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919',
// 'certname' => 'Electrical Safety Test',
// 'productname' => 'GE Healthcare VIVID',
// 'productnumber' => 'GE-VIV-Q992',
// 'issuedate' => '2024-06-12',
// 'expirydate' => '2026-10-01',
// 'vendor' => 'Pramita Medika Service',
// 'isval' => '2026-03-01'
// ]
// ];
// If no actid, return all certificates
if (empty($certificates)) {
return $this->response->setJSON(null);
}
// // If no actid, return all certificates
// if (empty($certificates)) {
// return $this->response->setJSON(null);
// }
return $this->response->setJSON($certificates);
}
public function createTrainingPreview($certid = null) { // Untuk Preview Sertifikat
//Melakukan search data dari database
// return $this->response->setJSON($certificates);
// }
// public function createTrainingPreview($certid = null) { // Untuk Preview Sertifikat
// //Melakukan search data dari database
if (!$certid) {
return $this->response->setStatusCode(400)->setJSON(['error' => 'Certificate ID is required']);
}
// if (!$certid) {
// return $this->response->setStatusCode(400)->setJSON(['error' => 'Certificate ID is required']);
// }
// Get certificate data Berdasarkan certid
$certificate = [
'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919',
'certname' => 'Jokoh Calibration Certificate',
'productname' => 'Jokoh',
'productnumber' => 'SN-2024-001',
'issuedate' => '2024-01-15',
'expirydate' => '2025-01-15',
'vendor' => 'Summit Calibration Lab',
'isval' => null
];
// // Get certificate data Berdasarkan certid
// $certificate = [
// 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919',
// 'certname' => 'Jokoh Calibration Certificate',
// 'productname' => 'Jokoh',
// 'productnumber' => 'SN-2024-001',
// 'issuedate' => '2024-01-15',
// 'expirydate' => '2025-01-15',
// 'vendor' => 'Summit Calibration Lab',
// 'isval' => null
// ];
if (empty($certificate)) { // JIka Tidak Ada
return $this->response->setStatusCode(404)->setJSON(['error' => 'Maintenance certificate not found']);
}
// if (empty($certificate)) { // JIka Tidak Ada
// return $this->response->setStatusCode(404)->setJSON(['error' => 'Maintenance certificate not found']);
// }
return $this->previewPdf($certificate, 'training'); // Preview PDF
}
// return $this->previewPdf($certificate, 'training'); // Preview PDF
// }
// Untuk Sertifikat Calibrate [4]
public function calibrateIndex() {
return view('certificate_calibrate_index');
}
public function getDataIndexCalibrate() {
// $actid = $this->request->getVar('actid');
// public function calibrateIndex() {
// return view('certificate_calibrate_index');
// }
// public function getDataIndexCalibrate() {
// // $actid = $this->request->getVar('actid');
// Sample data - replace with actual database query
$certificates = [
[
'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919',
'certname' => 'Jokoh Calibration Certificate',
'productname' => 'Jokoh',
'productnumber' => 'SN-2024-001',
'issuedate' => '2024-01-15',
'expirydate' => '2025-01-15',
'vendor' => 'Summit Calibration Lab',
'isval' => null
],
[
'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919',
'certname' => 'Electrical Safety Test',
'productname' => 'GE Healthcare VIVID',
'productnumber' => 'GE-VIV-Q992',
'issuedate' => '2024-06-12',
'expirydate' => '2026-10-01',
'vendor' => 'Pramita Medika Service',
'isval' => '2026-03-01'
]
];
// // Sample data - replace with actual database query
// $certificates = [
// [
// 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919',
// 'certname' => 'Jokoh Calibration Certificate',
// 'productname' => 'Jokoh',
// 'productnumber' => 'SN-2024-001',
// 'issuedate' => '2024-01-15',
// 'expirydate' => '2025-01-15',
// 'vendor' => 'Summit Calibration Lab',
// 'isval' => null
// ],
// [
// 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919',
// 'certname' => 'Electrical Safety Test',
// 'productname' => 'GE Healthcare VIVID',
// 'productnumber' => 'GE-VIV-Q992',
// 'issuedate' => '2024-06-12',
// 'expirydate' => '2026-10-01',
// 'vendor' => 'Pramita Medika Service',
// 'isval' => '2026-03-01'
// ]
// ];
// If no actid, return all certificates
if (empty($certificates)) {
return $this->response->setJSON(null);
}
// // If no actid, return all certificates
// if (empty($certificates)) {
// return $this->response->setJSON(null);
// }
return $this->response->setJSON($certificates);
}
public function createCalibratePreview($certid = null) { // Untuk Preview Sertifikat
//Melakukan search data dari database
// return $this->response->setJSON($certificates);
// }
// public function createCalibratePreview($certid = null) { // Untuk Preview Sertifikat
// //Melakukan search data dari database
if (!$certid) {
return $this->response->setStatusCode(400)->setJSON(['error' => 'Certificate ID is required']);
}
// if (!$certid) {
// return $this->response->setStatusCode(400)->setJSON(['error' => 'Certificate ID is required']);
// }
// Get certificate data Berdasarkan certid
$certificate = [
'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919',
'certname' => 'Jokoh Calibration Certificate',
'productname' => 'Jokoh',
'productnumber' => 'SN-2024-001',
'issuedate' => '2024-01-15',
'expirydate' => '2025-01-15',
'vendor' => 'Summit Calibration Lab',
'isval' => null
];
// // Get certificate data Berdasarkan certid
// $certificate = [
// 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919',
// 'certname' => 'Jokoh Calibration Certificate',
// 'productname' => 'Jokoh',
// 'productnumber' => 'SN-2024-001',
// 'issuedate' => '2024-01-15',
// 'expirydate' => '2025-01-15',
// 'vendor' => 'Summit Calibration Lab',
// 'isval' => null
// ];
if (empty($certificate)) { // JIka Tidak Ada
return $this->response->setStatusCode(404)->setJSON(['error' => 'Maintenance certificate not found']);
}
// if (empty($certificate)) { // JIka Tidak Ada
// return $this->response->setStatusCode(404)->setJSON(['error' => 'Maintenance certificate not found']);
// }
return $this->previewPdf($certificate, 'calibrate', 'tms24i'); // Preview PDF
}
// return $this->previewPdf($certificate, 'calibrate', 'tms24i'); // Preview PDF
// }
// Helper Function Preview dan Validate

View File

@ -223,7 +223,7 @@ if(isset($data)) {
Calibration Certificate
</label>
</div>
</div>
</div> -->
<div class="col-md-6 mb-2">
<div class="form-check">
@ -232,7 +232,7 @@ if(isset($data)) {
Installation Certificate
</label>
</div>
</div> -->
</div>
<div class="col-md-6 mb-2">
<div class="form-check">
@ -250,9 +250,9 @@ if(isset($data)) {
Berita Acara Instalasi
</label>
</div>
</div>
</div> -->
<div class="col-md-6 mb-2">
<!-- <div class="col-md-6 mb-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="training" value="1" id="training" <?= in_array('UTC', $cert_types) ? 'checked' : '' ?>>
<label class="form-check-label" for="training">
@ -637,10 +637,11 @@ if(isset($data)) {
<div class="row mb-3">
<div class="col-12 col-lg-5">
<div class="form-group">
<label for="trainingname" class="form-label">Nama</label>
<input type='text' class="form-control form-control-sm trainingname" placeholder="Masukkan nama" />
</div>
<label for="site" class="form-label border-start border-5 border-primary ps-1">Nama</label>
<select name="siteid" id="siteid" class="form-select form-select-sm select2 site" required>
<option value="">-- Choose one --</option>
</select>
</div>
<div class="col-12 col-lg-5">
<div class="form-group">
@ -988,9 +989,9 @@ $('#status').change(function() {
// else { $("#maintenance").prop('disabled', true); $("#calibration").prop('disabled', true); $("#installation").prop('disabled', true); $("#offreport").prop('disabled', true); $("#training").prop('disabled', true);}
// })
$('#acttypeid').change(function() {
if (this.value=='5'){ $("#maintenance").prop('disabled', false); }
else if (this.value=='3'){ $("#maintenance").prop('disabled', true);}
else { $("#maintenance").prop('disabled', true);}
if (this.value=='5'){ $("#maintenance").prop('disabled', false); $("#installation").prop('disabled', true);}
else if (this.value=='3'){ $("#maintenance").prop('disabled', true); $("#installation").prop('disabled', false);}
else { $("#maintenance").prop('disabled', true); $("#installation").prop('disabled', true);}
})

View File

@ -1,577 +0,0 @@
<?= $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 Management</h4>
</div>
<!-- <div class="col-md-7 align-self-center text-end">
<button type="button" class="btn btn-info text-white btn-sm" data-bs-toggle="modal" data-bs-target="#createModal">
<i class="fas fa-plus-circle"></i> Create
</button>
</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>
</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="calibration">Calibration</option>
<option value="training">Training</option>
<option value="maintenance">Maintenance</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>
<div class="table-responsive">
<table id="certificatesTable" class="table table-striped table-hover border">
<thead class="table-primary">
<tr>
<th class="text-center" style="width: 5%;">No</th>
<th style="width: 15%;">Certificate Name</th>
<th style="width: 15%;">Product/Equipment</th>
<th style="width: 12%;">Type</th>
<th style="width: 12%;">Issue Date</th>
<th style="width: 12%;">Expiry Date</th>
<th style="width: 10%;">Status</th>
<th style="width: 10%;">Vendor</th>
<th class="text-center" style="width: 9%;">Action</th>
</tr>
</thead>
<tbody>
<?php
if(isset($certificates) && !empty($certificates)) {
$no = 1;
foreach($certificates as $cert) {
$certid = $cert['certid'] ?? '';
$certname = $cert['certname'] ?? '-';
$productname = $cert['productname'] ?? '-';
$productnumber = $cert['productnumber'] ?? '';
$type = $cert['type'] ?? '-';
$issuedate = $cert['issuedate'] ?? '';
$expirydate = $cert['expirydate'] ?? '';
$vendor = $cert['vendor'] ?? '-';
// Format dates
if($issuedate && $issuedate != '0000-00-00') {
$issuedate = date('M d, Y', strtotime($issuedate));
} else {
$issuedate = '-';
}
if($expirydate && $expirydate != '0000-00-00') {
$expirydate = date('M d, Y', strtotime($expirydate));
// Check expiry status
$today = date('Y-m-d');
$expiryCheck = date('Y-m-d', strtotime($cert['expirydate']));
$daysUntilExpiry = (strtotime($expiryCheck) - strtotime($today)) / (60 * 60 * 24);
if($daysUntilExpiry < 0) {
$statusBadge = '<span class="badge bg-danger">Expired</span>';
$statusClass = 'expired';
} elseif($daysUntilExpiry <= 30) {
$statusBadge = '<span class="badge bg-warning text-dark">Expiring Soon</span>';
$statusClass = 'expiring';
} else {
$statusBadge = '<span class="badge bg-success">Active</span>';
$statusClass = 'active';
}
} else {
$expirydate = '-';
$statusBadge = '<span class="badge bg-secondary">N/A</span>';
$statusClass = '';
}
// Type badge
$typeBadge = '';
switch(strtolower($type)) {
case 'calibration':
$typeBadge = '<span class="badge bg-info">Calibration</span>';
break;
case 'training':
$typeBadge = '<span class="badge bg-primary">Training</span>';
break;
case 'maintenance':
$typeBadge = '<span class="badge bg-warning text-dark">Maintenance</span>';
break;
default:
$typeBadge = '<span class="badge bg-secondary">' . htmlspecialchars($type) . '</span>';
}
?>
<tr>
<td class="text-center"><?= $no++; ?></td>
<td>
<strong><?= htmlspecialchars($certname) ?></strong>
<br>
<small class="text-muted">ID: <?= $certid ?></small>
</td>
<td>
<?= htmlspecialchars($productname) ?>
<?php if($productnumber): ?>
<br><small class="text-muted">SN: <?= htmlspecialchars($productnumber) ?></small>
<?php endif; ?>
</td>
<td><?= $typeBadge ?></td>
<td><?= $issuedate ?></td>
<td><?= $expirydate ?></td>
<td><?= $statusBadge ?></td>
<td><?= htmlspecialchars($vendor) ?></td>
<td class="text-center">
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-success btn-view" data-certid="<?= $certid ?>" data-certtype="<?= $type ?>" title="View PDF">
<i class="fas fa-file-pdf"></i>
</button>
<!-- <button type="button" class="btn btn-warning btn-edit" data-certid="<?= $certid ?>" title="Edit">
<i class="fas fa-edit"></i>
</button>
<button type="button" class="btn btn-danger btn-delete" data-certid="<?= $certid ?>" data-certname="<?= htmlspecialchars($certname) ?>" title="Delete">
<i class="fas fa-trash"></i>
</button> -->
</div>
</td>
</tr>
<?php
}
} else {
?>
<!-- <tr>
<td colspan="9" class="text-center py-5">
<i class="fas fa-certificate fa-3x text-muted mb-3"></i>
<p class="text-muted">No certificates found</p>
<button type="button" class="btn btn-info text-white btn-sm" data-bs-toggle="modal" data-bs-target="#createModal">
<i class="fas fa-plus-circle"></i> Add First Certificate
</button>
</td>
</tr> -->
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Create Modal -->
<!-- <div class="modal fade" id="createModal" tabindex="-1" aria-labelledby="createModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-info text-white">
<h5 class="modal-title" id="createModalLabel">
<i class="fas fa-plus-circle"></i> Create New Certificate
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form id="createForm" action="<?= base_url('certificates/create') ?>" method="post">
<div class="modal-body">
<div class="row">
<div class="col-md-6 mb-3">
<label for="certname" class="form-label">Certificate Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="certname" name="certname" required>
</div>
<div class="col-md-6 mb-3">
<label for="type" class="form-label">Type <span class="text-danger">*</span></label>
<select class="form-select" id="type" name="type" required>
<option value="">Select Type</option>
<option value="calibration">Calibration</option>
<option value="training">Training</option>
<option value="maintenance">Maintenance</option>
</select>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="productid" class="form-label">Product/Equipment</label>
<select class="form-select select2" id="productid" name="productid">
<option value="">Select Product</option>
<?php if(isset($products)): ?>
<?php foreach($products as $product): ?>
<option value="<?= $product['productid'] ?>">
<?= htmlspecialchars($product['productname']) ?>
<?php if($product['productnumber']): ?>
(SN: <?= htmlspecialchars($product['productnumber']) ?>)
<?php endif; ?>
</option>
<?php endforeach; ?>
<?php endif; ?>
</select>
</div>
<div class="col-md-6 mb-3">
<label for="vendor" class="form-label">Vendor/Provider</label>
<input type="text" class="form-control" id="vendor" name="vendor">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="issuedate" class="form-label">Issue Date</label>
<input type="date" class="form-control" id="issuedate" name="issuedate">
</div>
<div class="col-md-6 mb-3">
<label for="expirydate" class="form-label">Expiry Date</label>
<input type="date" class="form-control" id="expirydate" name="expirydate">
</div>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description" rows="3"></textarea>
</div>
<div class="mb-3">
<label for="attachment" class="form-label">Attachment</label>
<input type="file" class="form-control" id="attachment" name="attachment" accept=".pdf,.jpg,.jpeg,.png">
<small class="text-muted">Allowed: PDF, JPG, PNG (Max 5MB)</small>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="fas fa-times"></i> Cancel
</button>
<button type="submit" class="btn btn-info text-white">
<i class="fas fa-save"></i> Save
</button>
</div>
</form>
</div>
</div>
</div> -->
<!-- Edit Modal -->
<!-- <div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-warning text-dark">
<h5 class="modal-title" id="editModalLabel">
<i class="fas fa-edit"></i> Edit Certificate
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form id="editForm" action="<?= base_url('certificates/update') ?>" method="post">
<input type="hidden" id="edit_certid" name="certid">
<div class="modal-body">
<div class="row">
<div class="col-md-6 mb-3">
<label for="edit_certname" class="form-label">Certificate Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="edit_certname" name="certname" required>
</div>
<div class="col-md-6 mb-3">
<label for="edit_type" class="form-label">Type <span class="text-danger">*</span></label>
<select class="form-select" id="edit_type" name="type" required>
<option value="">Select Type</option>
<option value="calibration">Calibration</option>
<option value="training">Training</option>
<option value="maintenance">Maintenance</option>
</select>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="edit_productid" class="form-label">Product/Equipment</label>
<select class="form-select select2" id="edit_productid" name="productid">
<option value="">Select Product</option>
<?php if(isset($products)): ?>
<?php foreach($products as $product): ?>
<option value="<?= $product['productid'] ?>">
<?= htmlspecialchars($product['productname']) ?>
<?php if($product['productnumber']): ?>
(SN: <?= htmlspecialchars($product['productnumber']) ?>)
<?php endif; ?>
</option>
<?php endforeach; ?>
<?php endif; ?>
</select>
</div>
<div class="col-md-6 mb-3">
<label for="edit_vendor" class="form-label">Vendor/Provider</label>
<input type="text" class="form-control" id="edit_vendor" name="vendor">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="edit_issuedate" class="form-label">Issue Date</label>
<input type="date" class="form-control" id="edit_issuedate" name="issuedate">
</div>
<div class="col-md-6 mb-3">
<label for="edit_expirydate" class="form-label">Expiry Date</label>
<input type="date" class="form-control" id="edit_expirydate" name="expirydate">
</div>
</div>
<div class="mb-3">
<label for="edit_description" class="form-label">Description</label>
<textarea class="form-control" id="edit_description" name="description" rows="3"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="fas fa-times"></i> Cancel
</button>
<button type="submit" class="btn btn-warning text-dark">
<i class="fas fa-save"></i> Update
</button>
</div>
</form>
</div>
</div>
</div> -->
<!-- View Modal -->
<!-- <div class="modal fade" id="viewModal" tabindex="-1" aria-labelledby="viewModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-success text-white">
<h5 class="modal-title" id="viewModalLabel">
<i class="fas fa-eye"></i> Certificate Details
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div id="viewContent">
Content loaded via AJAX
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="fas fa-times"></i> Close
</button>
<button type="button" class="btn btn-primary" id="btnPrint">
<i class="fas fa-print"></i> Print
</button>
</div>
</div>
</div>
</div> -->
<!-- Delete Confirmation Modal -->
<!-- <div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-danger text-white">
<h5 class="modal-title" id="deleteModalLabel">
<i class="fas fa-exclamation-triangle"></i> Confirm Delete
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete this certificate?</p>
<div class="alert alert-warning">
<strong>Certificate:</strong> <span id="deleteCertName"></span>
</div>
<p class="text-muted small">This action cannot be undone.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="fas fa-times"></i> Cancel
</button>
<form id="deleteForm" action="<?= base_url('certificates/delete') ?>" method="post">
<input type="hidden" id="delete_certid" name="certid">
<button type="submit" class="btn btn-danger text-white">
<i class="fas fa-trash"></i> Delete
</button>
</form>
</div>
</div>
</div>
</div> -->
<?= $this->endSection() ?>
<?= $this->section('script') ?>
<script>
$(function () {
// Store DataTable instance
var table = null;
// Initialize DataTable
table = $('#certificatesTable').DataTable({
"order": [[0, "asc"]],
"pageLength": 25,
"lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
"language": {
"emptyTable": "No certificates available",
"info": "Showing _START_ to _END_ of _TOTAL_ certificates",
"infoEmpty": "No certificates found",
"infoFiltered": "(filtered from _MAX_ total certificates)"
},
"dom": '<"row"<"col-md-6"l>>rtip',
"columnDefs": [
{ "orderable": false, "targets": [8] }, // Disable sorting on Action column
{ "searchable": true, "targets": [0, 1, 2, 3, 4, 5, 6, 7] } // Enable search on all columns except Action
]
});
// Hide default DataTables search
$('#certificatesTable_filter').hide();
// Initialize Select2
$('.select2').select2({
theme: 'bootstrap-5',
width: '100%',
dropdownParent: $('.modal')
});
// Custom search functionality
$('#searchInput').on('keyup', function() {
var searchValue = $(this).val().toLowerCase();
table.search(searchValue).draw();
});
// Status filter using DataTables column filter
$('#statusFilter').on('change', function() {
var status = $(this).val();
// Filter by status column (index 6)
if(status === '') {
table.column(6).search('').draw();
} else {
// Search for the badge text in status column
var statusText = '';
switch(status) {
case 'active':
statusText = 'Active';
break;
case 'expired':
statusText = 'Expired';
break;
case 'expiring':
statusText = 'Expiring Soon';
break;
}
table.column(6).search(statusText).draw();
}
});
// Type filter using DataTables column filter
$('#typeFilter').on('change', function() {
var type = $(this).val();
// Filter by type column (index 3)
if(type === '') {
table.column(3).search('').draw();
} else {
// Capitalize first letter for search
var typeText = type.charAt(0).toUpperCase() + type.slice(1);
table.column(3).search(typeText).draw();
}
});
// Reset filters
window.resetFilters = function() {
$('#searchInput').val('');
$('#statusFilter').val('');
$('#typeFilter').val('');
// Reset DataTables search and filters
table.search('').columns().search('').draw();
// Re-apply default ordering
table.order([5, 'asc']).draw();
};
// View button click - Open PDF in new tab based on certificate type
$(document).on('click', '.btn-view', function() {
var certid = $(this).data('certid');
var certType = $(this).data('certtype');
var url = '';
switch(certType) {
case 'training':
url = '<?= base_url('certificates/training/show') ?>/' + certid;
break;
case 'calibration':
url = '<?= base_url('certificates/calibrate/show') ?>/' + certid;
break;
case 'maintenance':
url = '<?= base_url('certificates/maintenance/show') ?>/' + certid;
break;
default:
url = '<?= base_url('certificates/view') ?>/' + certid;
}
window.open(url, '_blank');
});
// Edit button click
// $(document).on('click', '.btn-edit', function() {
// var certid = $(this).data('certid');
// $('#edit_certid').val(certid);
// $('#editModal').modal('show');
// // Load certificate data via AJAX
// $.get('<?= base_url('certificates/get') ?>/' + certid, function(data) {
// $('#edit_certname').val(data.certname);
// $('#edit_type').val(data.type);
// $('#edit_productid').val(data.productid).trigger('change');
// $('#edit_vendor').val(data.vendor);
// $('#edit_issuedate').val(data.issuedate);
// $('#edit_expirydate').val(data.expirydate);
// $('#edit_description').val(data.description);
// }).fail(function() {
// $('#editModal').modal('hide');
// alert('Failed to load certificate data.');
// });
// });
// Delete button click
// $(document).on('click', '.btn-delete', function() {
// var certid = $(this).data('certid');
// var certname = $(this).data('certname');
// $('#delete_certid').val(certid);
// $('#deleteCertName').text(certname);
// $('#deleteModal').modal('show');
// });
// Print button
$('#btnPrint').on('click', function() {
window.print();
});
// Form validation
// $('#createForm, #editForm').on('submit', function(e) {
// var form = this;
// if(form.checkValidity()) {
// // Form is valid, submit
// return true;
// }
// e.preventDefault();
// e.stopPropagation();
// form.classList.add('was-validated');
// });
// Date picker enhancement
$('input[type="date"]').on('focus', function() {
this.showPicker();
});
// Re-attach event handlers after DataTables pagination/draw
table.on('draw.dt', function() {
// Event handlers are already attached using $(document).on(), so no need to re-attach
});
});
</script>
<?= $this->endSection() ?>

View File

@ -3,167 +3,162 @@
<?= $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 Installation Management</h4>
</div>
</div>
<div class="container-fluid">
<div class="row page-titles">
<div class="col-md-5 align-self-center">
<h4 class="text-themecolor">Certificates Installation 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>
<option value="isval">Need Validation</option>
</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>
<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="productFilter" class="form-select form-select-sm">
<option value="">--Product Filter--</option>
<option value="tms">TMS</option>
<option value="jokoh">Jokoh</option>
<option value="mindray">Mindray</option>
</select>
</div>
<div class="col-md-4 mb-2">
<select id="validationFilter" class="form-select form-select-sm">
<option value="">--Validation Filter--</option>
<option value="valid">Validated</option>
<option value="unval">Unvalidated</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>
<!-- 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>
<th style="width: 32%">Certificate</th>
<th style="width: 38%">Act Report</th>
<th style="width: 10%">Issue Date</th>
<th style="width: 8%">Validation</th>
<th class="text-center" style="width: 12%">Action</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Validate Modal -->
<div class="modal fade" id="validateModal" tabindex="-1" aria-labelledby="validateModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-centered">
<div class="modal-content">
<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
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<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>
</div>
<div class="col-md-6 mb-3">
<label class="form-label fw-bold">Certificate Name</label>
<p id="modalCertName" class="form-control-plaintext">-</p>
</div>
</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">
<div class="col-md-6 mb-3">
<label class="form-label fw-bold">Vendor</label>
<p id="modalVendor" class="form-control-plaintext">-</p>
</div>
<div class="modal-dialog modal-xl modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-warning text-dark" id='modalHeader'>
<h5 class="modal-title" id="validateModalLabel">
Validate installation Certificate
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row border-bottom mb-3 pb-2">
<div class="col-md-8">
<label class="form-label "><i class="fa-solid fa-certificate me-2"></i>Certificate Name</label>
<h5 id="modalCertName" class="mt-2 fw-bolder">-</h5>
</div>
<div class="col-md-4 text-md-end">
<h5 id="modalValidation">-</h5>
</div>
</div>
<div class="row">
<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>
<label class="form-label "><i class="fa-solid fa-book-medical me-2"></i>Certificate Number</label>
<p id="modalCertNumber" class="form-control-plaintext border-bottom fw-bolder">-</p>
</div>
<div class="col-md-6 mb-3">
<label class="form-label "><i class="fa-solid fa-microchip me-2"></i>Product/Equipment</label>
<p id="modalProductName" class="form-control-plaintext border-bottom fw-bolder">-</p>
</div>
<div class="col-md-6 mb-3">
<label class="form-label "><i class="fa-solid fa-hashtag me-2"></i>Serial Number</label>
<p id="modalProductNumber" class="form-control-plaintext border-bottom fw-bolder">-</p>
</div>
<div class="col-md-6 mb-3">
<label class="form-label "><i class="fa-regular fa-hospital me-2"></i>Site</label>
<p id="modalSiteName" class="form-control-plaintext border-bottom fw-bolder">-</p>
</div>
<div class="col-md-12 mb-3">
<label class="form-label "><i class="fa-solid fa-calendar-check me-2"></i>Issue Date</label>
<p id="modalIssueDate" class="form-control-plaintext border-bottom fw-bolder">-</p>
</div>
</div>
</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>
<div class="col-md-12 mb-4">
<label class="form-label "><i class="fa-solid fa-file-lines me-2"></i>Activity Report Reference</label>
<a href="javascript:void(0)" id="modalActivityLink" class="activity-report-link text-decoration-none fw-bolder" style="color:#d43215b0;">
<div class="p-2 border rounded bg-light">
<i class="fa-solid fa-up-right-from-square me-2"></i>
<span id="modalActivity">-</span>
</div>
</a>
</div>
<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>
</div>
</div>
</div>
<div class="col-md-4 mb-3">
<label class="form-label"><i class="fa-solid fa-user me-2"></i>Owner Validation</label>
<p id="modalValOwner" class="form-control-plaintext border-bottom fw-bolder">-</p>
</div>
<div class="col-md-4 mb-3">
<label class="form-label"><i class="fa-solid fa-user me-2"></i>SPV Validation</label>
<p id="modalValSpv" class="form-control-plaintext border-bottom fw-bolder">-</p>
</div>
<div class="col-md-4 mb-3">
<label class="form-label"><i class="fa-solid fa-user me-2"></i>Manager Validation</label>
<p id="modalValManager" class="form-control-plaintext border-bottom fw-bolder">-</p>
</div>
</div>
</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>
</div>
</div>
<div id='modalInfo'></div>
<div class="row">
<div class="col-md-12 mb-3">
<div class="border rounded p-2" style="height: 500px; overflow: hidden;">
<iframe id="certificatePreview" src="" style="width: 100%; height: 100%; border: none;"></iframe>
</div>
</div>
</div>
</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>
</div>
</div>
</div>
<?= $this->endSection() ?>
<?= $this->section('style') ?>
<style>
#certificatesTable {
width: 100% !important;
}
#certificatesTable_wrapper {
width: 100% !important;
}
</style>
<?= $this->endSection() ?>
<?= $this->section('script') ?>
@ -171,7 +166,7 @@
$(function () {
let table = $('#certificatesTable').DataTable({
order: [[5, 'asc']],
order: [[3, 'asc']], // Order by Validation Column
pageLength: 25,
dom: '<"row"<"col-md-6"l>>rtip',
responsive: true,
@ -182,53 +177,43 @@ $(function () {
.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;
data: result.map((cert, index) => {
let certid = cert.cert_id || '';
let certname = cert.cert_name || '-';
let certnumber = cert.cert_number || '';
let actid = cert.actid || '';
let issuedateRaw = cert.issued_date || '';
let status = cert.status; // Validation status
let fullname = cert.fullname;
let activity_subject = cert.activity_subject;
let issuedate = '-';
let expirydate = '-';
let statusBadge = '<span class="badge bg-warning text-dark">Need Validation</span>';
let validationBadge = '';
if (isval != null) {
if (issuedateRaw && issuedateRaw !== '0000-00-00') {
issuedate = new Date(issuedateRaw).toLocaleDateString('en-US', { month: 'short', day: '2-digit', year: 'numeric' });
}
if (issuedateRaw && issuedateRaw !== '0000-00-00') {
let date = new Date(issuedateRaw);
let day = String(date.getDate()).padStart(2, '0');
let month = date.toLocaleString('en-US', { month: 'short' });
let year = date.getFullYear();
issuedate = `${day} ${month} ${year}`;
}
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>';
}
if (status == 'unvalidated') {
validationBadge = '<div class=""><span class="badge bg-warning text-dark">unvalidated</span></div>';
} else {
validationBadge = '<div class=""><span class="badge bg-success">validated</span></div>';
}
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>`,
`<strong>${certname}</strong><br><small class="text-muted">Cert# : ${certnumber}</small>`,
`<a href="javascript:void(0)" class="activity-report-link text-decoration-none" data-certid="${certid}" data-actid="${actid}" style="color:#d43215b0;">#${actid} - ${activity_subject} &nbsp;<i class="fa-solid fa-up-right-from-square"></i></strong><br><small class="text-muted">Owner : ${fullname}</small></a>`,
issuedate,
expirydate,
statusBadge,
isval == null
? `<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>`
validationBadge,
status == 'unvalidated'
? `<div class="text-center"><button type="button" class="btn btn-sm btn-warning text-dark btn-validate-modal" data-certid="${certid}"><i class="fa-solid fa-triangle-exclamation me-2"></i>Need Validation</button></div>`
: `<div class="text-center mb-1"><button type="button" class="btn btn-sm btn-info btn-validate-modal" data-certid="${certid}"><i class="fa-regular fa-eye me-2"></i>Detail</button></div>
<div class="text-center"><button type="button" class="btn btn-sm btn-success btn-view" data-certnumber="${certnumber}"><i class="fa-regular fa-file-pdf me-2"></i>Generated PDF</button></div>`
];
})
});
@ -238,19 +223,26 @@ $(function () {
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;
columnDefs: [
{
// Kondisi untuk Kolom 3 (Validation)
targets: 3,
render: function (data, type) {
if (type === 'sort') {
let val = data.toLowerCase();
if (val.includes('unvalidated')) return 1;
if (val.includes('validated')) return 2;
return 3;
}
return data;
}
return data;
},
{
// Kondisi untuk Kolom 4 (Action)
targets: [4],
orderable: false
}
}]
]
});
$('#certificatesTable_filter').hide();
@ -261,70 +253,107 @@ $(function () {
});
// Type filter using DataTables column filter
$('#typeFilter').on('change', function () {
$('#productFilter').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();
table.column(0).search('').draw();
} else {
// Capitalize first letter for search
let typeText = type.charAt(0).toUpperCase() + type.slice(1);
table.column(1).search(typeText).draw();
table.column(0).search(typeText).draw();
}
});
// 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();
$('#validationFilter').on('change', function () {
let validation = $(this).val();
if (validation === '') {
table.column(3).search('').draw();
} else if (validation === 'unval') {
table.column(3).search('unv').draw();
} else if (validation === 'valid') {
table.column(3).search('^validated$', true, false).draw();
}
});
// Reset
window.resetFilters = function () {
$('#searchInput, #statusFilter').val('');
table.search('').columns().search('').order([5,'asc']).draw();
$('#searchInput, #productFilter, #validationFilter').val('');
table.search('').columns().search('').draw();
};
// View PDF
$(document).on('click', '.btn-view', function () {
let certid = $(this).data('certid');
window.open('<?= base_url('certificates/installation/show/') ?>' + certid, '_blank');
let certnumber = $(this).data('certnumber');
window.open('<?= base_url('certificates/number/') ?>' + certnumber, '_blank');
});
// Activity report
$(document).on('click', '.activity-report-link', function () {
let certid = $(this).data('certid');
let actid = $(this).data('actid');
window.open(
'<?= base_url('certificates/installation/activity/') ?>' + certid,
'<?= base_url('activities/detail/') ?>' + actid,
'_blank',
'width=1200,height=800,scrollbars=yes,resizable=yes'
);
});
// Open modal
$(document).on('click', '.btn-validate', function () {
$(document).on('click', '.btn-validate-modal', function () {
let btn = $(this);
let certid = btn.data('certid');
$('#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'));
// POST API call to fetch certificate data
$.post(
'<?= base_url('certificates/api/showinstallation') ?>',
{ certid },
function (data) {
$('#modalCertName').text(data.cert_name || '-');
$('#modalCertNumber').text(data.cert_number || '-');
$('#modalProductName').text(data.productname || '-');
$('#modalProductNumber').text(data.productnumber || '-');
$('#modalIssueDate').text(data.issued_date || '-');
$('#modalSiteName').text(data.sitename || '-');
$('#confirmValidateBtn').data('certid', btn.data('certid'));
$('#certificatePreview').attr(
'src',
'<?= base_url('certificates/installation/show/') ?>' + btn.data('certid')
);
// Cek status validasi
const isValid = data.status === 'validated';
const theme = isValid ? 'success' : 'warning';
const icon = isValid ? 'fa-regular fa-circle-check' : 'fa-solid fa-triangle-exclamation';
const note = isValid
? 'Sertifikat Sudah Divalidasi'
: 'Review data berikut dengan teliti, setelah divalidasi maka sertifikat akan dinyatakan <strong>Valid</strong> dan <strong>sah secara sistem.</strong>';
$('#modalHeader').removeClass('bg-warning bg-success').addClass(`bg-${theme} text-dark`);
$('#modalValidation').html(
`<span class="badge bg-${theme} text-dark py-2 px-3">
<i class="${icon} me-2"></i>${data.status || '-'}
</span>`
);
$('#modalInfo').html(
`<div class="alert alert-${theme} border-0 shadow-sm d-flex align-items-center">
<i class="${icon} fs-4 me-3"></i>
<div>
<strong>Validation Note:</strong><br>
${note}
</div>
</div>`
);
$('#modalActivity').text(data.actid ? `#${data.actid} - ${data.subject || '-'}` : '-');
$('#modalActivityLink').attr('data-actid', data.actid || '');
$('#modalValOwner').html(data.user_validation_at ? `${data.username} - ${data.user_validation_at}<i class="fa-solid fa-circle-check text-success ms-2"></i>` : '-');
$('#modalValSpv').html(data.spv_validation_at ? `${data.spvname} - ${data.spv_validation_at}<i class="fa-solid fa-circle-check text-success ms-2"></i>` : '-');
$('#modalValManager').html(data.manager_validation_at ? `${data.managername} - ${data.manager_validation_at}<i class="fa-solid fa-circle-check text-success ms-2"></i>` : '-');
},
'json'
).fail(function () {
console.error('Error fetching certificate data');
});
// INI JANGAN DIUBAH
$('#confirmValidateBtn').data('certid', certid);
$('#certificatePreview').attr('src','<?= base_url('certificates/installation/show/') ?>' + certid);
$('#validateModal').modal('show');
});
@ -337,43 +366,23 @@ $(function () {
if (!confirm('Are you sure?')) return;
$.post(
'<?= base_url('certificates/api/validateCertificate') ?>',
'<?= base_url('certificates/api/validatecertificate') ?>',
{ certid, certificateType},
function (response) {
if (response.success) {
$('#validateModal').modal('hide');
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();
});
location.reload();
} else {
alert(response.message || 'Validation failed');
}
}, 'json'
).fail(function () {
$('#validateModal').modal('hide');
alert('Server error.');
).fail(function (xhr) {
console.log(xhr);
alert(xhr.responseText);
});
});
});

View File

@ -1,545 +0,0 @@
<?= $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 class="col-md-7 align-self-center text-end">
<button type="button" class="btn btn-info text-white btn-sm" data-bs-toggle="modal" data-bs-target="#createModal">
<i class="fas fa-plus-circle"></i> Create
</button>
</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>
</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="calibration">Calibration</option>
<option value="training">Training</option>
<option value="maintenance">Maintenance</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>
<div class="table-responsive">
<table id="certificatesTable" class="table table-striped table-hover border">
<thead class="table-primary">
<tr>
<th class="text-center" style="width: 5%;">No</th>
<th style="width: 15%;">Certificate Name</th>
<th style="width: 15%;">Product/Equipment</th>
<th style="width: 12%;">Type</th>
<th style="width: 12%;">Issue Date</th>
<th style="width: 12%;">Expiry Date</th>
<th style="width: 10%;">Status</th>
<th style="width: 10%;">Vendor</th>
<th class="text-center" style="width: 9%;">Action</th>
</tr>
</thead>
<tbody>
<?php
if(isset($certificates) && !empty($certificates)) {
$no = 1;
foreach($certificates as $cert) {
$certid = $cert['certid'] ?? '';
$certname = $cert['certname'] ?? '-';
$productname = $cert['productname'] ?? '-';
$productnumber = $cert['productnumber'] ?? '';
$type = $cert['type'] ?? '-';
$issuedate = $cert['issuedate'] ?? '';
$expirydate = $cert['expirydate'] ?? '';
$vendor = $cert['vendor'] ?? '-';
// Format dates
if($issuedate && $issuedate != '0000-00-00') {
$issuedate = date('M d, Y', strtotime($issuedate));
} else {
$issuedate = '-';
}
if($expirydate && $expirydate != '0000-00-00') {
$expirydate = date('M d, Y', strtotime($expirydate));
// Check expiry status
$today = date('Y-m-d');
$expiryCheck = date('Y-m-d', strtotime($cert['expirydate']));
$daysUntilExpiry = (strtotime($expiryCheck) - strtotime($today)) / (60 * 60 * 24);
if($daysUntilExpiry < 0) {
$statusBadge = '<span class="badge bg-danger">Expired</span>';
$statusClass = 'expired';
} elseif($daysUntilExpiry <= 30) {
$statusBadge = '<span class="badge bg-warning text-dark">Expiring Soon</span>';
$statusClass = 'expiring';
} else {
$statusBadge = '<span class="badge bg-success">Active</span>';
$statusClass = 'active';
}
} else {
$expirydate = '-';
$statusBadge = '<span class="badge bg-secondary">N/A</span>';
$statusClass = '';
}
// Type badge
$typeBadge = '';
switch(strtolower($type)) {
case 'calibration':
$typeBadge = '<span class="badge bg-info">Calibration</span>';
break;
case 'training':
$typeBadge = '<span class="badge bg-primary">Training</span>';
break;
case 'maintenance':
$typeBadge = '<span class="badge bg-warning text-dark">Maintenance</span>';
break;
default:
$typeBadge = '<span class="badge bg-secondary">' . htmlspecialchars($type) . '</span>';
}
?>
<tr>
<td class="text-center"><?= $no++; ?></td>
<td>
<strong><?= htmlspecialchars($certname) ?></strong>
<br>
<small class="text-muted">ID: <?= $certid ?></small>
</td>
<td>
<?= htmlspecialchars($productname) ?>
<?php if($productnumber): ?>
<br><small class="text-muted">SN: <?= htmlspecialchars($productnumber) ?></small>
<?php endif; ?>
</td>
<td><?= $typeBadge ?></td>
<td><?= $issuedate ?></td>
<td><?= $expirydate ?></td>
<td><?= $statusBadge ?></td>
<td><?= htmlspecialchars($vendor) ?></td>
<td class="text-center">
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-success btn-view" data-certid="<?= $certid ?>" data-certtype="<?= $type ?>" title="View PDF">
<i class="fas fa-file-pdf"></i>
</button>
<button type="button" class="btn btn-warning btn-edit" data-certid="<?= $certid ?>" title="Edit">
<i class="fas fa-edit"></i>
</button>
<button type="button" class="btn btn-danger btn-delete" data-certid="<?= $certid ?>" data-certname="<?= htmlspecialchars($certname) ?>" title="Delete">
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
<?php
}
} else {
?>
<tr>
<td colspan="9" class="text-center py-5">
<i class="fas fa-certificate fa-3x text-muted mb-3"></i>
<p class="text-muted">No certificates found</p>
<button type="button" class="btn btn-info text-white btn-sm" data-bs-toggle="modal" data-bs-target="#createModal">
<i class="fas fa-plus-circle"></i> Add First Certificate
</button>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Create Modal -->
<div class="modal fade" id="createModal" tabindex="-1" aria-labelledby="createModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-info text-white">
<h5 class="modal-title" id="createModalLabel">
<i class="fas fa-plus-circle"></i> Create New Certificate
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form id="createForm" action="<?= base_url('certificates/create') ?>" method="post">
<div class="modal-body">
<div class="row">
<div class="col-md-6 mb-3">
<label for="certname" class="form-label">Certificate Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="certname" name="certname" required>
</div>
<div class="col-md-6 mb-3">
<label for="type" class="form-label">Type <span class="text-danger">*</span></label>
<select class="form-select" id="type" name="type" required>
<option value="">Select Type</option>
<option value="calibration">Calibration</option>
<option value="training">Training</option>
<option value="maintenance">Maintenance</option>
</select>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="productid" class="form-label">Product/Equipment</label>
<select class="form-select select2" id="productid" name="productid">
<option value="">Select Product</option>
<?php if(isset($products)): ?>
<?php foreach($products as $product): ?>
<option value="<?= $product['productid'] ?>">
<?= htmlspecialchars($product['productname']) ?>
<?php if($product['productnumber']): ?>
(SN: <?= htmlspecialchars($product['productnumber']) ?>)
<?php endif; ?>
</option>
<?php endforeach; ?>
<?php endif; ?>
</select>
</div>
<div class="col-md-6 mb-3">
<label for="vendor" class="form-label">Vendor/Provider</label>
<input type="text" class="form-control" id="vendor" name="vendor">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="issuedate" class="form-label">Issue Date</label>
<input type="date" class="form-control" id="issuedate" name="issuedate">
</div>
<div class="col-md-6 mb-3">
<label for="expirydate" class="form-label">Expiry Date</label>
<input type="date" class="form-control" id="expirydate" name="expirydate">
</div>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description" rows="3"></textarea>
</div>
<div class="mb-3">
<label for="attachment" class="form-label">Attachment</label>
<input type="file" class="form-control" id="attachment" name="attachment" accept=".pdf,.jpg,.jpeg,.png">
<small class="text-muted">Allowed: PDF, JPG, PNG (Max 5MB)</small>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="fas fa-times"></i> Cancel
</button>
<button type="submit" class="btn btn-info text-white">
<i class="fas fa-save"></i> Save
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Modal -->
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-warning text-dark">
<h5 class="modal-title" id="editModalLabel">
<i class="fas fa-edit"></i> Edit Certificate
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form id="editForm" action="<?= base_url('certificates/update') ?>" method="post">
<input type="hidden" id="edit_certid" name="certid">
<div class="modal-body">
<div class="row">
<div class="col-md-6 mb-3">
<label for="edit_certname" class="form-label">Certificate Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="edit_certname" name="certname" required>
</div>
<div class="col-md-6 mb-3">
<label for="edit_type" class="form-label">Type <span class="text-danger">*</span></label>
<select class="form-select" id="edit_type" name="type" required>
<option value="">Select Type</option>
<option value="calibration">Calibration</option>
<option value="training">Training</option>
<option value="maintenance">Maintenance</option>
</select>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="edit_productid" class="form-label">Product/Equipment</label>
<select class="form-select select2" id="edit_productid" name="productid">
<option value="">Select Product</option>
<?php if(isset($products)): ?>
<?php foreach($products as $product): ?>
<option value="<?= $product['productid'] ?>">
<?= htmlspecialchars($product['productname']) ?>
<?php if($product['productnumber']): ?>
(SN: <?= htmlspecialchars($product['productnumber']) ?>)
<?php endif; ?>
</option>
<?php endforeach; ?>
<?php endif; ?>
</select>
</div>
<div class="col-md-6 mb-3">
<label for="edit_vendor" class="form-label">Vendor/Provider</label>
<input type="text" class="form-control" id="edit_vendor" name="vendor">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="edit_issuedate" class="form-label">Issue Date</label>
<input type="date" class="form-control" id="edit_issuedate" name="issuedate">
</div>
<div class="col-md-6 mb-3">
<label for="edit_expirydate" class="form-label">Expiry Date</label>
<input type="date" class="form-control" id="edit_expirydate" name="expirydate">
</div>
</div>
<div class="mb-3">
<label for="edit_description" class="form-label">Description</label>
<textarea class="form-control" id="edit_description" name="description" rows="3"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="fas fa-times"></i> Cancel
</button>
<button type="submit" class="btn btn-warning text-dark">
<i class="fas fa-save"></i> Update
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-danger text-white">
<h5 class="modal-title" id="deleteModalLabel">
<i class="fas fa-exclamation-triangle"></i> Confirm Delete
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete this certificate?</p>
<div class="alert alert-warning">
<strong>Certificate:</strong> <span id="deleteCertName"></span>
</div>
<p class="text-muted small">This action cannot be undone.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="fas fa-times"></i> Cancel
</button>
<form id="deleteForm" action="<?= base_url('certificates/delete') ?>" method="post">
<input type="hidden" id="delete_certid" name="certid">
<button type="submit" class="btn btn-danger text-white">
<i class="fas fa-trash"></i> Delete
</button>
</form>
</div>
</div>
</div>
</div>
<?= $this->endSection() ?>
<?= $this->section('script') ?>
<script>
$(function () {
// Store DataTable instance
var table = null;
// Initialize DataTable
table = $('#certificatesTable').DataTable({
"order": [[0, "asc"]],
"pageLength": 25,
"lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
"language": {
"emptyTable": "No certificates available",
"info": "Showing _START_ to _END_ of _TOTAL_ certificates",
"infoEmpty": "No certificates found",
"infoFiltered": "(filtered from _MAX_ total certificates)"
},
"dom": '<"row"<"col-md-6"l>>rtip',
"columnDefs": [
{ "orderable": false, "targets": [8] }, // Disable sorting on Action column
{ "searchable": true, "targets": [0, 1, 2, 3, 4, 5, 6, 7] } // Enable search on all columns except Action
]
});
// Hide default DataTables search
$('#certificatesTable_filter').hide();
// Initialize Select2
$('.select2').select2({
theme: 'bootstrap-5',
width: '100%',
dropdownParent: $('.modal')
});
// Custom search functionality
$('#searchInput').on('keyup', function() {
var searchValue = $(this).val().toLowerCase();
table.search(searchValue).draw();
});
// Status filter using DataTables column filter
$('#statusFilter').on('change', function() {
var status = $(this).val();
// Filter by status column (index 6)
if(status === '') {
table.column(6).search('').draw();
} else {
// Search for the badge text in status column
var statusText = '';
switch(status) {
case 'active':
statusText = 'Active';
break;
case 'expired':
statusText = 'Expired';
break;
case 'expiring':
statusText = 'Expiring Soon';
break;
}
table.column(6).search(statusText).draw();
}
});
// Type filter using DataTables column filter
$('#typeFilter').on('change', function() {
var type = $(this).val();
// Filter by type column (index 3)
if(type === '') {
table.column(3).search('').draw();
} else {
// Capitalize first letter for search
var typeText = type.charAt(0).toUpperCase() + type.slice(1);
table.column(3).search(typeText).draw();
}
});
// Reset filters
window.resetFilters = function() {
$('#searchInput').val('');
$('#statusFilter').val('');
$('#typeFilter').val('');
// Reset DataTables search and filters
table.search('').columns().search('').draw();
// Re-apply default ordering
table.order([5, 'asc']).draw();
};
// View button click - Open PDF in new tab based on certificate type
$(document).on('click', '.btn-view', function() {
var certid = $(this).data('certid');
var certType = $(this).data('certtype');
var url = '';
switch(certType) {
case 'training':
url = '<?= base_url('certificates/training') ?>/' + certid;
break;
case 'calibration':
url = '<?= base_url('certificates/calibrate') ?>/' + certid;
break;
case 'maintenance':
url = '<?= base_url('certificates/maintenance') ?>/' + certid;
break;
default:
url = '<?= base_url('certificates/view') ?>/' + certid;
}
window.open(url, '_blank');
});
// Edit button click
$(document).on('click', '.btn-edit', function() {
var certid = $(this).data('certid');
$('#edit_certid').val(certid);
$('#editModal').modal('show');
// Load certificate data via AJAX
$.get('<?= base_url('certificates/get') ?>/' + certid, function(data) {
$('#edit_certname').val(data.certname);
$('#edit_type').val(data.type);
$('#edit_productid').val(data.productid).trigger('change');
$('#edit_vendor').val(data.vendor);
$('#edit_issuedate').val(data.issuedate);
$('#edit_expirydate').val(data.expirydate);
$('#edit_description').val(data.description);
}).fail(function() {
$('#editModal').modal('hide');
alert('Failed to load certificate data.');
});
});
// Delete button click
$(document).on('click', '.btn-delete', function() {
var certid = $(this).data('certid');
var certname = $(this).data('certname');
$('#delete_certid').val(certid);
$('#deleteCertName').text(certname);
$('#deleteModal').modal('show');
});
// Form validation
$('#createForm, #editForm').on('submit', function(e) {
var form = this;
if(form.checkValidity()) {
// Form is valid, submit
return true;
}
e.preventDefault();
e.stopPropagation();
form.classList.add('was-validated');
});
// Date picker enhancement
$('input[type="date"]').on('focus', function() {
this.showPicker();
});
// Re-attach event handlers after DataTables pagination/draw
table.on('draw.dt', function() {
// Event handlers are already attached using $(document).on(), so no need to re-attach
});
});
</script>
<?= $this->endSection() ?>

View File

@ -41,10 +41,10 @@
<li> <a class="has-arrow waves-effect waves-dark" href='javascript:void(0)' aria-expanded="false"> <i class="fa-solid fa-certificate"></i><span class='hide-menu'>Certificates</span> </a>
<ul aria-expanded="false" class="collapse">
<li><a href="<?=base_url();?>certificates/maintenance">Maintenance</a></li>
<!-- <li><a href="<?=base_url();?>certificates/installation">Installation</a></li>
<li><a href="<?=base_url();?>certificates/training">Training</a></li>
<li><a href="<?=base_url();?>certificates/calibration">Callibration</a></li>
<li><a href="<?=base_url();?>certificates/official-report">Official Report</a></li> -->
<li><a href="<?=base_url();?>certificates/installation">Installation</a></li>
<!-- <li><a href="<?=base_url();?>certificates/training">Training</a></li> -->
<!-- <li><a href="<?=base_url();?>certificates/calibration">Callibration</a></li> -->
<!-- <li><a href="<?=base_url();?>certificates/official-report">Official Report</a></li> -->
</ul>
</li>