fix(suveyor/penilai/so): perbaikan print out, form survey dan laporan dan paparan

This commit is contained in:
majid
2025-02-26 05:07:25 +07:00
parent 2045da36d8
commit 7766d127e0
21 changed files with 1317 additions and 550 deletions

View File

@@ -662,8 +662,8 @@
</div>
<div class="tambah mb-10" id="tambah-npw" style="margin-bottom: 20px;">
<button type="button" class="btn btn-primary">
<div class="tambah mb-10" style="margin-bottom: 20px;">
<button type="button" id="tambah-npw" class="btn btn-primary">
<i class="ki-filled ki-plus"></i>
Tambah NPW </button>
</div>
@@ -723,7 +723,7 @@
@if (!empty($lpjData['keterangan_penilai']) && is_array($lpjData['keterangan_penilai']))
@foreach ($lpjData['keterangan_penilai'] as $index => $item)
<div class="keterangan_penilai flex items-center gap-2 mt-2 textarea-group w-full">
<textarea name="keterangan_penilai[]" class="textarea mt-2 " placeholder="Masukkan catatan penting" rows="10" >{{ old("keterangan_penilai.$index", $item) }}</textarea>
<textarea name="keterangan_penilai[]" class="textarea mt-2 " placeholder="Masukkan catatan penting" rows="10">{{ old("keterangan_penilai.$index", $item) }}</textarea>
<button class="btn btn-danger btn-sm remove-btn" type="button"
style="display: none;">
<i class="ki-outline ki-trash"></i>
@@ -1000,88 +1000,100 @@
}
function calculateTotal() {
const parseInput = (value) => parseFloat(value.replace(/[^0-9]/g, '')) || 0;
const parseInput = (value) => {
if (!value) return 0;
return parseFloat(value.replace(/[^0-9]/g, '')) || 0;
};
// Bagian Likuidasi
let persentaseLikuidasiInput = document.getElementById('likuidasi');
let persentaseLikuidasi = parseInput(persentaseLikuidasiInput.value);
persentaseLikuidasiInput.value = formatPercentage(persentaseLikuidasiInput.value);
let totalNilaiPasarLikuidasi = document.querySelector('input[name="likuidasi_nilai_1"]');
let totalLikuidasi = document.querySelector('input[name="likuidasi_nilai_2"]');
// Bagian Asuransi
let luasBangunanAsuransi = parseInput(document.getElementById('asuransi_luas_bangunan').value);
let hargaPerMeterAsuransi = parseInput(document.querySelector('input[name="asuransi_nilai_1"]').value);
let totalNilaiAsuransi = document.querySelector('input[name="asuransi_nilai_2"]');
// Perhitungan Asuransi
const hasilAsuransi = luasBangunanAsuransi * hargaPerMeterAsuransi;
let totalNilaiPasarWajar = 0;
// Perhitungan untuk input yang sudah ada
const jenisAsetData = @json($jenisAset);
// Menentukan input yang akan dihitung berdasarkan jenis aset
let standardInputs = [];
if (jenisAsetData.toUpperCase() === 'RUKO/RUKAN') {
standardInputs = [{
luas: 'luas_bangunan',
nilai: 'nilai_bangunan_1',
output: 'nilai_bangunan_2'
}];
} else {
standardInputs = [{
luas: 'luas_tanah',
nilai: 'nilai_tanah_1',
output: 'nilai_tanah_2'
},
{
luas: 'luas_bangunan',
nilai: 'nilai_bangunan_1',
output: 'nilai_bangunan_2'
}
];
// Function to format currency
function formatCurrency(value) {
// Ensure we have a valid number to format
const num = parseFloat(value.replace(/[^0-9]/g, '')) || 0;
return num.toLocaleString('id-ID');
}
standardInputs.forEach(input => {
let luas = parseInput(document.getElementById(input.luas).value);
let hargaPerMeter = parseInput(document.querySelector(`input[name="${input.nilai}"]`).value);
let totalNilai = luas * hargaPerMeter;
// Function to format percentage
function formatPercentage(value) {
if (!value) return '';
const num = parseFloat(value.replace(/[^0-9.]/g, '')) || 0;
return num.toString();
}
document.querySelector(`input[name="${input.output}"]`).value = formatCurrency(totalNilai
.toString());
totalNilaiPasarWajar += totalNilai;
// Calculate total nilai pasar wajar
let totalNilaiPasarWajar = 0;
// Get all kategori unik elements dynamically
const kategoriItems = document.querySelectorAll('[id^="luas_"]');
kategoriItems.forEach(item => {
const kategori = item.id.replace('luas_', '');
const luasInput = document.getElementById(`luas_${kategori}`);
const nilaiInput = document.querySelector(`input[name="nilai_${kategori}_1"]`);
const outputElement = document.querySelector(`input[name="nilai_${kategori}_2"]`);
if (luasInput && nilaiInput && outputElement) {
const luas = parseInput(luasInput.value);
const nilai = parseInput(nilaiInput.value);
const hasil = luas * nilai;
outputElement.value = formatCurrency(hasil.toString());
totalNilaiPasarWajar += hasil;
}
});
// Tambahkan perhitungan untuk NPW tambahan
const npwRows = document.querySelectorAll('.npw-row');
npwRows.forEach(row => {
let luasNPW = parseInput(row.querySelector('input[id^="luas_npw_"]').value);
let nilaiNPW = parseInput(row.querySelector('input[id^="nilai_npw_"][id$="_1"]').value);
let totalNilaiNPW = luasNPW * nilaiNPW;
const luasInput = row.querySelector('input[id^="luas_npw_"]');
const nilaiInput = row.querySelector('input[id^="nilai_npw_"][id$="_1"]');
const outputElement = row.querySelector('input[id^="nilai_npw_"][id$="_2"]');
row.querySelector('input[id^="nilai_npw_"][id$="_2"]').value = formatCurrency(totalNilaiNPW
.toString());
totalNilaiPasarWajar += totalNilaiNPW;
if (luasInput && nilaiInput && outputElement) {
const luas = parseInput(luasInput.value);
const nilai = parseInput(nilaiInput.value);
const hasil = luas * nilai;
outputElement.value = formatCurrency(hasil.toString());
totalNilaiPasarWajar += hasil;
}
});
// Update total nilai pasar wajar
document.getElementById('total_nilai_pasar_wajar').value = formatCurrency(totalNilaiPasarWajar.toString());
const totalElement = document.getElementById('total_nilai_pasar_wajar');
if (totalElement) {
totalElement.value = formatCurrency(totalNilaiPasarWajar.toString());
}
// Perhitungan Likuidasi
const hasilLikuidasi = (persentaseLikuidasi / 100) * totalNilaiPasarWajar;
// Bagian Likuidasi
const persentaseLikuidasiInput = document.getElementById('likuidasi');
if (persentaseLikuidasiInput) {
let persentaseLikuidasi = parseInput(persentaseLikuidasiInput.value);
persentaseLikuidasiInput.value = formatPercentage(persentaseLikuidasiInput.value);
// Tampilkan nilai likuidasi dan asuransi
totalNilaiPasarLikuidasi.value = formatCurrency(totalNilaiPasarWajar.toString());
totalNilaiAsuransi.value = formatCurrency(hasilAsuransi.toString());
const totalNilaiPasarLikuidasi = document.querySelector('input[name="likuidasi_nilai_1"]');
const totalLikuidasi = document.querySelector('input[name="likuidasi_nilai_2"]');
// Total likuidasi (total nilai pasar wajar + nilai likuidasi)
// const totalPasarWajarDenganLikuidasi = totalNilaiPasarWajar + hasilLikuidasi;
totalLikuidasi.value = formatCurrency(hasilLikuidasi.toString());
if (totalNilaiPasarLikuidasi && totalLikuidasi) {
totalNilaiPasarLikuidasi.value = formatCurrency(totalNilaiPasarWajar.toString());
// Perhitungan Likuidasi
const hasilLikuidasi = (persentaseLikuidasi / 100) * totalNilaiPasarWajar;
totalLikuidasi.value = formatCurrency(hasilLikuidasi.toString());
}
}
// Bagian Asuransi (jika ada)
const luasBangunanAsuransi = document.getElementById('asuransi_luas_bangunan');
const hargaPerMeterAsuransi = document.querySelector('input[name="asuransi_nilai_1"]');
const totalNilaiAsuransi = document.querySelector('input[name="asuransi_nilai_2"]');
if (luasBangunanAsuransi && hargaPerMeterAsuransi && totalNilaiAsuransi) {
const luas = parseInput(luasBangunanAsuransi.value);
const nilai = parseInput(hargaPerMeterAsuransi.value);
const hasilAsuransi = luas * nilai;
totalNilaiAsuransi.value = formatCurrency(hasilAsuransi.toString());
}
}

View File

@@ -116,14 +116,14 @@
<td>Tusuk Sate</td>
<td>:</td>
<td>
{{ $forminspeksi['tanah']['tusuk_sate'] == 'yes' ? 'Ya' : 'Tidak' }}
{{ isset($forminspeksi['tanah']['tusuk_sate']) && $forminspeksi['tanah']['tusuk_sate'] == 'yes' ? 'Ya' : 'Tidak' }}
</td>
</tr>
<tr>
<td>Lockland</td>
<td>:</td>
<td>
{{ $forminspeksi['tanah']['lockland'] == 'yes' ? 'Ya' : 'Tidak' }}
{{ isset($forminspeksi['tanah']['lockland']) && $forminspeksi['tanah']['lockland'] == 'yes' ? 'Ya' : 'Tidak' }}
</td>
</tr>
<tr>

View File

@@ -178,8 +178,8 @@
</td>
</tr>
<tr>
@isset($resumeData['fakta']['fakta_positif'])
@foreach ($resumeData['fakta']['fakta_positif'] as $key => $item)
@isset($forminspeksi['fakta']['fakta_positif'])
@foreach ($forminspeksi['fakta']['fakta_positif'] as $key => $item)
<tr>
<td>{!! nl2br(e($item)) !!}</td>
</tr>
@@ -195,8 +195,8 @@
</td>
</tr>
<tr>
@isset($resumeData['fakta']['fakta_negatif'])
@foreach ($resumeData['fakta']['fakta_negatif'] as $key => $item)
@isset($forminspeksi['fakta']['fakta_negatif'])
@foreach ($forminspeksi['fakta']['fakta_negatif'] as $key => $item)
<tr>
<td>{!! nl2br(e($item)) !!}</td>
</tr>
@@ -226,13 +226,13 @@
<table border="1" style="width: 100%; border-collapse: collapse; margin-bottom: 10px;">
@foreach ($resumeData['fisik'] as $item)
<tr>
<td style="border: 1px solid #000; padding: 4px; text-align: center">Sertifikat</td>
<td style="border: 1px solid #000; padding: 4px; text-align: center">Luas Tanah</td>
<td style="border: 1px solid #000; padding: 4px; text-align: center">Luas Bangunan</td>
<td style="border: 1px solid #000; padding: 4px; text-align: center">Nilai Pasar Wajar</td>
<tr>
<td style="border: 1px solid #000; padding: 4px; text-align: center">Sertifikat</td>
<td style="border: 1px solid #000; padding: 4px; text-align: center">Luas Tanah</td>
<td style="border: 1px solid #000; padding: 4px; text-align: center">Luas Bangunan</td>
<td style="border: 1px solid #000; padding: 4px; text-align: center">Nilai Pasar Wajar</td>
</tr>
</tr>
<tr>
<td style="border: 1px solid #000; padding: 4px; text-align: center">{{ $item['sertifikat'] ?? '' }}
</td>
@@ -323,9 +323,14 @@
<h6 style="text-transform: uppercase; margin: 0; ">lain lain</h2>
</td>
</tr>
<tr>
<td>{!! nl2br(e($resumeData['keterangan'] ?? '')) !!}</td>
</tr>
@isset($forminspeksi['fakta']['keterangan'])
@foreach ($forminspeksi['fakta']['keterangan'] as $key => $item)
<tr>
<td>{!! nl2br(e($item)) !!}</td>
</tr>
@endforeach
@endisset
</table>
<table style="width: 100%">

View File

@@ -21,9 +21,30 @@
}
</style>
@include('lpj::assetsku.includenya')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
@php
$paparan = $permohonan->status === 'proses-paparan' ? 'Paparan' : 'Pelaporan';
@endphp
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto ">
<form id="formResume" method="POST" class="w-full grid gap-5">
@csrf
@foreach ($permohonan->documents as $dokumen)
@if ($dokumen->jenisJaminan)
@php
$formKategori = json_decode($dokumen->jenisJaminan->form_kategori, true);
$jenisAset = $dokumen->jenisJaminan->name;
@endphp
@if (isset($formKategori) && $formKategori)
@php
$kategoriArray = is_array($formKategori) ? $formKategori : [$formKategori];
$kategoriUnik = array_unique($kategoriArray);
@endphp
<input type="hidden" name="action" value="{{ implode(',', $kategoriUnik) }}">
<input type="hidden" name="type" value="{{ implode(',', $kategoriUnik) }}">
@endif
@endif
@endforeach
<div class="card">
<div class="card-header bg-agi-50">
<h3 class="card-title uppercase">
@@ -36,7 +57,7 @@
@if (Auth::user()->hasAnyRole(['administrator', 'senior-officer', 'EO Appraisal', 'DD Appraisal']) &&
Route::currentRouteName('otorisator.show'))
<a href="{{ route('otorisator.show', ['id' => $permohonan->id, 'type' => 'Pelaporan']) }}"
<a href="{{ route('otorisator.show', ['id' => $permohonan->id, 'type' => $paparan]) }}"
class="btn btn-xs btn-info">
<i class="ki-filled ki-exit-left"></i> Back
</a>
@@ -109,7 +130,7 @@
</div>
</div>
</div>
<div class="card">
<div class="card ">
<div class="card-header bg-agi-50">
<h3 class="card-title uppercase">
faktor
@@ -119,10 +140,10 @@
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">Faktor Positif</label>
<div id="fakta-positif-container" class="flex flex-wrap items-baseline w-full">
@if (!empty($resumeData['fakta']['fakta_positif']))
@foreach ($resumeData['fakta']['fakta_positif'] as $index => $positif)
@if (!empty($forminspeksi['fakta']['fakta_positif']))
@foreach ($forminspeksi['fakta']['fakta_positif'] as $index => $positif)
<div class="fakta_positif flex items-center gap-2 mt-2 textarea-group w-full">
<textarea class="textarea mt-2" name="fakta_positif[]" rows="3">{{ old("fakta_positif.$index", $positif) }}</textarea>
<textarea class="textarea mt-2" name="fakta_positif[]" rows="10">{{ old("fakta_positif.$index", $positif) }}</textarea>
<button class="btn btn-danger btn-sm remove-btn" type="button"
style="display: none;">
<i class="ki-outline ki-trash"></i>
@@ -131,7 +152,7 @@
@endforeach
@else
<div class="fakta_positif flex items-center gap-2 mt-2 textarea-group w-full">
<textarea class="textarea mt-2" name="fakta_positif[]" rows="3">{{ old('fakta_positif.0', '') }}</textarea>
<textarea class="textarea mt-2" name="fakta_positif[]" rows="10">{{ old('fakta_positif.0', '') }}</textarea>
<button class="btn btn-danger btn-sm remove-btn" type="button" style="display: none;">
<i class="ki-outline ki-trash"></i>
</button>
@@ -147,10 +168,10 @@
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">Faktor Negatif</label>
<div id="fakta-negatif-container" class="flex flex-wrap items-baseline w-full">
@if (!empty($resumeData['fakta']['fakta_negatif']))
@foreach ($resumeData['fakta']['fakta_negatif'] as $index => $negatif)
@if (!empty($forminspeksi['fakta']['fakta_negatif']))
@foreach ($forminspeksi['fakta']['fakta_negatif'] as $index => $negatif)
<div class="fakta_negatif flex items-center gap-2 mt-2 textarea-group w-full">
<textarea class="textarea mt-2" name="fakta_negatif[]" rows="3">{{ old("fakta_negatif.$index", $negatif) }}</textarea>
<textarea class="textarea mt-2" name="fakta_negatif[]" rows="10">{{ old("fakta_negatif.$index", $negatif) }}</textarea>
<button class="btn btn-danger btn-sm remove-btn" type="button"
style="display: none;">
<i class="ki-outline ki-trash"></i>
@@ -159,7 +180,7 @@
@endforeach
@else
<div class="fakta_negatif flex items-center gap-2 mt-2 textarea-group w-full">
<textarea class="textarea mt-2" name="fakta_negatif[]" rows="3">{{ old('fakta_negatif.0', $resumeData['fakta']['fakta_negatif'][0] ?? '') }}</textarea>
<textarea class="textarea mt-2" name="fakta_negatif[]" rows="10">{{ old('fakta_negatif.0', $forminspeksi['fakta']['fakta_negatif'][0] ?? '') }}</textarea>
<button class="btn btn-danger btn-sm remove-btn" type="button" style="display: none;">
<i class="ki-outline ki-trash"></i>
</button>
@@ -176,7 +197,7 @@
</div>
<div class="card border border-agi-100 min-w-full">
<div class="card border border-agi-100 min-w-full ">
<div class="card-header bg-agi-50">
<h3 class="card-title uppercase">
KESIMPULAN NILAI PASAR WAJAR
@@ -184,7 +205,7 @@
</div>
<div class="card-body grid gap-5">
<div class="gird gap-5">
<div class="gird gap-5 ">
<label class="form-label max-w-56">SESUAI FISIK</label>
<div class="flex flex-wrap items-baseline w-full mt-5">
<table class="table table-auto table-border align-middle text-gray-700 font-medium text-sm">
@@ -216,7 +237,7 @@
<td class="text-center">
<input type="text" name="fisik_nilai[]"
class="input currency-format nilai-pasar"
value="{{ $item['nilai'] }}" >
value="{{ $item['nilai'] }}">
</td>
</tr>
@@ -266,8 +287,7 @@
class="input number-format" value="{{ $luas_bangunan }}"></td>
<td class="text-center">
<input type="text" name="fisik_nilai[]"
class="input currency-format nilai-pasar"
>
class="input currency-format nilai-pasar">
</td>
</tr>
@@ -277,7 +297,7 @@
</div>
</div>
<div class="gird gap-5">
<div class="gird gap-5 ">
<label class="form-label max-w-56">SESUAI IMB</label>
<div class="flex flex-wrap items-baseline w-full">
@@ -312,7 +332,7 @@
<td class="text-center">
<input type="text" name="sesuai_nilai[]"
class="input currency-format nilai-pasar"
value="{{ $item['nilai'] }}" >
value="{{ $item['nilai'] }}">
</td>
</tr>
@@ -332,8 +352,8 @@
class="input number-format">
</td>
<td class="text-center">
<input type="text" name="sesuai_nilai[]" class="input currency-format"
>
<input type="text" name="sesuai_nilai[]"
class="input currency-format">
</td>
</tr>
@@ -345,7 +365,7 @@
@if (!empty($resumeData['tambahan']))
@foreach ($resumeData['tambahan'] as $counter => $item)
<div id="kesimpulan" class="gird gap-5">
<div id="kesimpulan" class="gird gap-5 ">
<div class="flex flex-wrap items-baseline w-full">
@@ -385,7 +405,7 @@
<td class="text-center">
<input type="text" name="tambahan_nilai[]"
class="input currency-format nilai-pasar"
value="{{ $item['nilai'] }}" >
value="{{ $item['nilai'] }}">
</td>
</tr>
@@ -397,7 +417,7 @@
@endforeach
@endif
<div id="kesimpulan" class="grid gap-5 w-full"></div>
<div>
<div class="">
<button type="button" class="btn btn-primary btn-sm mt-5" onclick="tambahKesimpulanNilai()">
<i class="ki-outline ki-plus"></i>
Kesimpulan Nilai
@@ -406,12 +426,37 @@
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5" style="margin-top: 20px">
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5 " style="margin-top: 20px ">
<label class="form-label lg:form-label max-w-56 ">Catatan yang Perlu Diperhatikan
</label>
<div class="input-group w-full flex gap-2">
<textarea name="keterangan" class="textarea mt-2" placeholder="Masukkan catatan penting" rows="3">{{ old('keterangan', $resumeData['keterangan'] ?? '') }}</textarea>
<div class="w-full">
<div id="keterangan-container" class="flex items-baseline flex-wrap gap-2.5 w-full">
@if (!empty($forminspeksi['fakta']['keterangan']) && is_array($forminspeksi['fakta']['keterangan']))
@foreach ($forminspeksi['fakta']['keterangan'] as $index => $item)
<div class="keterangan flex items-center gap-2 mt-2 textarea-group w-full">
<textarea name="keterangan[]" class="textarea mt-2" placeholder="Masukkan catatan penting" rows="10">{{ old("keterangan.$index", $item) }}</textarea>
<button class="btn btn-danger btn-sm remove-btn" type="button"
style="display: none;">
<i class="ki-outline ki-trash"></i>
</button>
</div>
@endforeach
@else
<div class="keterangan flex items-center gap-2 mt-2 textarea-group w-full">
<textarea name="keterangan[]" class="textarea mt-2" placeholder="Masukkan catatan penting" rows="10"></textarea>
<button class="btn btn-danger btn-sm remove-btn" type="button"
style="display: none;">
<i class="ki-outline ki-trash"></i>
</button>
<em id="error-keterangan" class="alert text-danger text-sm"></em>
</div>
@endif
</div>
<button type="button" onclick="addClonableItem('keterangan-container', 'keterangan')"
class="btn btn-primary btn-sm mt-5 ">
<i class="ki-outline ki-plus"></i>
</button>
</div>
</div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5" style="margin-top: 20px">
@@ -444,9 +489,12 @@
</div>
<div class="flex card-footer justify-end gap-5">
<button type="button" class="btn btn-primary" onclick="saveResume()">
<i class="ki-filled ki-save-2"></i>
Save</button>
@if (Auth::user()->hasAnyRole(['senior-officer', 'EO Appraisal', 'DD Appraisal', 'administrator']))
<a class="btn btn-info"
href="{{ route('penilai.lampiran') }}?permohonanId={{ request('permohonanId') }}&documentId={{ request('documentId') }}&inspeksiId={{ request('inspeksiId') }}&jaminanId={{ request('jaminanId') }}&statusLpj=1">
@@ -570,6 +618,23 @@
const permohonanId = urlParams.get('permohonanId');
const documentId = urlParams.get('documentId');
const inspeksiId = urlParams.get('inspeksiId');
const faktaPositif = Array.from(document.querySelectorAll('[name="fakta_positif[]"]'))
.map(textarea => textarea.value.trim())
.filter(value => value !== '');
const faktaNegatif = Array.from(document.querySelectorAll('[name="fakta_negatif[]"]'))
.map(textarea => textarea.value.trim())
.filter(value => value !== '');
const keterangan = Array.from(document.querySelectorAll('[name="keterangan[]"]'))
.map(textarea => textarea.value.trim())
.filter(value => value !== '');
const action = Array.from(document.querySelectorAll('input[name="action"]'))
.map(input => input.value)
.join(',') || "";
const type = Array.from(document.querySelectorAll('input[name="type"]'))
.map(input => input.value)
.join(',') || "";
const requestUrl =
`{{ route('penilai.storeResume') }}`;
@@ -580,9 +645,15 @@
type: 'POST',
data: JSON.stringify({
permohonan_id: permohonanId,
document_id: documentId,
dokument_id: documentId,
inspeksi_id: inspeksiId,
resume: jsonData,
fakta_positif: faktaPositif,
fakta_negatif: faktaNegatif,
action: action,
type: type,
keterangan: keterangan
}),
contentType: 'application/json',
@@ -634,26 +705,13 @@
const formData = new FormData(formElement);
const jsonData = {
tanggal_resume: "",
fakta: {
fakta_positif: [],
fakta_negatif: []
},
fisik: [],
sesuai_imb: [],
tambahan: [],
keterangan: ""
tambahan: []
};
// Ambil fakta positif
document.querySelectorAll('textarea[name="fakta_positif[]"]').forEach(textarea => {
jsonData.fakta.fakta_positif.push(textarea.value);
});
// Ambil fakta negatif
document.querySelectorAll('textarea[name="fakta_negatif[]"]').forEach(textarea => {
jsonData.fakta.fakta_negatif.push(textarea.value);
});
// Ambil data fisik
document.querySelectorAll('table tbody tr').forEach(row => {
@@ -696,10 +754,6 @@
}
});
// Ambil keterangan
const keterangan = formElement.querySelector('textarea[name="keterangan"]')?.value || "";
jsonData.keterangan = keterangan;
const tanggal_resume = formElement.querySelector('input[name="tanggal_resume"]')?.value || "";
jsonData.tanggal_resume = tanggal_resume;
@@ -719,9 +773,4 @@
}
});
});
</script>

