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

@@ -43,7 +43,7 @@ class LaporanController extends Controller
'penilai', 'penilai',
'dokumenjaminan', 'dokumenjaminan',
])->find($id); ])->find($id);
if ($permohonan->penilai->type_penilai == 'memo') { if ($permohonan->penilai->type_penilai == 'memo') {
return $this->penilaiController->print_out($request = new Request(['documentId' => $permohonan->penilai->dokument_id, 'jaminanId' => $permohonan->dokumenjaminan[0]->jenis_jaminan_id, 'permohonanId' => $permohonan->id, 'statusLpj' => 1, 'type' => 'memo'])); return $this->penilaiController->print_out($request = new Request(['documentId' => $permohonan->penilai->dokument_id, 'jaminanId' => $permohonan->dokumenjaminan[0]->jenis_jaminan_id, 'permohonanId' => $permohonan->id, 'statusLpj' => 1, 'type' => 'memo']));
} }
@@ -75,7 +75,7 @@ class LaporanController extends Controller
} }
// Retrieve data from the database // Retrieve data from the database
$query = Permohonan::query()->whereIn('status',['proses-laporan','done'])->whereNotNull('approval_so_at')->whereNotNull('approval_eo_at')->where(function ($q) { $query = Permohonan::query()->whereIn('status',['proses-laporan','done', 'paparan', 'proses-paparan'])->whereNotNull('approval_so_at')->whereNotNull('approval_eo_at')->where(function ($q) {
$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]);

View File

@@ -496,7 +496,7 @@ class PenilaiController extends Controller
}); });
} }
$query->whereRaw('LOWER(status) IN (?, ?, ?, ?, ?, ?)', ['assign','survey-completed', 'proses-laporan', 'paparan', 'proses-paparan','paparan']); $query->whereRaw('LOWER(status) IN (?, ?, ?, ?, ?, ?,?)', ['assign','survey-completed', 'proses-laporan', 'paparan', 'proses-paparan','paparan', 'revisi-laporan']);
if (!Auth::user()->hasRole('administrator')) { if (!Auth::user()->hasRole('administrator')) {
$query->whereHas('penilaian.userPenilai', function ($q) { $query->whereHas('penilaian.userPenilai', function ($q) {
@@ -775,20 +775,23 @@ class PenilaiController extends Controller
public function storeResume(Request $request) public function storeResume(Request $request)
{ {
try { try {
// dd($request->all());
$validatedData = $request->validate([ $validatedData = $request->validate([
'permohonan_id' => 'required', 'permohonan_id' => 'required',
'document_id' => 'required', 'dokument_id' => 'required',
'inspeksi_id' => 'required', 'inspeksi_id' => 'required',
'resume' => 'required|array', 'resume' => 'required|array',
'fakta_positif' => 'nullable|array',
'fakta_negatif' => 'nullable|array',
'type' => 'required',
'action' => 'required',
'keterangan' => 'nullable|array'
]); ]);
// Simpan atau update data
Penilai::updateOrCreate( Penilai::updateOrCreate(
[ [
'permohonan_id' => $validatedData['permohonan_id'], 'permohonan_id' => $validatedData['permohonan_id'],
'dokument_id' => $validatedData['document_id'], 'dokument_id' => $validatedData['dokument_id'],
'inspeksi_id' => $validatedData['inspeksi_id'], 'inspeksi_id' => $validatedData['inspeksi_id'],
], ],
[ [
@@ -796,10 +799,51 @@ class PenilaiController extends Controller
] ]
); );
$inspeksi = Inspeksi::where('permohonan_id', $validatedData['permohonan_id'])
->where('dokument_id', $validatedData['dokument_id'])
->first();
if ($inspeksi) {
// Get existing data_form
$existingData = json_decode($inspeksi->data_form, true) ?: [];
// Structure the fakta data correctly
$existingFaktaData = $existingData['fakta'] ?? [];
// Gabungkan data baru dengan data yang sudah ada
$updatedFaktaData = array_merge($existingFaktaData, [
'fakta_positif' => $validatedData['fakta_positif'] ?? $existingFaktaData['fakta_positif'] ?? null,
'fakta_negatif' => $validatedData['fakta_negatif'] ?? $existingFaktaData['fakta_negatif'] ?? null,
'keterangan' => $validatedData['keterangan'] ?? $existingFaktaData['keterangan'] ?? null,
]);
$existingData['fakta'] = $updatedFaktaData;
$inspeksi->update([
'data_form' => json_encode($existingData),
]);
} else {
// If inspeksi
$newData = [
'fakta' => [
'fakta_positif' => $validatedData['fakta_positif'] ?? null,
'fakta_negatif' => $validatedData['fakta_negatif'] ?? null,
'keterangan' => $validatedData['keterangan'] ?? null,
],
];
Inspeksi::create([
'permohonan_id' => $validatedData['permohonan_id'],
'dokument_id' => $validatedData['dokument_id'],
'data_form' => json_encode($newData),
'name' => $validatedData['type']
]);
}
return response()->json([ return response()->json([
'success' => true, 'success' => true,
'message' => 'Berhasil saved resume' 'message' => 'Berhasil saved resume',
], 200); ], 200);
} catch (\Exception $e) { } catch (\Exception $e) {
return response()->json([ return response()->json([
@@ -1332,8 +1376,6 @@ class PenilaiController extends Controller
$validationRules = [ $validationRules = [
'resume' => [ 'resume' => [
'fakta.fakta_positif',
'fakta.fakta_negatif',
'fisik' 'fisik'
], ],
]; ];
@@ -1498,5 +1540,20 @@ class PenilaiController extends Controller
} }
public function revisiSurveyor(Request $request, $id)
{
$permohonan = Permohonan::findOrFail($id);
$permohonan->update([
'status' => 'revisi-survey',
'keterangan' => $request->message,
'submitted_at' => now()
]);
return response()->json([
'success' => true,
'message' => 'Berhasil Revisi Ke surveyor',
], 200);
}
} }

View File

@@ -17,6 +17,7 @@ use Modules\Lpj\Models\StatusPermohonan;
use Modules\Lpj\Models\Teams; use Modules\Lpj\Models\Teams;
use Modules\Lpj\Models\Inspeksi; use Modules\Lpj\Models\Inspeksi;
use Modules\Lpj\Models\Penilai; use Modules\Lpj\Models\Penilai;
use Modules\Lpj\Models\Regions;
use Modules\Location\Models\Province; use Modules\Location\Models\Province;
use Modules\Location\Models\City; use Modules\Location\Models\City;
use Modules\Location\Models\District; use Modules\Location\Models\District;
@@ -26,6 +27,7 @@ use Modules\Lpj\Http\Controllers\SurveyorController;
use Modules\Lpj\Http\Controllers\PenilaiController; use Modules\Lpj\Http\Controllers\PenilaiController;
use Modules\Lpj\Http\Requests\FormSurveyorRequest; use Modules\Lpj\Http\Requests\FormSurveyorRequest;
class PenilaianController extends Controller class PenilaianController extends Controller
{ {
public $user; public $user;
@@ -404,6 +406,8 @@ class PenilaianController extends Controller
'paparan' => 'Paparan' 'paparan' => 'Paparan'
]; ];
$regions = Regions::all();
$header = $headers[$type] ?? 'Pelaporan'; $header = $headers[$type] ?? 'Pelaporan';
switch ($header) { switch ($header) {
@@ -412,7 +416,7 @@ class PenilaianController extends Controller
case 'Paparan': case 'Paparan':
return view('lpj::penilaian.paparan-so', compact('header')); return view('lpj::penilaian.paparan-so', compact('header'));
default: default:
return view('lpj::penilaian.otorisator.index', compact('header')); return view('lpj::penilaian.otorisator.index', compact('header', 'regions'));
} }
} }
@@ -634,6 +638,7 @@ class PenilaianController extends Controller
// Pencarian berdasarkan parameter search // Pencarian berdasarkan parameter search
if ($request->has('search') && !empty($request->get('search'))) { if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search'); $search = $request->get('search');
$query->where(function ($q) use ($search) { $query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%'); $q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%'); $q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
@@ -641,6 +646,7 @@ class PenilaianController extends Controller
$q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%'); $q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%'); $q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%'); $q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('region', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%'); $q->orWhere('status', 'LIKE', '%' . $search . '%');
}); });
} }
@@ -661,13 +667,29 @@ class PenilaianController extends Controller
} }
// Filter berdasarkan region user yang login // Filter berdasarkan region user yang login
if (Auth::user()->hasRole('senior-officer')) { if ($status == 'proses-laporan') {
$query->whereHas('region.teams.teamsUsers', function ($q) { $requestedRegion = $request->get('search');
$q->where('user_id', Auth::id());
}); if ($requestedRegion) {
$query->whereHas('region', function ($q) use ($requestedRegion) {
$q->where('name', $requestedRegion);
});
} else {
$query->whereHas('region.teams.teamsUsers', function ($q) {
$q->where('user_id', Auth::id());
});
}
} else {
if (Auth::user()->hasRole('senior-officer')) {
$query->whereHas('region.teams.teamsUsers', function ($q) {
$q->where('user_id', Auth::id());
});
}
} }
// Sorting berdasarkan sortField dan sortOrder // Sorting berdasarkan sortField dan sortOrder
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) { if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder'); $order = $request->get('sortOrder');

View File

@@ -82,13 +82,17 @@ use Modules\Lpj\Http\Requests\FormSurveyorRequest;
use Modules\Lpj\Emails\SendJadwalKunjunganEmail; use Modules\Lpj\Emails\SendJadwalKunjunganEmail;
use App\Helpers\Lpj; use App\Helpers\Lpj;
use Modules\Lpj\Models\Authorization; use Modules\Lpj\Models\Authorization;
use Modules\Lpj\Services\SurveyorValidateService;
class SurveyorController extends Controller class SurveyorController extends Controller
{ {
public $user; public $user;
public $validateService;
public function __construct(SurveyorValidateService $validateService)
{
$this->validateService = $validateService;
}
public function index() public function index()
{ {
@@ -156,11 +160,12 @@ class SurveyorController extends Controller
/** /**
* Store form inspeksi. * Store form inspeksi.
*/ */
public function store(FormSurveyorRequest $request) public function store(Request $request)
{ {
try { try {
// Validate request data // Validate request data
$validatedData = $request->validated(); $validatedData = $request->all();
// Get action specific rules and process data // Get action specific rules and process data
$processedData = $this->getActionSpecificRules( $processedData = $this->getActionSpecificRules(
@@ -237,6 +242,9 @@ class SurveyorController extends Controller
$rules = []; $rules = [];
$hasAssetDescriptionRules = false; $hasAssetDescriptionRules = false;
$hasFactaData = false; $hasFactaData = false;
$pisah = array_filter( $pisah = array_filter(
explode(',', $action), explode(',', $action),
function ($act) use ($allowedActions) { function ($act) use ($allowedActions) {
@@ -244,20 +252,27 @@ class SurveyorController extends Controller
} }
); );
// dd($pisah);
foreach ($pisah as $act) { foreach ($pisah as $act) {
$act = trim($act); $act = trim($act); // Bersihkan spasi
$method = $allowedActions[$act]; if (isset($allowedActions[$act])) {
$method = $allowedActions[$act];
$actionRules = $this->$method($data, $request); $actionRules = $this->$method($data, $request);
$rules = array_merge($rules, $actionRules); $rules = array_merge($rules, $actionRules);
if (in_array($act, ['apartemen-kantor', 'tanah', 'bangunan', 'rap'])) { // Cek apakah act memerlukan asset description rules
$hasAssetDescriptionRules = true; if (in_array($act, ['apartemen-kantor', 'tanah', 'bangunan', 'rap'])) {
$hasAssetDescriptionRules = true;
}
// Cek apakah act memerlukan fakta data
if (in_array($act, ['rap'])) {
$hasFactaData = true;
}
} }
if (in_array($act, ['rap'])) {
$hasFactaData = true;
}
} }
if ($hasAssetDescriptionRules) { if ($hasAssetDescriptionRules) {
@@ -499,52 +514,57 @@ class SurveyorController extends Controller
$formatFotoData = []; $formatFotoData = [];
$nomor_registrasi = $request->nomor_registrasi; $nomor_registrasi = $request->nomor_registrasi;
// Generate a unique timestamp for this batch // Generate a unique timestamp for this batch
$batchTimestamp = time(); $batchTimestamp = time();
// Create a lookup map of existing file names for faster checking
$existingFileNames = [];
if (isset($formatFotojson[$paramName]) && is_array($formatFotojson[$paramName])) {
foreach ($formatFotojson[$paramName] as $existingFile) {
if (isset($existingFile['name'])) {
$existingFileNames[$existingFile['name']] = true;
}
}
}
foreach ($files as $index => $file) { foreach ($files as $index => $file) {
$originalName = $file->getClientOriginalName(); $originalName = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension(); $extension = $file->getClientOriginalExtension();
$fileNameWithoutExt = pathinfo($originalName, PATHINFO_FILENAME);
// Validasi nama file // Validasi nama file
if (empty($originalName)) { if (empty($fileNameWithoutExt)) {
$originalName = "file_{$batchTimestamp}"; $fileNameWithoutExt = "file_{$batchTimestamp}_{$index}";
} }
// Use batchTimestamp and index to ensure uniqueness // Check if this file name already exists in formatFotojson
if (isset($existingFileNames[$fileNameWithoutExt])) {
// File already exists, skip it
continue;
}
// Use batchTimestamp and index to ensure uniqueness in storage
$uniqueFileName = "{$batchTimestamp}_{$index}.{$extension}"; $uniqueFileName = "{$batchTimestamp}_{$index}.{$extension}";
// Simpan file // Simpan file
$path = $file->storeAs("surveyor/{$paramName}/{$nomor_registrasi}", $uniqueFileName, 'public'); $path = $file->storeAs("surveyor/{$paramName}/{$nomor_registrasi}", $uniqueFileName, 'public');
// Check if this file already exists in formatFotojson // Add file data
$fileExists = false; $fotoData = [
if (isset($formatFotojson[$paramName]) && is_array($formatFotojson[$paramName])) { 'name' => $fileNameWithoutExt,
foreach ($formatFotojson[$paramName] as $existingFile) { 'path' => $path,
// Check if the original file name matches 'category' => 'lainnya',
if (isset($existingFile['name']) && 'sub' => null,
$existingFile['name'] === pathinfo($originalName, PATHINFO_FILENAME)) { 'description' => null,
$fileExists = true; 'created_by' => Auth::user()->name,
break; 'created_at' => now()->toDateTimeString(),
} ];
}
}
// Only add if this file doesn't already exist $formatFotoData[] = $fotoData;
if (!$fileExists) {
$fotoData = [ // Add to the lookup map to prevent duplicates within the same batch
'name' => pathinfo($originalName, PATHINFO_FILENAME), $existingFileNames[$fileNameWithoutExt] = true;
'path' => $path,
'category' => 'lainnya',
'sub' => null,
'description' => null,
'created_by' => Auth::user()->name,
'created_at' => now()->toDateTimeString(),
];
$formatFotoData[] = $fotoData;
}
} }
// Only update if we have new photos to add // Only update if we have new photos to add
@@ -756,6 +776,7 @@ class SurveyorController extends Controller
$buttonStatusCheck = $this->checkButtonStatus($id); $buttonStatusCheck = $this->checkButtonStatus($id);
$buttonStatus = json_decode($buttonStatusCheck->getContent(), true); $buttonStatus = json_decode($buttonStatusCheck->getContent(), true);
// Check if button should be disabled // Check if button should be disabled
if ($buttonStatus['buttonDisable']) { if ($buttonStatus['buttonDisable']) {
return response()->json([ return response()->json([
@@ -764,19 +785,57 @@ class SurveyorController extends Controller
], 422); ], 422);
} }
$inspeksiRecords = Inspeksi::with(['dokument.jenisJaminan'])
->where('permohonan_id', $id)
->get();
$validateConfig = [
'tanah' => 'validateTanah',
'bangunan' => 'validateBangunan',
'lingkungan' => 'validateLingkungan',
'fakta' => 'validateFactData',
'rap' => 'validateRapData',
];
// Ambil data inspeksi
$inspeksiRecords = Inspeksi::with(['dokument.jenisJaminan'])
->where('permohonan_id', $id)
->get();
foreach ($inspeksiRecords as $inspeksi) {
$cekname = $inspeksi->name;
// Pecah nama menjadi array
$names = array_map('trim', explode(',', $cekname));
$dataForm = json_decode($inspeksi->data_form, true);
foreach ($names as $name) {
// Validasi hanya untuk nama yang ada dalam konfigurasi
if (array_key_exists($name, $validateConfig)) {
$validateMethod = $validateConfig[$name];
$invalidFields = $this->validateService->{$validateMethod}($dataForm);
// Jika validasi gagal, kembalikan respons error
if ($invalidFields) {
return response()->json([
'success' => false,
'message' => ucfirst($name) . ' tidak valid: ' . implode(', ', $invalidFields),
], 422);
}
}
}
}
// If validation passes, update permohonan status // If validation passes, update permohonan status
$permohonan = Permohonan::findOrFail($id); $permohonan = Permohonan::findOrFail($id);
$permohonan->update([ $permohonan->update([
'status' => 'survey-completed', 'status' => 'survey-completed',
'submitted_at' => now() 'submitted_at' => now()
]); ]);
return response()->json([ return response()->json([
'success' => true, 'success' => true,
'message' => 'Form surveyor berhasil disubmit' 'message' => 'Form surveyor berhasil disubmit'
@@ -1384,7 +1443,8 @@ class SurveyorController extends Controller
'type' => $request->input('type'), 'type' => $request->input('type'),
'dokument_id' => $request->input('dokument_id'), 'dokument_id' => $request->input('dokument_id'),
'objek_penilaian' => $objekPenilaian, 'objek_penilaian' => $objekPenilaian,
'data_pembanding' => $this->formatDataPembanding($request) 'data_pembanding' => $this->formatDataPembanding($request),
'keterangan' => $request->input('keterangan')
]; ];
@@ -1974,7 +2034,7 @@ class SurveyorController extends Controller
}); });
} }
$query->whereRaw('LOWER(status) IN (?, ?, ?, ?, ?, ? ,?,?)', ['assign', 'survey', 'proses-survey', 'request-reschedule', 'reschedule', 'rejected-reschedule', 'approved-reschedule', 'revisi-laporan' ]); $query->whereRaw('LOWER(status) IN (?, ?, ?, ?, ?, ? ,?,?)', ['assign', 'survey', 'proses-survey', 'request-reschedule', 'reschedule', 'rejected-reschedule', 'approved-reschedule', 'revisi-survey' ]);
if (!Auth::user()->hasRole('administrator')) { if (!Auth::user()->hasRole('administrator')) {
@@ -2295,7 +2355,7 @@ class SurveyorController extends Controller
'province_code' => $data['province_code'] ?? null, 'province_code' => $data['province_code'] ?? null,
]; ];
$alamatKey = ($data['alamat_sesuai'] === 'sesuai') ? 'sesuai' : 'tidak sesuai'; $alamatKey = ($data['alamat_sesuai'] ?? null) === 'sesuai' ? 'sesuai' : 'tidak sesuai';
$alamat = []; $alamat = [];
// Masukkan key baru yang sesuai // Masukkan key baru yang sesuai
@@ -2304,21 +2364,27 @@ class SurveyorController extends Controller
'asset' => [ 'asset' => [
'debitur_perwakilan' => $data['debitur_perwakilan'] ?? [], 'debitur_perwakilan' => $data['debitur_perwakilan'] ?? [],
'jenis_asset' => [ 'jenis_asset' => [
$data['jenis_asset'] => ($data['jenis_asset'] === 'sesuai') $data['jenis_asset'] ?? null => ($data['jenis_asset'] ?? null) === 'sesuai'
? $data['jenis_asset_name'] ? ($data['jenis_asset_name'] ?? null)
: ($data['jenis_asset_tidak_sesuai'] ?? null) : ($data['jenis_asset_tidak_sesuai'] ?? null)
], ],
'alamat' => $alamat, 'alamat' => $alamat,
'hub_cadeb' => [ 'hub_cadeb' => [
$data['hub_cadeb'] => ($data['hub_cadeb'] == 'sesuai') ? $data['hub_cadeb_sesuai'] : $data['hub_cadeb_tidak_sesuai'] $data['hub_cadeb'] ?? null => ($data['hub_cadeb'] ?? null) === 'sesuai'
], ? ($data['hub_cadeb_sesuai'] ?? null)
'hub_cadeb_penghuni' => [ : ($data['hub_cadeb_tidak_sesuai'] ?? null)
$data['hub_cadeb_penghuni'] => ($data['hub_cadeb_penghuni'] == 'sesuai') ? $data['hub_cadeb_penghuni_sesuai'] : $data['hub_penghuni_tidak_sesuai'] ],
], 'hub_cadeb_penghuni' => [
$data['hub_cadeb_penghuni'] ?? null => ($data['hub_cadeb_penghuni'] ?? null) === 'sesuai'
? ($data['hub_cadeb_penghuni_sesuai'] ?? null)
: ($data['hub_penghuni_tidak_sesuai'] ?? null)
],
'pihak_bank' => $data['pihak_bank'] ?? null, 'pihak_bank' => $data['pihak_bank'] ?? null,
'kordinat_lng' => $data['kordinat_lng'] ?? null, 'kordinat_lng' => $data['kordinat_lng'] ?? null,
'kordinat_lat' => $data['kordinat_lat'] ?? null, 'kordinat_lat' => $data['kordinat_lat'] ?? null,
'nomor_nib' => $data['nomor_nib'] ?? null
] ]
]; ];
} }
@@ -2326,16 +2392,22 @@ class SurveyorController extends Controller
private function getTanahData(array $data): array private function getTanahData(array $data): array
{ {
//luas tanah key //luas tanah key
$luas_tanah_key = ($data['luas_tanah'] === 'sesuai') ? 'sesuai' : 'tidak sesuai'; // Luas tanah key
$luas_tanah_key = ($data['luas_tanah'] ?? null) === 'sesuai' ? 'sesuai' : 'tidak sesuai';
$luas_tanah = []; $luas_tanah = [];
$hasil_tanah = $luas_tanah_key === 'sesuai' ? $data['luas_tanah_sesuai'] : $data['luas_tanah_tidak_sesuai']; $hasil_tanah = $luas_tanah_key === 'sesuai'
? ($data['luas_tanah_sesuai'] ?? null)
: ($data['luas_tanah_tidak_sesuai'] ?? null);
$luas_tanah[$luas_tanah_key] = $hasil_tanah; $luas_tanah[$luas_tanah_key] = $hasil_tanah;
// hadap mata angin // Hadap mata angin key
$hadap_mata_angin_key = ($data['hadap_mata_angin'] === 'sesuai') ? 'sesuai' : 'tidak sesuai'; $hadap_mata_angin_key = ($data['hadap_mata_angin'] ?? null) === 'sesuai' ? 'sesuai' : 'tidak sesuai';
$hadap_mata_angin = []; $hadap_mata_angin = [];
$hasil_hadap_mata_angin = $hadap_mata_angin_key === 'sesuai' ? $data['hadap_mata_angin_sesuai'] : $data['hadap_mata_angin_tidak_sesuai']; $hasil_hadap_mata_angin = $hadap_mata_angin_key === 'sesuai'
$hadap_mata_angin[$hadap_mata_angin_key] = $hasil_hadap_mata_angin; ? ($data['hadap_mata_angin_sesuai'] ?? null)
: ($data['hadap_mata_angin_tidak_sesuai'] ?? null);
$hadap_mata_angin[$hadap_mata_angin_key] = $hasil_hadap_mata_angin;
return [ return [
'tanah' => [ 'tanah' => [
@@ -2415,14 +2487,17 @@ class SurveyorController extends Controller
$luas_tanah_bagunan_key = ($data['luas_tanah_bagunan'] === 'sesuai') ? 'sesuai' : 'tidak sesuai'; $luas_tanah_bagunan_key = ($data['luas_tanah_bagunan'] ?? null) === 'sesuai' ? 'sesuai' : 'tidak sesuai';
$luas_tanah_bagunan = []; $luas_tanah_bagunan = [];
$hasil_tanah_bagunan = $luas_tanah_bagunan_key === 'sesuai' ? $data['luas_bangunan_sesuai'] : $data['luas_tanah_bagunan_tidak_sesuai']; $hasil_tanah_bagunan = $luas_tanah_bagunan_key === 'sesuai'
? ($data['luas_bangunan_sesuai'] ?? null)
: ($data['luas_tanah_bagunan_tidak_sesuai'] ?? null);
// Masukkan key baru yang sesuai // Masukkan key baru yang sesuai
$luas_tanah_bagunan[$luas_tanah_bagunan_key] = $hasil_tanah_bagunan; $luas_tanah_bagunan[$luas_tanah_bagunan_key] = $hasil_tanah_bagunan;
return [ return [
'bangunan' => [ 'bangunan' => [
'luas_tanah_bagunan' => $luas_tanah_bagunan, 'luas_tanah_bagunan' => $luas_tanah_bagunan,
@@ -2461,10 +2536,11 @@ class SurveyorController extends Controller
false, false,
'lainnya' 'lainnya'
), ),
'disekitar_lokasi' => $data['disekitar_lokasi'] === 'yes' ? [ 'disekitar_lokasi' => ($data['disekitar_lokasi'] ?? null) === 'yes' ? [
'kondisi' => $data['kondisi_bagunan_disekitar_lokasi'] ?? null, 'kondisi' => $data['kondisi_bagunan_disekitar_lokasi'] ?? null,
'sifat' => $data['sifat_bagunan_disekitar_lokasi'] ?? null, 'sifat' => $data['sifat_bagunan_disekitar_lokasi'] ?? null,
] : $data['disekitar_lokasi'], ] : ($data['disekitar_lokasi'] ?? null),
'kondisi_bagunan_disekitar_lokasi' => $data['kondisi_bagunan_disekitar_lokasi'] ?? null, 'kondisi_bagunan_disekitar_lokasi' => $data['kondisi_bagunan_disekitar_lokasi'] ?? null,
'sifat_bagunan_disekitar_lokasi' => $data['sifat_bagunan_disekitar_lokasi'] ?? null, 'sifat_bagunan_disekitar_lokasi' => $data['sifat_bagunan_disekitar_lokasi'] ?? null,
'dekat_makam' => $data['dekat_makam'] ?? null, 'dekat_makam' => $data['dekat_makam'] ?? null,
@@ -3407,17 +3483,17 @@ class SurveyorController extends Controller
$arr1[$key] = $value; $arr1[$key] = $value;
} }
} }
// Bersihkan key lama yang tidak ada di array baru // Bersihkan key lama yang tidak ada di array baru
foreach ($arr1 as $key => $value) { foreach ($arr1 as $key => $value) {
if (!array_key_exists($key, $arr2) && $key !== 'signature') { if (!array_key_exists($key, $arr2) && $key !== 'signature') {
unset($arr1[$key]); unset($arr1[$key]);
} }
} }
return $arr1; return $arr1;
} }
public function print_out_inspeksi($permohonan_id, $dokument_id, $jenis_jaminan_id) public function print_out_inspeksi($permohonan_id, $dokument_id, $jenis_jaminan_id)

View File

@@ -0,0 +1,392 @@
<?php
namespace Modules\Lpj\Services;
class SurveyorValidateService
{
/**
* Validasi data asset
*
* @param array $assetData
* @return string
*/
public function validateAsset(array $assetData): array
{
$invalidFields = [];
// Validasi data `debitur_perwakilan`
if (empty($assetData['asset']['debitur_perwakilan'])) {
$invalidFields[] = 'debitur perwakilan';
}
// Validasi data `jenis_asset`
$jenisAsset = $assetData['asset']['jenis_asset'] ?? [];
foreach ($jenisAsset as $key => $value) {
if (empty($key) || empty($value)) {
$invalidFields[] = "jenis_asset[$key]";
}
}
// Validasi data `alamat`
$alamat = $assetData['asset']['alamat'] ?? [];
foreach ($alamat as $key => $alamatData) {
if (empty($key)) {
$invalidFields[] = "alamat[$key]";
}
foreach ($alamatData as $field => $value) {
if (empty($value)) {
$invalidFields[] = "alamat[$key][$field]";
}
}
}
// Validasi data `hub_cadeb`
$hubCadeb = $assetData['asset']['hub_cadeb'] ?? [];
foreach ($hubCadeb as $key => $value) {
if (empty($key) || empty($value)) {
$invalidFields[] = "Hubungan cadeb/debitur dengan Pemilik Jaminan";
}
}
// Validasi data `hub_cadeb_penghuni`
$hubCadebPenghuni = $assetData['asset']['hub_cadeb_penghuni'] ?? [];
foreach ($hubCadebPenghuni as $key => $value) {
if (empty($key) || empty($value)) {
$invalidFields[] = "Hubungan Cadeb/Debitur dengan Penghuni Jaminan";
}
}
// Validasi data tambahan lainnya
$fieldsToValidate = [
'pihak_bank',
'kordinat_lng',
'kordinat_lat',
'nomor_nib',
];
foreach ($fieldsToValidate as $field) {
if (empty($assetData['asset'][$field])) {
$invalidFields[] = $field;
}
}
// validasi signature
$signature = [
'penilai',
'cabang',
'debitur',
];
foreach ($signature as $value) {
if (empty($assetData['signature'][$value])) {
$invalidFields[] = 'Tanda tangan' . $value . ' tidak ada';
}
}
// Kembalikan daftar field yang tidak valid
return $invalidFields;
}
public function validateTanah(array $data): array
{
$invalidFields = [];
if (empty($data['tanah']['luas_tanah'])) {
$invalidFields[] = 'luas tanah';
}
if (empty($data['tanah']['hadap_mata_angin'])) {
$invalidFields[] = 'hadap mata angin';
}
// Validasi bentuk tanah
if (empty($data['tanah']['bentuk_tanah'])) {
$invalidFields[] = 'bentuk tanah';
}
// Validasi kontur tanah
if (empty($data['tanah']['kontur_tanah'])) {
$invalidFields[] = 'kontur tanah';
}
// Validasi ketinggian tanah
if (empty($data['tanah']['ketinggian_jalan']) && empty($data['tanah']['ketinggian_lebih_tinggi']) && empty($data['tanah']['ketinggian_lebih_rendah'])) {
$invalidFields[] = 'ketinggian tanah';
}
// Validasi kontur jalan
if (empty($data['tanah']['kontur_jalan'])) {
$invalidFields[] = 'kontur jalan';
}
// Validasi posisi kavling
if (empty($data['tanah']['posisi_kavling'])) {
$invalidFields[] = 'posisi kavling';
}
// Validasi tusuk sate
if (!isset($data['tanah']['tusuk_sate'])) {
$invalidFields[] = 'tusuk sate';
}
// Validasi lockland
if (!isset($data['tanah']['lockland'])) {
$invalidFields[] = 'lockland';
}
// Validasi kondisi fisik tanah
if (empty($data['tanah']['kondisi_fisik_tanah'])) {
$invalidFields[] = 'kondisi fisik tanah';
}
return $invalidFields;
}
public function validateBangunan(array $data): array
{
$invalidFields = [];
// Validasi luas tanah banguna
if (empty($data['bangunan']['luas_tanah_bagunan'])) {
$invalidFields[] = 'luas bangunan';
}
// Validasi jenis bangunan
if (empty($data['bangunan']['jenis_bangunan'])) {
$invalidFields[] = 'jenis bangunan';
}
// Validasi kondisi bangunan
if (empty($data['bangunan']['kondisi_bangunan'])) {
$invalidFields[] = 'kondisi bangunan';
}
// Validasi sifat bangunan
if (empty($data['bangunan']['sifat_bangunan'])) {
$invalidFields[] = 'sifat bangunan';
}
// Validasi sifat bangunan input
if (empty($data['bangunan']['sifat_bangunan_input'])) {
$invalidFields[] = 'sifat bangunan input';
}
// Validasi sarana pelengkap
if (empty($data['bangunan']['sarana_pelengkap'])) {
$invalidFields[] = 'sarana pelengkap';
}
// Validasi sarana pelengkap input
if (empty($data['bangunan']['sarana_pelengkap_input'])) {
$invalidFields[] = 'sarana pelengkap input';
}
return $invalidFields;
}
public function validateLingkungan(array $data): array
{
$invalidFields = [];
// Validasi jarak jalan utama
if (empty($data['lingkungan']['jarak_jalan_utama'])) {
$invalidFields[] = 'jarak jalan utama';
}
// Validasi jalan lingkungan
if (empty($data['lingkungan']['jalan_linkungan'])) {
$invalidFields[] = 'jalan lingkungan';
}
// Validasi jarak CBD point
if (empty($data['lingkungan']['jarak_cbd_point'])) {
$invalidFields[] = 'jarak CBD point';
}
// Validasi nama CBD point
if (empty($data['lingkungan']['nama_cbd_point'])) {
$invalidFields[] = 'nama CBD point';
}
// Validasi lebar perkerasan jalan
if (empty($data['lingkungan']['lebar_perkerasan_jalan'])) {
$invalidFields[] = 'lebar perkerasan jalan';
}
// Validasi perkerasan jalan
if (empty($data['lingkungan']['perkerasan_jalan'])) {
$invalidFields[] = 'perkerasan jalan';
}
// Validasi lalu lintas
if (empty($data['lingkungan']['lalu_lintas'])) {
$invalidFields[] = 'lalu lintas';
}
// Validasi golongan masyarakat sekitar
if (empty($data['lingkungan']['gol_mas_sekitar'])) {
$invalidFields[] = 'golongan masyarakat sekitar';
}
// Validasi tingkat keramaian
if (empty($data['lingkungan']['tingkat_keramaian'])) {
$invalidFields[] = 'tingkat keramaian';
}
// Validasi terletak di area
if (empty($data['lingkungan']['terletak_diarea'])) {
$invalidFields[] = 'terletak di area';
}
// Validasi lokasi sekitar
if (isset($data['lingkungan']['disekitar_lokasi']) && $data['lingkungan']['disekitar_lokasi'] === 'yes') {
if (empty($data['lingkungan']['kondisi_bagunan_disekitar_lokasi'])) {
$invalidFields[] = 'kondisi bangunan di sekitar lokasi';
}
if (empty($data['lingkungan']['sifat_bagunan_disekitar_lokasi'])) {
$invalidFields[] = 'sifat bangunan di sekitar lokasi';
}
}
// Validasi dekat makam
if (isset($data['lingkungan']['dekat_makam']) && $data['lingkungan']['dekat_makam'] === 'yes') {
if (empty($data['lingkungan']['jarak_makam'])) {
$invalidFields[] = 'jarak makam';
}
if (empty($data['lingkungan']['nama_makam'])) {
$invalidFields[] = 'nama makam';
}
}
// Validasi dekat TPS
if (isset($data['lingkungan']['dekat_tps']) && $data['lingkungan']['dekat_tps'] === 'yes') {
if (empty($data['lingkungan']['jarak_tps'])) {
$invalidFields[] = 'jarak TPS';
}
if (empty($data['lingkungan']['nama_tps'])) {
$invalidFields[] = 'nama TPS';
}
}
// Validasi fasilitas dekat object
if (empty($data['lingkungan']['fasilitas_dekat_object'])) {
$invalidFields[] = 'fasilitas dekat object';
}
// Validasi fasilitas dekat object input
if (empty($data['lingkungan']['fasilitas_dekat_object_input'])) {
$invalidFields[] = 'fasilitas dekat object input';
}
return $invalidFields;
}
public function validateFactData(array $data): array
{
$invalidFields = [];
// Validasi fakta_positif dan fakta_negatif
if (empty($data['fakta']['fakta_positif'])) {
$invalidFields[] = 'fakta_positif harus diisi';
}
if (empty($data['fakta']['fakta_negatif'])) {
$invalidFields[] = 'fakta_negatif harus diisi';
}
// Validasi rute_menuju
if (empty($data['fakta']['rute_menuju'])) {
$invalidFields[] = 'rute_menuju harus diisi';
}
// Validasi batas_batas dan batas_batas_input
if (empty($data['fakta']['batas_batas']) && empty($data['fakta']['batas_batas_input'])) {
$invalidFields[] = 'Batas batas';
}
// Validasi kondisi_lingkungan
if (empty($data['fakta']['kondisi_lingkungan'])) {
$invalidFields[] = 'kondisi_lingkungan harus diisi';
}
return $invalidFields;
}
public function validateRapData(array $data): array
{
$invalidFields = [];
// Validasi pengalaman_developer
if (empty($data['pengalaman_developer'])) {
$invalidFields[] = 'Pengalaman developer harus diisi';
}
// Validasi kondisi_perumahan
if (empty($data['kondisi_perumahan'])) {
$invalidFields[] = 'Kondisi perumahan harus diisi';
}
// Validasi progres_pembangunan
if (empty($data['progres_pembangunan'])) {
$invalidFields[] = 'Progres pembangunan harus diisi';
}
// Validasi partisi
if (isset($data['partisi'])) {
foreach ($data['partisi'] as $name => $values) {
if (empty($values['value'])) {
$invalidFields[] = "Partisi '{$name}' harus memiliki nilai";
}
}
}
// Validasi jumlah_unit
if (empty($data['jumlah_unit'])) {
$invalidFields[] = 'Jumlah unit harus diisi';
}
// Validasi batas_batas_perumahan
if (empty($data['batas_batas_perumahan'])) {
$invalidFields[] = 'Batas batas perumahan harus diisi';
}
// Validasi fasus_fasum
if (empty($data['fasus_fasum'])) {
$invalidFields[] = 'Fasus fasum harus diisi';
}
// Validasi harga_unit
if (empty($data['harga_unit'])) {
$invalidFields[] = 'Harga unit harus diisi';
}
// Validasi target_market
if (empty($data['target_market'])) {
$invalidFields[] = 'Target market harus diisi';
}
// Validasi kerjasama_dengan_bank
if (empty($data['kerjasama_dengan_bank'])) {
$invalidFields[] = 'Kerjasama dengan bank harus diisi';
}
// Validasi rute_menuju_lokasi
if (empty($data['rute_menuju_lokasi'])) {
$invalidFields[] = 'Rute menuju lokasi harus diisi';
}
return $invalidFields;
}
}

View File

@@ -662,8 +662,8 @@
</div> </div>
<div class="tambah mb-10" id="tambah-npw" style="margin-bottom: 20px;"> <div class="tambah mb-10" style="margin-bottom: 20px;">
<button type="button" class="btn btn-primary"> <button type="button" id="tambah-npw" class="btn btn-primary">
<i class="ki-filled ki-plus"></i> <i class="ki-filled ki-plus"></i>
Tambah NPW </button> Tambah NPW </button>
</div> </div>
@@ -723,7 +723,7 @@
@if (!empty($lpjData['keterangan_penilai']) && is_array($lpjData['keterangan_penilai'])) @if (!empty($lpjData['keterangan_penilai']) && is_array($lpjData['keterangan_penilai']))
@foreach ($lpjData['keterangan_penilai'] as $index => $item) @foreach ($lpjData['keterangan_penilai'] as $index => $item)
<div class="keterangan_penilai flex items-center gap-2 mt-2 textarea-group w-full"> <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" <button class="btn btn-danger btn-sm remove-btn" type="button"
style="display: none;"> style="display: none;">
<i class="ki-outline ki-trash"></i> <i class="ki-outline ki-trash"></i>
@@ -1000,88 +1000,100 @@
} }
function calculateTotal() { 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 // Function to format currency
let persentaseLikuidasiInput = document.getElementById('likuidasi'); function formatCurrency(value) {
let persentaseLikuidasi = parseInput(persentaseLikuidasiInput.value); // Ensure we have a valid number to format
persentaseLikuidasiInput.value = formatPercentage(persentaseLikuidasiInput.value); const num = parseFloat(value.replace(/[^0-9]/g, '')) || 0;
return num.toLocaleString('id-ID');
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'
}
];
} }
standardInputs.forEach(input => { // Function to format percentage
let luas = parseInput(document.getElementById(input.luas).value); function formatPercentage(value) {
let hargaPerMeter = parseInput(document.querySelector(`input[name="${input.nilai}"]`).value); if (!value) return '';
let totalNilai = luas * hargaPerMeter; const num = parseFloat(value.replace(/[^0-9.]/g, '')) || 0;
return num.toString();
}
document.querySelector(`input[name="${input.output}"]`).value = formatCurrency(totalNilai // Calculate total nilai pasar wajar
.toString()); let totalNilaiPasarWajar = 0;
totalNilaiPasarWajar += totalNilai;
// 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 // Tambahkan perhitungan untuk NPW tambahan
const npwRows = document.querySelectorAll('.npw-row'); const npwRows = document.querySelectorAll('.npw-row');
npwRows.forEach(row => { npwRows.forEach(row => {
let luasNPW = parseInput(row.querySelector('input[id^="luas_npw_"]').value); const luasInput = row.querySelector('input[id^="luas_npw_"]');
let nilaiNPW = parseInput(row.querySelector('input[id^="nilai_npw_"][id$="_1"]').value); const nilaiInput = row.querySelector('input[id^="nilai_npw_"][id$="_1"]');
let totalNilaiNPW = luasNPW * nilaiNPW; const outputElement = row.querySelector('input[id^="nilai_npw_"][id$="_2"]');
row.querySelector('input[id^="nilai_npw_"][id$="_2"]').value = formatCurrency(totalNilaiNPW if (luasInput && nilaiInput && outputElement) {
.toString()); const luas = parseInput(luasInput.value);
totalNilaiPasarWajar += totalNilaiNPW; const nilai = parseInput(nilaiInput.value);
const hasil = luas * nilai;
outputElement.value = formatCurrency(hasil.toString());
totalNilaiPasarWajar += hasil;
}
}); });
// Update total nilai pasar wajar // 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 // Bagian Likuidasi
const hasilLikuidasi = (persentaseLikuidasi / 100) * totalNilaiPasarWajar; const persentaseLikuidasiInput = document.getElementById('likuidasi');
if (persentaseLikuidasiInput) {
let persentaseLikuidasi = parseInput(persentaseLikuidasiInput.value);
persentaseLikuidasiInput.value = formatPercentage(persentaseLikuidasiInput.value);
// Tampilkan nilai likuidasi dan asuransi const totalNilaiPasarLikuidasi = document.querySelector('input[name="likuidasi_nilai_1"]');
totalNilaiPasarLikuidasi.value = formatCurrency(totalNilaiPasarWajar.toString()); const totalLikuidasi = document.querySelector('input[name="likuidasi_nilai_2"]');
totalNilaiAsuransi.value = formatCurrency(hasilAsuransi.toString());
// Total likuidasi (total nilai pasar wajar + nilai likuidasi) if (totalNilaiPasarLikuidasi && totalLikuidasi) {
// const totalPasarWajarDenganLikuidasi = totalNilaiPasarWajar + hasilLikuidasi; totalNilaiPasarLikuidasi.value = formatCurrency(totalNilaiPasarWajar.toString());
totalLikuidasi.value = formatCurrency(hasilLikuidasi.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>Tusuk Sate</td>
<td>:</td> <td>:</td>
<td> <td>
{{ $forminspeksi['tanah']['tusuk_sate'] == 'yes' ? 'Ya' : 'Tidak' }} {{ isset($forminspeksi['tanah']['tusuk_sate']) && $forminspeksi['tanah']['tusuk_sate'] == 'yes' ? 'Ya' : 'Tidak' }}
</td> </td>
</tr> </tr>
<tr> <tr>
<td>Lockland</td> <td>Lockland</td>
<td>:</td> <td>:</td>
<td> <td>
{{ $forminspeksi['tanah']['lockland'] == 'yes' ? 'Ya' : 'Tidak' }} {{ isset($forminspeksi['tanah']['lockland']) && $forminspeksi['tanah']['lockland'] == 'yes' ? 'Ya' : 'Tidak' }}
</td> </td>
</tr> </tr>
<tr> <tr>

View File

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

View File

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

View File

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

View File

@@ -188,6 +188,21 @@
</p> </p>
</div> </div>
</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> </div>
@php @php
$inspeksiId = null; $inspeksiId = null;
@@ -316,7 +331,6 @@
PRINT OUT PRINT OUT
</a> </a>
</div> </div>
</div> </div>
</div> </div>
@endforeach @endforeach
@@ -324,7 +338,14 @@
<a class="btn btn-success" onclick="savePenilai()"> <a class="btn btn-success" onclick="savePenilai()">
REPORT REPORT
</a> </a>
<a class="btn btn-warning" onclick="revisiSurveyor('{{ $permohonan->id }}', '{{$permohonan->debiture->name }}', '{{$permohonan->nomor_registrasi }}')">
REVISI
</a>
</div> </div>
</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> </script>
@include('lpj::surveyor.js.utils') @include('lpj::surveyor.js.utils')

View File

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

View File

@@ -160,10 +160,24 @@
@elseif($dataHeader == 'paparan') @elseif($dataHeader == 'paparan')
@if($permohonan->penilai->file_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 onclick="viewPDF('{{ Storage::url($permohonan->penilai->file_paparan) }}')"><i
class="ki-filled ki-eye mr-2"></i>Lihat Data Paparan</span> class="ki-filled ki-eye mr-2"></i>Lihat Data Paparan</span>
@endif @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) @if(Auth::user()->hasAnyRole(['administrator','senior-officer']) && $authorization->approve_so==null)
<button onclick="otorisatorData({{ $authorization->id }},'SO')" type="button" class="btn btn-primary"> <button onclick="otorisatorData({{ $authorization->id }},'SO')" type="button" class="btn btn-primary">
<i class="ki-filled ki-double-check"></i> <i class="ki-filled ki-double-check"></i>

View File

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

View File

@@ -16,37 +16,57 @@
$dokumentName = null; $dokumentName = null;
@endphp @endphp
<form id="dataPembandingForm" method="POST" enctype="multipart/form-data"> <form id="dataPembandingForm" method="POST" enctype="multipart/form-data" class="grid gap-5">
@csrf @csrf
<input type="hidden" name="permohonan_id" value="{{ $permohonan->id }}"> <input type="hidden" name="permohonan_id" value="{{ $permohonan->id }}">
<input type="hidden" name="type" value="tanah"> <input type="hidden" name="type" value="tanah">
<input type="hidden" name="dokument_id" value="{{ request('dokument') }}"> <input type="hidden" name="dokument_id" value="{{ request('dokument') }}">
<input type="hidden" name="nomor_registrasi" value="{{ $permohonan->nomor_registrasi }}"> <input type="hidden" name="nomor_registrasi" value="{{ $permohonan->nomor_registrasi }}">
<div class="card"> <div class="card">
@foreach ($permohonan->documents as $dokumen) <div class="card-body">
@if ($dokumen->jenisJaminan) @foreach ($permohonan->documents as $dokumen)
@php @if ($dokumen->jenisJaminan)
$dokumentName = $dokumen->jenisJaminan->name; @php
$formKategori = json_decode($dokumen->jenisJaminan->form_kategori, true); $dokumentName = $dokumen->jenisJaminan->name;
@endphp $formKategori = json_decode($dokumen->jenisJaminan->form_kategori, true);
<input type="hidden" name="action" @endphp
value="{{ is_array($formKategori) ? implode(',', $formKategori) : $formKategori }}"> <input type="hidden" name="action"
@if (!in_array(strtoupper($dokumentName), $tanahBangunanTypes)) value="{{ is_array($formKategori) ? implode(',', $formKategori) : $formKategori }}">
@include('lpj::surveyor.components.pembanding-tanah-bangunan-unit') @if (!in_array(strtoupper($dokumentName), $tanahBangunanTypes))
@else @include('lpj::surveyor.components.pembanding-tanah-bangunan-unit')
@include('lpj::surveyor.components.pembanding-kendaraan') @else
@include('lpj::surveyor.components.pembanding-kendaraan')
@endif
@endif @endif
@endif @endforeach
@endforeach </div>
<div class="card-footer"> </div>
<div class="flex justify-end gap-2">
<button type="button" onclick="submitData()" class="btn btn-primary"> <div class="card">
<i class="ki-duotone ki-save-2 fs-2"></i> <div class="card-body ">
Simpan <div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5" style="margin: 20px">
</button> <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>
</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> </form>
</div> </div>
</div> </div>
@@ -125,7 +145,7 @@
} }
} else { } else {
// Format currency untuk input harga // Format currency untuk input harga
if (name.includes('diskon')) { if (name.includes('diskon')) {
element.value = value || '0'; element.value = value || '0';
} else { } else {
element.value = value || ''; element.value = value || '';

View File

@@ -271,264 +271,279 @@
<script> <script>
let jsonDataContoh = @json($formFoto); let jsonDataContoh = @json($formFoto);
Dropzone.autoDiscover = false; Dropzone.autoDiscover = false;
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
let myDropzone = null; let myDropzone = null;
let uploadQueue = 0; let uploadQueue = 0;
let uploadBatch = []; let uploadBatch = [];
function initDropzone(selector, paramName) { function initDropzone(selector, paramName) {
try { try {
const dropzoneElement = document.querySelector(selector); const dropzoneElement = document.querySelector(selector);
if (!dropzoneElement) { if (!dropzoneElement) {
console.error(`Dropzone element not found: ${selector}`); console.error(`Dropzone element not found: ${selector}`);
return null; 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, { // Check if file already exists on server
url: "{{ route('surveyor.storeFoto') }}", if (existingFiles.has(file.name)) {
paramName: paramName, done('File dengan nama ini sudah ada.');
acceptedFiles: 'image/*', return;
uploadMultiple: false, }
parallelUploads: 1,
autoProcessQueue: true,
dictDefaultMessage: 'Seret foto atau klik untuk unggah',
headers: { // Add file to processed set
'X-CSRF-TOKEN': '{{ csrf_token() }}' processedFiles.add(fileId);
}, done();
},
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);
}
addedfiles: function(files) {
const validFiles = Array.from(files).filter(file => {
// Only count files that haven't been rejected
return !file.rejected;
}); });
return myDropzone; uploadQueue += validFiles.length;
} catch (error) { uploadBatch = validFiles;
console.error('Dropzone initialization error:', error);
return null;
}
}
function loadExistingPhotos(dropzone, paramName) { if (validFiles.length > 0) showLoadingOverlay();
showLoadingOverlay(); },
$.ajax({ error: function(file, response) {
url: "{{ route('surveyor.getFoto') }}", // Remove file from processed list on error
method: 'GET', const fileId = file.name + '_' + file.size;
data: { processedFiles.delete(fileId);
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
};
dropzone.emit("addedfile", mockFile); // Format error message
dropzone.emit("thumbnail", mockFile, foto.path); let errorMsg = typeof response === 'string' ? response :
dropzone.emit("complete", mockFile); (response.message || 'Gagal mengupload file');
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 handleUploadComplete(file, isSuccess, errorMessage = null) { handleUploadComplete(file, false, errorMsg);
uploadQueue--; },
const index = uploadBatch.indexOf(file);
if (index > -1) {
uploadBatch.splice(index, 1);
}
// Show individual error if any success: function(file, response) {
if (!isSuccess && errorMessage) { if (response.success) {
showErrorMessage(errorMessage); const fileData = {
} path: response.path || file.path,
name: file.name,
description: '',
category: 'lainnya',
sub: '',
param_name: paramName
};
// If all uploads are complete // Add file to existing files set to prevent duplicates
if (uploadQueue === 0) { existingFiles.add(file.name);
hideLoadingOverlay();
// Show final status message addEditAndDeleteButtons(file, fileData);
const totalFiles = uploadBatch.length + 1; // +1 for current file handleUploadComplete(file, true);
if (totalFiles === 1) {
// Single file upload
if (isSuccess) {
showSuccessMessage('Foto berhasil diupload');
}
} else { } else {
// Multiple files upload handleUploadComplete(file, false, response.message);
showSuccessMessage(`${totalFiles} foto berhasil diupload`);
} }
},
// Reset batch init: function() {
uploadBatch = []; 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() { return myDropzone;
const overlay = document.querySelector('.loading-overlay'); } catch (error) {
if (!overlay) { console.error('Dropzone initialization error:', error);
// Buat elemen overlay return null;
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 function loadExistingPhotos(dropzone, paramName, existingFilesSet) {
loadingOverlay.innerHTML = '<div class="loader"></div>'; showLoadingOverlay();
// Tambahkan overlay ke dalam <body> $.ajax({
document.body.appendChild(loadingOverlay); url: "{{ route('surveyor.getFoto') }}",
} else { method: 'GET',
// Tampilkan overlay jika sudah ada data: {
overlay.style.display = 'flex'; 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); let fotoObjekJaminan = @json($fotoObjekJaminan);

View File

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

View File

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

View File

@@ -22,6 +22,21 @@
@include('lpj::component.detail-jaminan',['backLink'=>'surveyor.index']) @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 border border-agi-100 min-w-full">
<div class="card-header bg-agi-50" id="basic_settings"> <div class="card-header bg-agi-50" id="basic_settings">
<div class="card-title flex flex-row gap-1.5"> <div class="card-title flex flex-row gap-1.5">

View File

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

View File

@@ -616,6 +616,7 @@ Route::middleware(['auth'])->group(function () {
Route::post('storeMemo', [PenilaiController::class, 'storeMemo'])->name('storeMemo'); Route::post('storeMemo', [PenilaiController::class, 'storeMemo'])->name('storeMemo');
Route::post('storeRap', [PenilaiController::class, 'storeRap'])->name('storeRap'); Route::post('storeRap', [PenilaiController::class, 'storeRap'])->name('storeRap');
Route::post('storeLpjSederhanadanStandard', [PenilaiController::class, 'storeLpjSederhanadanStandard'])->name('storeLpjSederhanadanStandard'); Route::post('storeLpjSederhanadanStandard', [PenilaiController::class, 'storeLpjSederhanadanStandard'])->name('storeLpjSederhanadanStandard');
Route::put('revisi-surveyor/{id}', [PenilaiController::class, 'revisiSurveyor'])->name('revisiSurveyor');
}); });