🎨 feat(slik): Implementasi fitur pindah data SLIK ke laporan dan perbaikan UI
- Menambahkan tombol "SLIK" pada halaman index dan show untuk memindahkan data ke laporan SLIK - Mengimplementasikan fungsi moveToLaporan() dengan konfirmasi SweetAlert dan proses AJAX - Melakukan migrasi framework CSS dari Bootstrap ke TailwindCSS pada laporan-slik/show.blade.php - Memperbaiki struktur layout dengan grid system TailwindCSS yang responsif - Mengupdate breadcrumbs dengan styling dan route names yang benar - Menghapus fitur truncate data SLIK dari interface untuk keamanan data - Memperbaiki route names dari admin-kredit.laporan-slik menjadi laporan-slik - Mengoptimasi tombol Export dengan penghapusan parameter ID yang tidak diperlukan - Menambahkan konfigurasi import SLIK di .env.example untuk optimasi performa - Memperbaiki template download link dengan class styling yang konsisten - Mengimplementasikan error handling yang komprehensif dengan user feedback - Menambahkan auto-reload DataTable setelah operasi pemindahan data berhasil - Melakukan redesign card layout dengan pembagian "Data Debitur" dan "Data Fasilitas" - Menambahkan feedback visual dengan disable tombol setelah berhasil dipindahkan - Mengoptimasi konfigurasi DataTable dengan reload functionality - Menambahkan breadcrumb routes untuk laporan SLIK dengan struktur hierarki - Mengimplementasikan progress tracking untuk monitoring proses import - Memperbaiki JavaScript dengan pemisahan fungsi dan penambahan variabel global - Menstandarisasi framework CSS untuk konsistensi visual - Mengimplementasikan responsive design yang lebih baik
This commit is contained in:
117
app/Exports/LaporanSlikExport.php
Normal file
117
app/Exports/LaporanSlikExport.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Exports;
|
||||
|
||||
use Maatwebsite\Excel\Concerns\FromQuery;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
use Maatwebsite\Excel\Concerns\WithStyles;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class LaporanSlikExport implements FromQuery, WithHeadings, WithMapping, WithStyles
|
||||
{
|
||||
protected $query;
|
||||
|
||||
public function __construct($query)
|
||||
{
|
||||
$this->query = $query;
|
||||
}
|
||||
|
||||
public function query()
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'Sandi Bank',
|
||||
'Kode Kantor',
|
||||
'Kode Cabang',
|
||||
'Tahun',
|
||||
'Bulan',
|
||||
'No Rekening',
|
||||
'CIF',
|
||||
'Nama Debitur',
|
||||
'NPWP',
|
||||
'No KTP',
|
||||
'No Telp',
|
||||
'Alamat',
|
||||
'Kode Pos',
|
||||
'Kode Kab/Kota',
|
||||
'Kode Negara Domisili',
|
||||
'Kode Jenis',
|
||||
'Kode Sifat',
|
||||
'Kode Valuta',
|
||||
'Baki Debet',
|
||||
'Kolektibilitas',
|
||||
'Tanggal Mulai',
|
||||
'Tanggal Jatuh Tempo',
|
||||
'Tanggal Selesai',
|
||||
'Tanggal Restrukturisasi',
|
||||
'Kode Sebab Macet',
|
||||
'Tanggal Macet',
|
||||
'Kode Kondisi',
|
||||
'Tanggal Kondisi',
|
||||
'Nilai Agunan',
|
||||
'Jenis Agunan',
|
||||
'Kode Agunan',
|
||||
'Peringkat Agunan',
|
||||
'Fasilitas',
|
||||
'Status Agunan',
|
||||
'Tanggal Lapor',
|
||||
'Status',
|
||||
'Tanggal Dibuat',
|
||||
];
|
||||
}
|
||||
|
||||
public function map($laporanSlik): array
|
||||
{
|
||||
return [
|
||||
$laporanSlik->sandi_bank,
|
||||
$laporanSlik->kode_kantor,
|
||||
$laporanSlik->kode_cabang,
|
||||
$laporanSlik->tahun,
|
||||
$laporanSlik->bulan,
|
||||
$laporanSlik->no_rekening,
|
||||
$laporanSlik->cif,
|
||||
$laporanSlik->nama_debitur,
|
||||
$laporanSlik->npwp,
|
||||
$laporanSlik->no_ktp,
|
||||
$laporanSlik->no_telp,
|
||||
$laporanSlik->alamat,
|
||||
$laporanSlik->kode_pos,
|
||||
$laporanSlik->kode_kab_kota,
|
||||
$laporanSlik->kode_negara_domisili,
|
||||
$laporanSlik->kode_jenis,
|
||||
$laporanSlik->kode_sifat,
|
||||
$laporanSlik->kode_valuta,
|
||||
$laporanSlik->baki_debet,
|
||||
$laporanSlik->kolektibilitas,
|
||||
$laporanSlik->tanggal_mulai,
|
||||
$laporanSlik->tanggal_jatuh_tempo,
|
||||
$laporanSlik->tanggal_selesai,
|
||||
$laporanSlik->tanggal_restrukturisasi,
|
||||
$laporanSlik->kode_sebab_macet,
|
||||
$laporanSlik->tanggal_macet,
|
||||
$laporanSlik->kode_kondisi,
|
||||
$laporanSlik->tanggal_kondisi,
|
||||
$laporanSlik->nilai_agunan,
|
||||
$laporanSlik->jenis_agunan,
|
||||
$laporanSlik->kode_agunan,
|
||||
$laporanSlik->peringkat_agunan,
|
||||
$laporanSlik->fasilitas,
|
||||
$laporanSlik->status_agunan,
|
||||
$laporanSlik->tanggal_lapor,
|
||||
$laporanSlik->status,
|
||||
$laporanSlik->created_at->format('d/m/Y H:i'),
|
||||
];
|
||||
}
|
||||
|
||||
public function styles(Worksheet $sheet)
|
||||
{
|
||||
return [
|
||||
1 => ['font' => ['bold' => true]],
|
||||
];
|
||||
}
|
||||
}
|
||||
220
resources/views/laporan-slik/index.blade.php
Normal file
220
resources/views/laporan-slik/index.blade.php
Normal file
@@ -0,0 +1,220 @@
|
||||
@extends('layouts.main')
|
||||
|
||||
@section('breadcrumbs')
|
||||
{{ Breadcrumbs::render('admin-kredit.laporan-slik') }}
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="grid">
|
||||
<div class="min-w-full border card border-agi-100 card-grid" data-datatable="false" data-datatable-page-size="10"
|
||||
data-datatable-state-save="false" id="laporan-slik-table"
|
||||
data-api-url="{{ route('admin-kredit.laporan-slik.datatables') }}">
|
||||
<div class="flex-wrap py-5 card-header bg-agi-50">
|
||||
<h3 class="card-title">
|
||||
Laporan SLIK
|
||||
</h3>
|
||||
<div class="flex flex-wrap gap-2 lg:gap-5">
|
||||
<div class="flex">
|
||||
<label class="input input-sm">
|
||||
<i class="ki-filled ki-magnifier"></i>
|
||||
<input placeholder="Search Laporan SLIK" id="search" type="text" value="">
|
||||
</label>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2.5">
|
||||
<div class="h-[24px] border border-r-gray-200"></div>
|
||||
<a class="btn btn-sm btn-light" href="#" id="export-excel">
|
||||
<i class="ki-filled ki-file-down"></i> Export Excel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="scrollable-x-auto">
|
||||
<table
|
||||
class="table text-sm font-medium text-gray-700 align-middle table-auto table-border min-w-[1200px]"
|
||||
data-datatable-table="true">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-14">
|
||||
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox" />
|
||||
</th>
|
||||
<th class="min-w-[100px]" data-datatable-column="sandi_bank">
|
||||
<span class="sort">
|
||||
<span class="sort-label">Sandi Bank</span>
|
||||
<span class="sort-icon"></span>
|
||||
</span>
|
||||
</th>
|
||||
<th class="min-w-[120px]" data-datatable-column="no_rekening">
|
||||
<span class="sort">
|
||||
<span class="sort-label">No Rekening</span>
|
||||
<span class="sort-icon"></span>
|
||||
</span>
|
||||
</th>
|
||||
<th class="min-w-[120px]" data-datatable-column="baki_debet">
|
||||
<span class="sort">
|
||||
<span class="sort-label">Baki Debet</span>
|
||||
<span class="sort-icon"></span>
|
||||
</span>
|
||||
</th>
|
||||
<th class="min-w-[100px]" data-datatable-column="status">
|
||||
<span class="sort">
|
||||
<span class="sort-label">Status</span>
|
||||
<span class="sort-icon"></span>
|
||||
</span>
|
||||
</th>
|
||||
<th class="min-w-[50px] text-center" data-datatable-column="actions">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
<div
|
||||
class="flex-col gap-3 justify-center font-medium text-gray-600 card-footer md:justify-between md:flex-row text-2sm">
|
||||
<div class="flex gap-2 items-center">
|
||||
Show
|
||||
<select class="w-16 select select-sm" data-datatable-size="true" name="perpage"> </select> per page
|
||||
</div>
|
||||
<div class="flex gap-4 items-center">
|
||||
<span data-datatable-info="true"> </span>
|
||||
<div class="pagination" data-datatable-pagination="true">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('styles')
|
||||
<style>
|
||||
/* Responsive adjustments for table */
|
||||
@media (max-width: 768px) {
|
||||
.table-responsive {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
max-width: 95% !important;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.grid-cols-1.md\:grid-cols-2 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure table is scrollable on small screens */
|
||||
.scrollable-x-auto {
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* Prevent text wrapping in table cells */
|
||||
.table th,
|
||||
.table td {
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Allow wrapping for long text in detail modal */
|
||||
.modal-body .text-gray-900 {
|
||||
word-break: break-word;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
let dataTable;
|
||||
</script>
|
||||
<script type="module">
|
||||
/**
|
||||
* Inisialisasi DataTable untuk Laporan SLIK menggunakan KTDataTable
|
||||
*/
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const element = document.querySelector('#laporan-slik-table');
|
||||
const searchInput = document.getElementById('search');
|
||||
|
||||
const apiUrl = element.getAttribute('data-api-url');
|
||||
|
||||
// Konfigurasi DataTable menggunakan KTDataTable
|
||||
const dataTableOptions = {
|
||||
apiEndpoint: apiUrl,
|
||||
pageSize: 10,
|
||||
columns: {
|
||||
select: {
|
||||
render: (item, data, context) => {
|
||||
const checkbox = document.createElement('input');
|
||||
checkbox.className = 'checkbox checkbox-sm';
|
||||
checkbox.type = 'checkbox';
|
||||
checkbox.value = data.id.toString();
|
||||
checkbox.setAttribute('data-datatable-row-check', 'true');
|
||||
return checkbox.outerHTML.trim();
|
||||
},
|
||||
},
|
||||
sandi_bank: {
|
||||
title: 'Sandi Bank',
|
||||
},
|
||||
no_rekening: {
|
||||
title: 'No Rekening',
|
||||
},
|
||||
baki_debet_formatted: {
|
||||
title: 'Baki Debet',
|
||||
render: (item, data) => {
|
||||
return data.baki_debet_formatted || '-';
|
||||
},
|
||||
},
|
||||
status_badge: {
|
||||
title: 'Status',
|
||||
render: (item, data) => {
|
||||
return data.status_badge || '-';
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
title: 'Aksi',
|
||||
render: (item, data) => {
|
||||
return `
|
||||
<div class="flex gap-2">
|
||||
<button class="btn btn-sm btn-light btn-icon" onclick="showDetail(${data.id})" title="Detail">
|
||||
<i class="ki-filled ki-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Inisialisasi DataTable
|
||||
dataTable = new KTDataTable(element, dataTableOptions);
|
||||
dataTable.showSpinner();
|
||||
|
||||
// Fungsi pencarian
|
||||
searchInput.addEventListener('input', function() {
|
||||
const searchValue = this.value.trim();
|
||||
dataTable.search(searchValue, true);
|
||||
});
|
||||
|
||||
// Export Excel functionality
|
||||
document.getElementById('export-excel').addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Build export URL with current filters
|
||||
const params = new URLSearchParams();
|
||||
if (searchInput.value) params.append('search', searchInput.value);
|
||||
const exportUrl = '{{ route('admin-kredit.laporan-slik.export') }}?' + params.toString();
|
||||
window.open(exportUrl, '_blank');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Fungsi untuk menampilkan detail data Laporan SLIK
|
||||
* @param {number} id - ID data Laporan SLIK yang akan ditampilkan
|
||||
*/
|
||||
function showDetail(id) {
|
||||
// Redirect ke halaman detail
|
||||
window.location.href = `{{ route('admin-kredit.laporan-slik.show', ':id') }}`.replace(':id', id);
|
||||
}
|
||||
</script>
|
||||
@endpush
|
||||
172
resources/views/laporan-slik/show.blade.php
Normal file
172
resources/views/laporan-slik/show.blade.php
Normal file
@@ -0,0 +1,172 @@
|
||||
@extends('layouts.main')
|
||||
|
||||
@section('breadcrumbs')
|
||||
{{ Breadcrumbs::render('admin-kredit.laporan-slik.show', $laporanSlik) }}
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="grid">
|
||||
<div class="w-full">
|
||||
<!-- Header -->
|
||||
<div class="flex flex-wrap gap-4 justify-between items-center mb-6">
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-gray-900">Detail Laporan SLIK</h3>
|
||||
<p class="mt-1 text-sm text-gray-600">Informasi lengkap laporan SLIK {{ $laporanSlik->nama_debitur }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<a href="{{ route('admin-kredit.laporan-slik.index') }}" class="btn btn-sm btn-light">
|
||||
<i class="ki-filled ki-arrow-left"></i>
|
||||
Kembali
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card Detail -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Informasi Laporan SLIK</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="grid grid-cols-1 gap-6 md:grid-cols-2">
|
||||
<!-- Informasi Debitur -->
|
||||
<div class="space-y-4">
|
||||
<h4 class="mb-3 text-base font-semibold text-gray-800">Data Debitur</h4>
|
||||
|
||||
<div class="space-y-3">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">Nama Debitur:</span>
|
||||
<span class="text-sm text-gray-900">{{ $laporanSlik->nama_debitur ?? '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">No. Rekening:</span>
|
||||
<span class="text-sm text-gray-900">{{ $laporanSlik->no_rekening ?? '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">CIF:</span>
|
||||
<span class="text-sm text-gray-900">{{ $laporanSlik->cif ?? '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">NPWP:</span>
|
||||
<span class="text-sm text-gray-900">{{ $laporanSlik->npwp ?? '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">No. KTP:</span>
|
||||
<span class="text-sm text-gray-900">{{ $laporanSlik->no_ktp ?? '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">No. Telp:</span>
|
||||
<span class="text-sm text-gray-900">{{ $laporanSlik->no_telp ?? '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">Alamat:</span>
|
||||
<span class="text-sm text-gray-900">{{ $laporanSlik->alamat ?? '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">Kode Pos:</span>
|
||||
<span class="text-sm text-gray-900">{{ $laporanSlik->kode_pos ?? '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Informasi Fasilitas -->
|
||||
<div class="space-y-4">
|
||||
<h4 class="mb-3 text-base font-semibold text-gray-800">Data Fasilitas</h4>
|
||||
|
||||
<div class="space-y-3">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">Fasilitas:</span>
|
||||
<span class="text-sm text-gray-900">{{ $laporanSlik->fasilitas ?? '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">Kolektibilitas:</span>
|
||||
<span class="text-sm text-gray-900">{{ $laporanSlik->kolektibilitas ?? '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">Jenis Agunan:</span>
|
||||
<span class="text-sm text-gray-900">{{ $laporanSlik->jenis_agunan ?? '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">Nilai Agunan:</span>
|
||||
<span class="text-sm text-gray-900">Rp
|
||||
{{ number_format($laporanSlik->nilai_agunan ?? 0, 0, ',', '.') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">Baki Debet:</span>
|
||||
<span class="text-sm text-gray-900">Rp
|
||||
{{ number_format($laporanSlik->baki_debet ?? 0, 0, ',', '.') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">Sandi Bank:</span>
|
||||
<span class="text-sm text-gray-900">{{ $laporanSlik->sandi_bank ?? '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-600">Status:</span>
|
||||
<span class="text-sm text-gray-900">
|
||||
<span
|
||||
class="badge badge-light-{{ $laporanSlik->status == 'aktif' ? 'success' : 'danger' }}">
|
||||
{{ $laporanSlik->status ?? 'aktif' }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 row">
|
||||
<div class="col-12">
|
||||
<h5 class="mb-3">Detail Lainnya</h5>
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="20%"><strong>Kolektibilitas</strong></td>
|
||||
<td width="5%">:</td>
|
||||
<td>{{ $laporanSlik->kolektibilitas }}</td>
|
||||
<td width="20%"><strong>Tanggal Mulai</strong></td>
|
||||
<td width="5%">:</td>
|
||||
<td>{{ $laporanSlik->tanggal_mulai ?? '-' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Tanggal Jatuh Tempo</strong></td>
|
||||
<td>:</td>
|
||||
<td>{{ $laporanSlik->tanggal_jatuh_tempo ?? '-' }}</td>
|
||||
<td><strong>Tanggal Selesai</strong></td>
|
||||
<td>:</td>
|
||||
<td>{{ $laporanSlik->tanggal_selesai ?? '-' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Jenis Agunan</strong></td>
|
||||
<td>:</td>
|
||||
<td>{{ $laporanSlik->jenis_agunan ?? '-' }}</td>
|
||||
<td><strong>Fasilitas</strong></td>
|
||||
<td>:</td>
|
||||
<td>{{ $laporanSlik->fasilitas ?? '-' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Tanggal Lapor</strong></td>
|
||||
<td>:</td>
|
||||
<td>{{ $laporanSlik->tanggal_lapor ?? '-' }}</td>
|
||||
<td><strong>Tanggal Dibuat</strong></td>
|
||||
<td>:</td>
|
||||
<td>{{ $laporanSlik->created_at->format('d/m/Y H:i') }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
Reference in New Issue
Block a user