View File

@@ -191,7 +191,7 @@
actions: {
title: 'Action',
render: (item, data) => {
if (data.status === 'survey-completed' || data.status === 'proses-laporan' || data.status === 'paparan' || data.status === 'proses-paparan' || data.status === 'paparan') {
if (data.status === 'survey-completed' || data.status === 'proses-laporan' || data.status === 'paparan' || data.status === 'proses-paparan' || data.status === 'paparan' || data.status == 'revisi-laporan') {
return `
<div class="flex flex-nowrap justify-center gap-1.5">
<a class="btn btn-sm btn-outline btn-info" href="penilai/${data.id}/show">

View File

@@ -188,6 +188,21 @@
</p>
</div>
</div>
@if ($permohonan->status == 'revisi-laporan')
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">
Catatan Revisi
</label>
<div class="flex flex-wrap items-baseline w-full">
<p class="flex w-full text-gray-600 font-medium text-sm">
{{ $permohonan->keterangan ?? '' }}
</p>
</div>
</div>
@endif
</div>
@php
$inspeksiId = null;
@@ -316,7 +331,6 @@
PRINT OUT
</a>
</div>
</div>
</div>
@endforeach
@@ -324,7 +338,14 @@
<a class="btn btn-success" onclick="savePenilai()">
REPORT
</a>
<a class="btn btn-warning" onclick="revisiSurveyor('{{ $permohonan->id }}', '{{$permohonan->debiture->name }}', '{{$permohonan->nomor_registrasi }}')">
REVISI
</a>
</div>
</div>
@@ -626,6 +647,55 @@
});
}
function revisiSurveyor(dataId, debitur, noreg) {
Swal.fire({
title: 'Apakah Anda yakin?',
text: `Untuk melakukan Revisi nomor registrasi ${noreg} atas nama debiture ${debitur} !`,
icon: 'warning',
input: 'textarea',
inputLabel: 'Keterangan',
inputPlaceholder: 'Masukkan keterangan...',
inputAttributes: {
'aria-label': 'Masukkan keterangan'
},
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Ya, Lanjutkan!',
cancelButtonText: 'Batal',
}).then((result) => {
if (result.isConfirmed) {
const userMessage = result.value || '';
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
});
$.ajax({
url: `/penilai/revisi-surveyor/${dataId}`,
type: 'PUT',
data: {
message: userMessage
},
success: (response) => {
Swal.fire('Berhasil!', response.message , 'success').then(
() => {
window.location.href =
'{{ route('penilai.index') }}';
});
console.log(response);
},
error: (error) => {
console.error('Error:', error);
Swal.fire('Gagal!', 'Terjadi kesalahan saat melakukan Revisi.',
'error');
}
});
}
});
}
</script>
@include('lpj::surveyor.js.utils')

View File

@@ -6,35 +6,50 @@
@section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
<div class="card border border-agi-100 pb-2.5">
<div class="min-w-full card-grid" data-datatable="false" data-datatable-page-size="10"
data-datatable-state-save="false" id="permohonan-table"
data-api-url="{{ route('otorisator.datatables', ['otorisator' => $header]) }}">
<div class="flex-wrap py-5 card-header bg-agi-50">
<h3 class="card-title">
Daftar {{ $header }}
</h3>
<div class="flex flex-wrap gap-2 lg:gap-5">
<div class="card border border-agi-100 card-grid min-w-full" data-datatable="false" data-datatable-page-size="10"
data-datatable-state-save="false" id="permohonan-table"
data-api-url="{{ route('otorisator.datatables', ['otorisator' => $header]) }}">
<div class="flex-wrap py-5 card-header bg-agi-50">
<h3 class="card-title">
Daftar {{ $header }}
</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 Penilaian" id="search" type="text" value="">
</label>
</div>
@if ($header == 'Pelaporan')
<div class="flex">
<label class="input input-sm"> <i class="ki-filled ki-magnifier"> </i>
<input placeholder="Search Penilaian" 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="{{ route('permohonan.export') }}"> Export to Excel </a>
<select class="select select-sm w-28" id="region">
<option value="">
Pilih Region
</option>
@foreach ($regions as $region)
<option value="{{ $region->name }}">
{{ $region->name }}
</option>
@endforeach
</select>
</div>
@endif
<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="{{ route('permohonan.export') }}"> Export to 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"
data-datatable-table="true">
<thead>
<div class="card-body">
<div class="scrollable-x-auto">
<table class="table table-auto table-border align-middle text-gray-700 font-medium text-sm"
data-datatable-table="true">
<thead>
<tr>
<th class="w-14">
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox"/>
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox" />
</th>
<th class="min-w-[150px]" data-datatable-column="nomor_registrasi">
<span class="sort"> <span class="sort-label"> Nomor Registrasi </span>
@@ -93,20 +108,19 @@
<th class="min-w-[50px] text-center" data-datatable-column="actions">Action</th>
</tr>
</thead>
</table>
</thead>
</table>
</div>
<div
class="flex-col justify-center gap-3 font-medium text-gray-600 card-footer md:justify-between md:flex-row text-2sm">
<div class="flex items-center gap-2">
Show
<select class="w-16 select select-sm" data-datatable-size="true" name="perpage"> </select> per
page
</div>
<div
class="flex-col justify-center gap-3 font-medium text-gray-600 card-footer md:justify-between md:flex-row text-2sm">
<div class="flex items-center gap-2">
Show
<select class="w-16 select select-sm" data-datatable-size="true" name="perpage"> </select> per
page
</div>
<div class="flex items-center gap-4">
<span data-datatable-info="true"> </span>
<div class="pagination" data-datatable-pagination="true">
</div>
<div class="flex items-center gap-4">
<span data-datatable-info="true"> </span>
<div class="pagination" data-datatable-pagination="true">
</div>
</div>
</div>
@@ -208,7 +222,7 @@
penilai: {
title: 'Penilai',
render: (item, data) => {
if(data.penilaian.user_penilai[0]){
if (data.penilaian.user_penilai[0]) {
console.log(data.penilaian.user_penilai[0]);
return `${data.penilaian.user_penilai[0].user.name} | ${data.penilaian.user_penilai[0].team.name} | ${data.penilaian.user_penilai[0].team.regions.name}`;
}
@@ -219,7 +233,7 @@
jenis_laporan: {
title: 'Jenis laporan',
render: (item, data) => {
if(data.penilai.type_penilai){
if (data.penilai.type_penilai) {
return `<span class="text-md font-bold capitalize">${data.penilai.type_penilai}</span>`;
}
return '';
@@ -240,7 +254,7 @@
approval_so: {
title: 'Approval SO',
render: (item, data) => {
if(data.approve_so) {
if (data.approve_so) {
return `${data.approve_so.name} | ${window.formatTanggalIndonesia(data.approval_so_at)}`;
}
return '';
@@ -249,7 +263,7 @@
approval_eo: {
title: 'Approval EO',
render: (item, data) => {
if(data.approve_eo) {
if (data.approve_eo) {
return `${data.approve_eo.name} | ${window.formatTanggalIndonesia(data.approval_eo_at)}`;
}
return '';
@@ -258,7 +272,7 @@
approval_dd: {
title: 'Approval DD',
render: (item, data) => {
if(data.approve_dd) {
if (data.approve_dd) {
return `${data.approve_dd.name} | ${window.formatTanggalIndonesia(data.approval_dd_at)}`;
}
return '';
@@ -285,11 +299,17 @@
let dataTable = new KTDataTable(element, dataTableOptions);
// Custom search functionality
searchInput.addEventListener('input', function () {
searchInput.addEventListener('input', function() {
const searchValue = this.value.trim();
dataTable.search(searchValue, true);
});
const regionSelect = document.getElementById('region');
regionSelect.addEventListener('change', function() {
const selectedRegion = this.value;
dataTable.search(selectedRegion, true);
});
</script>
<script>
@@ -325,7 +345,9 @@
message: userMessage // Kirim pesan sebagai bagian dari data
},
success: (response) => {
Swal.fire('Berhasil!', 'Data berhasil diotorisasi. Menunggu Approval EO dan atau DD', 'success').then(() => {
Swal.fire('Berhasil!',
'Data berhasil diotorisasi. Menunggu Approval EO dan atau DD',
'success').then(() => {
window.location.reload();
});
console.log(response);

View File

@@ -160,10 +160,24 @@
@elseif($dataHeader == 'paparan')
@if($permohonan->penilai->file_paparan)
<span class="btn btn-success"
<span class="btn btn-success btn-outline"
onclick="viewPDF('{{ Storage::url($permohonan->penilai->file_paparan) }}')"><i
class="ki-filled ki-eye mr-2"></i>Lihat Data Paparan</span>
@endif
@if($permohonan->penilai->kertas_kerja)
<span class="btn btn-warning btn-outline"
onclick="viewPDF('{{ Storage::url($permohonan->penilai->kertas_kerja) }}')"><i
class="ki-filled ki-eye mr-2"></i>Lihat Kertas Kerja</span>
@endif
<a class="btn btn-success"
href="{{ route('otorisator.view-laporan') }}?permohonanId={{ $permohonan->id }}&documentId={{ $documentId }}&inspeksiId={{ $inspeksiId }}&jaminanId={{ $jenisJaminanId }}&statusLpj={{ true }}">
Lihat Laporan
</a>
@if(Auth::user()->hasAnyRole(['administrator','senior-officer']) && $authorization->approve_so==null)
<button onclick="otorisatorData({{ $authorization->id }},'SO')" type="button" class="btn btn-primary">
<i class="ki-filled ki-double-check"></i>

View File

@@ -6,7 +6,7 @@
@section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
<div class="card border border-agi-100 pb-2.5">
<div class="min-w-full card-grid" data-datatable="false" data-datatable-page-size="10"
data-datatable-state-save="false" id="permohonan-table"
data-api-url="{{ route('otorisator.datatables', ['otorisator' => $header]) }}">
@@ -108,7 +108,7 @@
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@@ -16,37 +16,57 @@
$dokumentName = null;
@endphp
<form id="dataPembandingForm" method="POST" enctype="multipart/form-data">
<form id="dataPembandingForm" method="POST" enctype="multipart/form-data" class="grid gap-5">
@csrf
<input type="hidden" name="permohonan_id" value="{{ $permohonan->id }}">
<input type="hidden" name="type" value="tanah">
<input type="hidden" name="dokument_id" value="{{ request('dokument') }}">
<input type="hidden" name="nomor_registrasi" value="{{ $permohonan->nomor_registrasi }}">
<div class="card">
@foreach ($permohonan->documents as $dokumen)
@if ($dokumen->jenisJaminan)
@php
$dokumentName = $dokumen->jenisJaminan->name;
$formKategori = json_decode($dokumen->jenisJaminan->form_kategori, true);
@endphp
<input type="hidden" name="action"
value="{{ is_array($formKategori) ? implode(',', $formKategori) : $formKategori }}">
@if (!in_array(strtoupper($dokumentName), $tanahBangunanTypes))
@include('lpj::surveyor.components.pembanding-tanah-bangunan-unit')
@else
@include('lpj::surveyor.components.pembanding-kendaraan')
<div class="card-body">
@foreach ($permohonan->documents as $dokumen)
@if ($dokumen->jenisJaminan)
@php
$dokumentName = $dokumen->jenisJaminan->name;
$formKategori = json_decode($dokumen->jenisJaminan->form_kategori, true);
@endphp
<input type="hidden" name="action"
value="{{ is_array($formKategori) ? implode(',', $formKategori) : $formKategori }}">
@if (!in_array(strtoupper($dokumentName), $tanahBangunanTypes))
@include('lpj::surveyor.components.pembanding-tanah-bangunan-unit')
@else
@include('lpj::surveyor.components.pembanding-kendaraan')
@endif
@endif
@endif
@endforeach
<div class="card-footer">
<div class="flex justify-end gap-2">
<button type="button" onclick="submitData()" class="btn btn-primary">
<i class="ki-duotone ki-save-2 fs-2"></i>
Simpan
</button>
@endforeach
</div>
</div>
<div class="card">
<div class="card-body ">
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5" style="margin: 20px">
<label class="form-label lg:form-label max-w-56 ">Catatan yang Perlu Diperhatikan
</label>
<div class="w-full">
<div id="keterangan-container" class="flex items-baseline flex-wrap gap-2.5 w-full">
<div class="keterangan flex items-center gap-2 mt-2 textarea-group w-full">
<textarea name="keterangan" class="textarea mt-2" placeholder="Masukkan catatan penting" rows="10">{{ $comparisons['keterangan'] ?? old('keterangan') }}</textarea>
<em id="error-keterangan" class="alert text-danger text-sm"></em>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer">
<div class="flex justify-end gap-2">
<button type="button" onclick="submitData()" class="btn btn-primary">
<i class="ki-duotone ki-save-2 fs-2"></i>
Simpan
</button>
</div>
</div>
</form>
</div>
</div>
@@ -125,7 +145,7 @@
}
} else {
// Format currency untuk input harga
if (name.includes('diskon')) {
if (name.includes('diskon')) {
element.value = value || '0';
} else {
element.value = value || '';

View File

@@ -271,264 +271,279 @@
<script>
let jsonDataContoh = @json($formFoto);
Dropzone.autoDiscover = false;
document.addEventListener('DOMContentLoaded', function() {
let myDropzone = null;
let uploadQueue = 0;
let uploadBatch = [];
document.addEventListener('DOMContentLoaded', function() {
let myDropzone = null;
let uploadQueue = 0;
let uploadBatch = [];
function initDropzone(selector, paramName) {
try {
const dropzoneElement = document.querySelector(selector);
if (!dropzoneElement) {
console.error(`Dropzone element not found: ${selector}`);
return null;
function initDropzone(selector, paramName) {
try {
const dropzoneElement = document.querySelector(selector);
if (!dropzoneElement) {
console.error(`Dropzone element not found: ${selector}`);
return null;
}
const processedFiles = new Set();
// Track files that are already on the server
const existingFiles = new Set();
myDropzone = new Dropzone(selector, {
url: "{{ route('surveyor.storeFoto') }}",
paramName: paramName,
acceptedFiles: 'image/*',
uploadMultiple: false,
parallelUploads: 1,
autoProcessQueue: true,
dictDefaultMessage: 'Seret foto atau klik untuk unggah',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
params: {
permohonan_id: {{ $permohonan->id ?? 0 }},
dokument_id: '{{ request('dokument') ?? '' }}',
param_name: paramName,
nomor_registrasi: '{{ $permohonan->nomor_registrasi ?? '' }}',
},
accept: function(file, done) {
// Generate a unique identifier for the file - use hash or content-based ID if possible
const fileId = file.name + '_' + file.size;
// If file is already being processed, reject it
if (processedFiles.has(fileId)) {
done('File sudah dalam antrian upload.');
return;
}
const processedFiles = new Set();
myDropzone = new Dropzone(selector, {
url: "{{ route('surveyor.storeFoto') }}",
paramName: paramName,
acceptedFiles: 'image/*',
uploadMultiple: false,
parallelUploads: 1,
autoProcessQueue: true,
dictDefaultMessage: 'Seret foto atau klik untuk unggah',
// Check if file already exists on server
if (existingFiles.has(file.name)) {
done('File dengan nama ini sudah ada.');
return;
}
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
params: {
permohonan_id: {{ $permohonan->id ?? 0 }},
dokument_id: '{{ request('dokument') ?? '' }}',
param_name: paramName,
nomor_registrasi: '{{ $permohonan->nomor_registrasi ?? '' }}',
},
accept: function(file, done) {
// Generate a unique identifier for the file
const fileId = file.name + '_' + file.size;
// If file is already being processed, reject it
if (processedFiles.has(fileId)) {
done('File sudah dalam antrian upload.');
return;
}
// Add file to processed set
processedFiles.add(fileId);
done();
},
addedfiles: function(files) {
const validFiles = Array.from(files).filter(file => {
// Generate a unique ID for this file
const fileId = file.name + '_' + file.size;
// Only count files that haven't been rejected
return !file.rejected;
});
uploadQueue += validFiles.length;
uploadBatch = validFiles;
if (validFiles.length > 0) showLoadingOverlay();
},
error: function(file, response) {
// Remove file from processed list on error
const fileId = file.name + '_' + file.size;
processedFiles.delete(fileId);
handleUploadComplete(file, false, response.message);
},
success: function(file, response) {
if (response.success) {
const fileData = {
path: response.path || file.path,
name: file.name,
description: '',
category: 'lainnya',
sub: '',
param_name: paramName
};
addEditAndDeleteButtons(file, fileData);
handleUploadComplete(file, true);
} else {
handleUploadComplete(file, false, response.message);
}
},
init: function() {
const dz = this;
// Clear processed files when all uploads complete
this.on("queuecomplete", function() {
processedFiles.clear();
});
// Load existing photos
loadExistingPhotos(this, paramName);
}
// Add file to processed set
processedFiles.add(fileId);
done();
},
addedfiles: function(files) {
const validFiles = Array.from(files).filter(file => {
// Only count files that haven't been rejected
return !file.rejected;
});
return myDropzone;
} catch (error) {
console.error('Dropzone initialization error:', error);
return null;
}
}
uploadQueue += validFiles.length;
uploadBatch = validFiles;
function loadExistingPhotos(dropzone, paramName) {
showLoadingOverlay();
if (validFiles.length > 0) showLoadingOverlay();
},
$.ajax({
url: "{{ route('surveyor.getFoto') }}",
method: 'GET',
data: {
permohonan_id: {{ $permohonan->id ?? 0 }},
dokument_id: '{{ request('dokument') ?? '' }}',
param_name: paramName
},
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
success: function(response) {
if (response.fotos && response.fotos.length) {
response.fotos.forEach(function(foto) {
var mockFile = {
name: foto.name,
size: foto.size || 12345,
originalPath: foto.path
};
error: function(file, response) {
// Remove file from processed list on error
const fileId = file.name + '_' + file.size;
processedFiles.delete(fileId);
dropzone.emit("addedfile", mockFile);
dropzone.emit("thumbnail", mockFile, foto.path);
dropzone.emit("complete", mockFile);
addEditAndDeleteButtons(mockFile, {
path: foto.path,
name: foto.name,
description: foto.description || '',
category: foto.category || 'lainnya',
sub: foto.sub || '',
param_name: paramName
});
});
}
},
error: function(xhr, status, error) {
console.error('Gagal memuat foto:', error);
showErrorMessage('Gagal memuat foto yang ada');
},
complete: function() {
hideLoadingOverlay();
}
});
}
// Format error message
let errorMsg = typeof response === 'string' ? response :
(response.message || 'Gagal mengupload file');
function handleUploadComplete(file, isSuccess, errorMessage = null) {
uploadQueue--;
const index = uploadBatch.indexOf(file);
if (index > -1) {
uploadBatch.splice(index, 1);
}
handleUploadComplete(file, false, errorMsg);
},
// Show individual error if any
if (!isSuccess && errorMessage) {
showErrorMessage(errorMessage);
}
success: function(file, response) {
if (response.success) {
const fileData = {
path: response.path || file.path,
name: file.name,
description: '',
category: 'lainnya',
sub: '',
param_name: paramName
};
// If all uploads are complete
if (uploadQueue === 0) {
hideLoadingOverlay();
// Add file to existing files set to prevent duplicates
existingFiles.add(file.name);
// Show final status message
const totalFiles = uploadBatch.length + 1; // +1 for current file
if (totalFiles === 1) {
// Single file upload
if (isSuccess) {
showSuccessMessage('Foto berhasil diupload');
}
addEditAndDeleteButtons(file, fileData);
handleUploadComplete(file, true);
} else {
// Multiple files upload
showSuccessMessage(`${totalFiles} foto berhasil diupload`);
handleUploadComplete(file, false, response.message);
}
},
// Reset batch
uploadBatch = [];
init: function() {
const dz = this;
// Clear processed files when all uploads complete
this.on("queuecomplete", function() {
processedFiles.clear();
});
// Load existing photos
loadExistingPhotos(this, paramName, existingFiles);
}
}
});
function showLoadingOverlay() {
const overlay = document.querySelector('.loading-overlay');
if (!overlay) {
// Buat elemen overlay
const loadingOverlay = document.createElement('div');
loadingOverlay.className = 'loading-overlay';
loadingOverlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
`;
return myDropzone;
} catch (error) {
console.error('Dropzone initialization error:', error);
return null;
}
}
// Tambahkan loader di dalam overlay
loadingOverlay.innerHTML = '<div class="loader"></div>';
function loadExistingPhotos(dropzone, paramName, existingFilesSet) {
showLoadingOverlay();
// Tambahkan overlay ke dalam <body>
document.body.appendChild(loadingOverlay);
} else {
// Tampilkan overlay jika sudah ada
overlay.style.display = 'flex';
$.ajax({
url: "{{ route('surveyor.getFoto') }}",
method: 'GET',
data: {
permohonan_id: {{ $permohonan->id ?? 0 }},
dokument_id: '{{ request('dokument') ?? '' }}',
param_name: paramName
},
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
success: function(response) {
if (response.fotos && response.fotos.length) {
response.fotos.forEach(function(foto) {
var mockFile = {
name: foto.name,
size: foto.size || 12345,
originalPath: foto.path
};
// Add to existing files set to prevent duplicates
existingFilesSet.add(foto.name);
dropzone.emit("addedfile", mockFile);
dropzone.emit("thumbnail", mockFile, foto.path);
dropzone.emit("complete", mockFile);
addEditAndDeleteButtons(mockFile, {
path: foto.path,
name: foto.name,
description: foto.description || '',
category: foto.category || 'lainnya',
sub: foto.sub || '',
param_name: paramName
});
});
}
},
error: function(xhr, status, error) {
console.error('Gagal memuat foto:', error);
showErrorMessage('Gagal memuat foto yang ada');
},
complete: function() {
hideLoadingOverlay();
}
function hideLoadingOverlay() {
const overlay = document.querySelector('.loading-overlay');
if (overlay) overlay.style.display = 'none';
}
function showSuccessMessage(message) {
Swal.fire({
icon: 'success',
title: message,
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 1500
});
}
function showErrorMessage(message) {
Swal.fire({
icon: 'error',
title: 'Upload Gagal',
text: message || 'Error tidak diketahui'
});
}
// Inisialisasi Dropzone untuk elemen awal dengan pengecekan
function safeInitDropzone(selector, paramName) {
setTimeout(() => {
const dropzone = initDropzone(selector, paramName);
if (!dropzone) {
console.error(`Failed to initialize Dropzone for ${selector}`);
}
}, 100);
}
// Inisialisasi dropzone untuk elemen awal
safeInitDropzone('#upload-dropzone', 'upload_foto');
});
}
function handleUploadComplete(file, isSuccess, errorMessage = null) {
uploadQueue--;
const index = uploadBatch.indexOf(file);
if (index > -1) {
uploadBatch.splice(index, 1);
}
// Show individual error if any
if (!isSuccess && errorMessage) {
showErrorMessage(errorMessage);
}
// If all uploads are complete
if (uploadQueue === 0) {
hideLoadingOverlay();
// Show final status message
const totalFiles = uploadBatch.length + 1; // +1 for current file
if (totalFiles === 1) {
// Single file upload
if (isSuccess) {
showSuccessMessage('Foto berhasil diupload');
}
} else {
// Multiple files upload
showSuccessMessage(`${totalFiles} foto berhasil diupload`);
}
// Reset batch
uploadBatch = [];
}
}
function showLoadingOverlay() {
const overlay = document.querySelector('.loading-overlay');
if (!overlay) {
// Buat elemen overlay
const loadingOverlay = document.createElement('div');
loadingOverlay.className = 'loading-overlay';
loadingOverlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
`;
// Tambahkan loader di dalam overlay
loadingOverlay.innerHTML = '<div class="loader"></div>';
// Tambahkan overlay ke dalam <body>
document.body.appendChild(loadingOverlay);
} else {
// Tampilkan overlay jika sudah ada
overlay.style.display = 'flex';
}
}
function hideLoadingOverlay() {
const overlay = document.querySelector('.loading-overlay');
if (overlay) overlay.style.display = 'none';
}
function showSuccessMessage(message) {
Swal.fire({
icon: 'success',
title: message,
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 1500
});
}
function showErrorMessage(message) {
Swal.fire({
icon: 'error',
title: 'Upload Gagal',
text: message || 'Error tidak diketahui'
});
}
// Inisialisasi Dropzone untuk elemen awal dengan pengecekan
function safeInitDropzone(selector, paramName) {
setTimeout(() => {
const dropzone = initDropzone(selector, paramName);
if (!dropzone) {
console.error(`Failed to initialize Dropzone for ${selector}`);
}
}, 100);
}
// Inisialisasi dropzone untuk elemen awal
safeInitDropzone('#upload-dropzone', 'upload_foto');
});
let fotoObjekJaminan = @json($fotoObjekJaminan);

View File

@@ -138,18 +138,17 @@
}
@endphp
@if (isset($inspectionData['bangunan']))
<tr>
<td class="px-4 py-2">Luas Bangunan ()</td>
<td class="px-4 py-2">
<input type="text" name="luas_tanah_bagunan" class="input"
value="{{ $inspectionData['bangunan']['luas_tanah_bagunan']['sesuai'] ?? ($inspectionData['bangunan']['luas_tanah_bagunan']['tidak sesuai'] ?? '') }}">
</td>
<td class="px-4 py-2">
<input type="text" name="luas_bangunan_pembanding[]" class="input ">
</td>
</tr>
@endif
<tr>
<td class="px-4 py-2">Luas Bangunan ()</td>
<td class="px-4 py-2">
<input type="text" name="luas_tanah_bagunan" class="input"
value="{{ $inspectionData['bangunan']['luas_tanah_bagunan']['sesuai'] ?? ($inspectionData['bangunan']['luas_tanah_bagunan']['tidak sesuai'] ?? '') }}">
</td>
<td class="px-4 py-2">
<input type="text" name="luas_bangunan_pembanding[]" class="input ">
</td>
</tr>
<!-- Informasi Harga -->

View File

@@ -124,12 +124,12 @@
<td>
<label>
<input type="radio" name="tusuk_sate" value="yes"
{{ $forminspeksi['tanah']['tusuk_sate'] == 'yes' ? 'checked' : '' }}>
{{ isset($forminspeksi['tanah']['tusuk_sate']) && $forminspeksi['tanah']['tusuk_sate'] == 'yes' ? 'Ya' : 'Tidak' }}
Ya
</label>
<label>
<input type="radio" name="tusuk_sate" value="no"
{{ $forminspeksi['tanah']['tusuk_sate'] == 'no' ? 'checked' : '' }}>
{{isset($forminspeksi['tanah']['tusuk_sate']) && $forminspeksi['tanah']['tusuk_sate'] == 'no' ? 'checked' : '' }}>
Tidak
</label>
</td>
@@ -139,12 +139,12 @@
<td>
<label>
<input type="radio" name="lockland" value="yes"
{{ $forminspeksi['tanah']['lockland'] == 'yes' ? 'checked' : '' }}>
{{ isset($forminspeksi['tanah']['lockland']) && $forminspeksi['tanah']['lockland'] == 'yes' ? 'checked' : '' }}>
Ya
</label>
<label>
<input type="radio" name="lockland" value="no"
{{ $forminspeksi['tanah']['lockland'] == 'no' ? 'checked' : '' }}>
{{ isset($forminspeksi['tanah']['lockland']) && $forminspeksi['tanah']['lockland'] == 'no' ? 'checked' : '' }}>
Tidak
</label>
</td>

View File

@@ -22,6 +22,21 @@
@include('lpj::component.detail-jaminan',['backLink'=>'surveyor.index'])
@if ($permohonan->status == 'revisi-survey')
<div class="card border border-agi-100 min-w-full">
<div class="card-header bg-agi-50" id="basic_settings">
<div class="card-title flex flex-row gap-1.5">
Catatan Revisi
</div>
</div>
<div class="card-body">
<p>{{ $permohonan->keterangan ?? '' }}</p>
</div>
</div>
@endif
<div class="card border border-agi-100 min-w-full">
<div class="card-header bg-agi-50" id="basic_settings">
<div class="card-title flex flex-row gap-1.5">

View File

@@ -410,12 +410,10 @@
render: (item, data) => {
let tooltip = '';
if (data.status === 'revisi-laporan') {
if (data.status === 'revisi-laporan' || data.status === 'revisi-survey') {
tooltip = data.keterangan || '';
} else if (data.status === 'reschedule') {
tooltip = data.penilaian?.reschedule_note || '';
} else {
tooltip = '';
}
return `