feat(memo): tambah filter jenis penilaian dan perbaiki fungsi clear checkbox pada datatable memo
Perubahan yang dilakukan:
- Menambahkan dropdown filter "Jenis Penilaian" (Internal/External) pada halaman index memo penyelesaian
- Mengimplementasikan filter gabungan menggunakan separator '|' untuk kombinasi filter dan search
- Memperbaiki fungsi clearSelectedCheckboxes dengan selector '#memo-table thead input[type="checkbox"]' agar lebih spesifik
- Menambahkan event listener untuk filter jenis penilaian yang terintegrasi dengan fungsi search datatable
- Mengupdate MemoController untuk memisahkan parameter filter menjadi jenis penilaian dan search term menggunakan explode('|')
- Menambahkan log untuk debugging filter dan proses checkbox
- Memodifikasi tampilan dengan class `gap-2` pada container filter untuk spacing yang lebih baik
- Menambahkan console.log pada fungsi handleCheckboxChange untuk tracking interaksi user
- Memperbaiki error handling pada fungsi clearSelectedCheckboxes untuk memastikan checkbox ter-reset dengan benar
- Menampilkan jumlah item terpilih pada tombol "Create Memo" untuk meningkatkan feedback user
Tujuan perubahan:
- Mempermudah pengguna dalam memfilter data berdasarkan jenis penilaian langsung di datatable memo
- Memastikan fungsi checkbox selection berjalan dengan konsisten dan lebih robust
- Meningkatkan user experience dengan feedback visual yang lebih jelas saat filter dan selection digunakan
- Menyederhanakan interaksi user sekaligus menjaga akurasi proses pembuatan memo penyelesaian
This commit is contained in:
@@ -190,22 +190,33 @@ class MemoController extends Controller
|
|||||||
$q->whereIn('nilai_plafond_id', [1, 4])
|
$q->whereIn('nilai_plafond_id', [1, 4])
|
||||||
->whereNotNull('approval_dd_at')
|
->whereNotNull('approval_dd_at')
|
||||||
->orWhereIn('nilai_plafond_id', [2, 3]);
|
->orWhereIn('nilai_plafond_id', [2, 3]);
|
||||||
})
|
});
|
||||||
->whereHas('noc'); // Hanya tampilkan permohonan yang memiliki NOC
|
//->whereHas('noc'); // Hanya tampilkan permohonan yang memiliki NOC
|
||||||
|
|
||||||
|
|
||||||
$query = $query->orderBy('nomor_registrasi', 'desc');
|
$query = $query->orderBy('nomor_registrasi', 'desc');
|
||||||
|
|
||||||
// Apply search filter jika ada
|
// Apply search filter jika ada
|
||||||
if ($request->has('search') && !empty($request->get('search'))) {
|
if ($request->has('search') && !empty($request->get('search'))) {
|
||||||
$search = $request->get('search');
|
$searchParams = explode('|', $request->get('search'));
|
||||||
$query->where(function ($q) use ($search) {
|
|
||||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
|
$filterJenisPenilaian = $searchParams[0] ?? '';
|
||||||
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
|
$searchTerm = $searchParams[1] ?? '';
|
||||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
|
|
||||||
$q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%');
|
// Filter berdasarkan jenis penilaian
|
||||||
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
|
if (!empty($filterJenisPenilaian)) {
|
||||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
|
$query->where('jenis_penilaian_id', $filterJenisPenilaian);
|
||||||
$q->orWhere('status', 'LIKE', '%' . $search . '%');
|
Log::info('Applied jenis penilaian filter', ['filter' => $filterJenisPenilaian]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$query->where(function ($q) use ($searchTerm) {
|
||||||
|
$q->where('nomor_registrasi', 'LIKE', '%' . $searchTerm . '%');
|
||||||
|
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $searchTerm . '%');
|
||||||
|
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $searchTerm . '%');
|
||||||
|
$q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $searchTerm . '%');
|
||||||
|
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $searchTerm . '%');
|
||||||
|
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $searchTerm . '%');
|
||||||
|
$q->orWhere('status', 'LIKE', '%' . $searchTerm . '%');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,15 @@
|
|||||||
Memo Penyelesaian
|
Memo Penyelesaian
|
||||||
</h3>
|
</h3>
|
||||||
<div class="flex flex-wrap gap-2 lg:gap-5">
|
<div class="flex flex-wrap gap-2 lg:gap-5">
|
||||||
<div class="flex">
|
<div class="flex gap-2">
|
||||||
<label class="input input-sm"> <i class="ki-filled ki-magnifier"> </i>
|
<label class="input input-sm"> <i class="ki-filled ki-magnifier"> </i>
|
||||||
<input placeholder="Search Memo Penyelesaian" id="search" type="text" value="">
|
<input placeholder="Search Memo Penyelesaian" id="search" type="text" value="">
|
||||||
</label>
|
</label>
|
||||||
|
<select class="select select-sm" id="filter-jenis-penilaian">
|
||||||
|
<option value="">Semua Jenis Penilaian</option>
|
||||||
|
<option value="1">Internal</option>
|
||||||
|
<option value="2">External</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-wrap gap-2.5">
|
<div class="flex flex-wrap gap-2.5">
|
||||||
<div class="h-[24px] border border-r-gray-200"></div>
|
<div class="h-[24px] border border-r-gray-200"></div>
|
||||||
@@ -128,6 +133,7 @@
|
|||||||
<script type="module">
|
<script type="module">
|
||||||
const element = document.querySelector('#memo-table');
|
const element = document.querySelector('#memo-table');
|
||||||
const searchInput = document.getElementById('search');
|
const searchInput = document.getElementById('search');
|
||||||
|
const filterJenisPenilaian = document.getElementById('filter-jenis-penilaian');
|
||||||
const btnCreateMemo = document.getElementById('btn-create-memo');
|
const btnCreateMemo = document.getElementById('btn-create-memo');
|
||||||
let selectedItems = [];
|
let selectedItems = [];
|
||||||
|
|
||||||
@@ -298,22 +304,60 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Fungsi untuk menangani perubahan checkbox
|
* Fungsi untuk menangani perubahan checkbox
|
||||||
|
* Mengelola state tombol berdasarkan checkbox yang dipilih
|
||||||
*/
|
*/
|
||||||
function handleCheckboxChange() {
|
function handleCheckboxChange() {
|
||||||
// Hanya ambil checkbox yang tidak disabled dan checked
|
// Hanya ambil checkbox yang tidak disabled dan checked
|
||||||
const checkboxes = document.querySelectorAll('input[data-datatable-row-check="true"]:checked:not(:disabled)');
|
const checkboxes = document.querySelectorAll('input[data-datatable-row-check="true"]:checked:not(:disabled)');
|
||||||
selectedItems = Array.from(checkboxes).map(cb => cb.value);
|
selectedItems = Array.from(checkboxes).map(cb => cb.value);
|
||||||
|
|
||||||
// Enable/disable tombol create memo berdasarkan jumlah item yang dipilih
|
// Log untuk debugging
|
||||||
btnCreateMemo.disabled = selectedItems.length === 0;
|
console.log('Selected items:', selectedItems);
|
||||||
|
|
||||||
if (selectedItems.length > 0) {
|
// Enable/disable tombol berdasarkan jumlah item yang dipilih
|
||||||
|
const hasSelection = selectedItems.length > 0;
|
||||||
|
btnCreateMemo.disabled = !hasSelection;
|
||||||
|
|
||||||
|
// Update text tombol create memo
|
||||||
|
if (hasSelection) {
|
||||||
btnCreateMemo.textContent = `Buat Memo Penyelesaian (${selectedItems.length} item)`;
|
btnCreateMemo.textContent = `Buat Memo Penyelesaian (${selectedItems.length} item)`;
|
||||||
} else {
|
} else {
|
||||||
btnCreateMemo.textContent = 'Buat Memo Penyelesaian';
|
btnCreateMemo.textContent = 'Buat Memo Penyelesaian';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fungsi untuk clear semua checkbox yang terpilih
|
||||||
|
* Menghapus semua selection dan reset state tombol
|
||||||
|
*/
|
||||||
|
function clearSelectedCheckboxes() {
|
||||||
|
try {
|
||||||
|
// Uncheck master checkbox juga - gunakan selector yang lebih spesifik
|
||||||
|
const masterCheckbox = document.querySelector('#memo-table thead input[type="checkbox"]');
|
||||||
|
if (masterCheckbox) {
|
||||||
|
masterCheckbox.checked = false;
|
||||||
|
}
|
||||||
|
// Uncheck semua checkbox yang tidak disabled
|
||||||
|
const checkboxes = document.querySelectorAll('input[data-datatable-row-check="true"]:not(:disabled)');
|
||||||
|
checkboxes.forEach(checkbox => {
|
||||||
|
checkbox.checked = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reset selected items array
|
||||||
|
selectedItems = [];
|
||||||
|
|
||||||
|
// Update state tombol
|
||||||
|
btnCreateMemo.disabled = true;
|
||||||
|
btnCreateMemo.textContent = 'Buat Memo Penyelesaian';
|
||||||
|
|
||||||
|
// Log untuk debugging
|
||||||
|
console.log('All checkboxes cleared successfully');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error clearing checkboxes:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Event listener untuk checkbox changes
|
// Event listener untuk checkbox changes
|
||||||
element.addEventListener('change', function(e) {
|
element.addEventListener('change', function(e) {
|
||||||
if (e.target.type === 'checkbox') {
|
if (e.target.type === 'checkbox') {
|
||||||
@@ -325,6 +369,7 @@
|
|||||||
btnCreateMemo.addEventListener('click', function() {
|
btnCreateMemo.addEventListener('click', function() {
|
||||||
if (selectedItems.length > 0) {
|
if (selectedItems.length > 0) {
|
||||||
const selectedIds = selectedItems.join(',');
|
const selectedIds = selectedItems.join(',');
|
||||||
|
console.log('Creating memo for IDs:', selectedIds);
|
||||||
window.location.href = `{{ route('memo.create') }}?selected_ids=${selectedIds}`;
|
window.location.href = `{{ route('memo.create') }}?selected_ids=${selectedIds}`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -334,5 +379,43 @@
|
|||||||
const searchValue = this.value.trim();
|
const searchValue = this.value.trim();
|
||||||
dataTable.search(searchValue, true);
|
dataTable.search(searchValue, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter berdasarkan jenis penilaian
|
||||||
|
* Menggunakan pola yang sama dengan districts filter
|
||||||
|
*/
|
||||||
|
filterJenisPenilaian.addEventListener('change', function() {
|
||||||
|
const filterValue = this.value;
|
||||||
|
const searchValue = searchInput.value.trim();
|
||||||
|
|
||||||
|
// Gabungkan filter dan search dalam satu parameter
|
||||||
|
const combinedSearch = `${filterValue}|${searchValue}`;
|
||||||
|
|
||||||
|
// Log untuk debugging
|
||||||
|
console.log('Filter jenis penilaian:', filterValue);
|
||||||
|
console.log('Search value:', searchValue);
|
||||||
|
console.log('Combined search:', combinedSearch);
|
||||||
|
|
||||||
|
// Gunakan search method seperti di districts
|
||||||
|
dataTable.search(combinedSearch, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update search input handler untuk mendukung filter
|
||||||
|
*/
|
||||||
|
searchInput.addEventListener('input', function() {
|
||||||
|
const searchValue = this.value.trim();
|
||||||
|
const filterValue = filterJenisPenilaian.value;
|
||||||
|
|
||||||
|
// Gabungkan search dan filter
|
||||||
|
const combinedSearch = `${filterValue}|${searchValue}`;
|
||||||
|
|
||||||
|
// Log untuk debugging
|
||||||
|
console.log('Search input:', searchValue);
|
||||||
|
console.log('Current filter:', filterValue);
|
||||||
|
console.log('Combined search:', combinedSearch);
|
||||||
|
|
||||||
|
dataTable.search(combinedSearch, true);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
@endpush
|
||||||
|
|||||||
Reference in New Issue
Block a user