Merge remote-tracking branch 'composer/feature/senior-officer' into staging

# Conflicts:
#	resources/views/component/kertas-kerja.blade.php
This commit is contained in:
Daeng Deni Mardaeni
2024-12-20 15:32:18 +07:00
5 changed files with 132 additions and 195 deletions

View File

@@ -311,8 +311,8 @@ class PenilaiController extends Controller
$data = Inspeksi::where('permohonan_id', $permohonanId)->where('dokument_id', $documentId)->first();
// return view('lpj::component.kertas-kerja', compact('data'));
return Excel::download(new KertasKerjaExport($data), 'kertas-kerja.xlsx');
return view('lpj::component.kertas-kerja', compact('data'));
// return Excel::download(new KertasKerjaExport($data), 'kertas-kerja.xlsx');
}

View File

@@ -478,7 +478,7 @@ class SurveyorController extends Controller
$dataPembanding = json_decode($inspeksi->data_pembanding, true);
// Get jenis jaminan to check if it needs denah
$jenisJaminan = JenisJaminan::find($inspeksi->jenis_jaminan_id);
$jenisJaminan = JenisJaminan::find($inspeksi->dokument_id);
$isTanahBangunan = !in_array(
strtoupper($jenisJaminan->name ?? ''),
['KAPAL', 'PESAWAT', 'KENDARAAN', 'ALAT BERAT']

View File

@@ -470,15 +470,6 @@
$fotoTypes = ['foto_gistaru', 'foto_bhumi', 'foto_argis_region', 'foto_tempat'];
@endphp
@php
$imagePath = $dataform['foto_gistaru'];
@endphp
<img
src="{{ asset('public/' . $imagePath) }}"
alt=""
class="max-w-full h-auto mx-auto"
>
<div class="grid grid-cols-4 gap-4">
@forelse ($fotoTypes as $type)
@@ -487,19 +478,19 @@
$imagePath = $dataform[$type];
@endphp
{{-- @if ($imagePath && Storage::exists($imagePath)) --}}
@if ($imagePath && Storage::exists($imagePath))
<img
src="{{ asset('public/' . $imagePath) }}"
src="{{ asset('storage/' . $imagePath) }}"
alt="{{ $type }}"
class="max-w-full h-auto mx-auto"
onerror="this.src='{{ asset('default-image.png') }}'"
>
<p class="mt-2 text-sm">{{ Str::title(str_replace('_', ' ', $type)) }}</p>
{{-- @else
@else
<div class="bg-gray-200 p-4 text-center">
<p>Tidak ada gambar</p>
</div>
@endif --}}
@endif
</div>
@empty
<p>Tidak ada tipe foto yang tersedia</p>
@@ -536,74 +527,12 @@
<h4 class="mt-6">FOTO OBJEK</h4>
@php
// Fungsi untuk mengumpulkan foto dengan pengecekan yang aman
function collectSafeImages($data, $paths = []) {
if (!is_array($data)) {
return $paths;
}
foreach ($data as $key => $value) {
if (is_array($value)) {
// Jika array memiliki kunci foto
if (isset($value['foto_rute'])) {
$paths[] = $value['foto_rute'];
}
if (isset($value['foto_objek'])) {
$paths[] = $value['foto_objek'];
}
if (isset($value['foto_lingkungan'])) {
$paths[] = $value['foto_lingkungan'];
}
if (isset($value['foto_lantai_unit'])) {
$paths[] = $value['foto_lantai_unit'];
}
// Rekursif untuk nested array
$paths = collectSafeImages($value, $paths);
} elseif (is_string($value) && strpos($value, 'foto_') !== false) {
$paths[] = $value;
}
}
return $paths;
}
// Decode foto form dengan penanganan error
try {
$dataFoto = json_decode($data->foto_form, true) ?? [];
} catch (Exception $e) {
$dataFoto = [];
}
// Kumpulkan foto
$images = collectSafeImages($dataFoto);
// Filter foto yang valid
$validImages = array_filter($images, function($image) {
return $image && Storage::exists($image);
})
@endphp
<div class="grid grid-cols-4 gap-4">
@forelse ($validImages as $image)
<div class="text-center">
<img
src="{{ asset('storage/' . $image) }}"
alt="Foto Survey"
class="w-full h-64 object-cover"
onerror="this.src='{{ asset('default-image.png') }}'"
>
</div>
@empty
<div class="col-span-4 text-center bg-gray-200 p-4">
<p>Tidak ada foto objek yang tersedia</p>
</div>
@endforelse
</div>
</body>
@@ -611,6 +540,8 @@
</html>
<script>
const data = @json($dataFoto);
const data = @json($dataform);
console.log(data);
</script>

View File

@@ -211,7 +211,7 @@
</div>
</div>
<button type="button" class="btn btn-danger btn-sm delete-btn"
onclick="deletePhoto('{{ $index }}')">
id="btnDelete">
<i class="ki-filled ki-trash"></i>
</button>
</div>
@@ -446,7 +446,7 @@
<div class="input-group w-full flex gap-2">
<input id="inputBasement" type="file" name="foto_basement"
class="file-input file-input-bordered w-full" accept="image/*"
capture="camera">
onchange="previewImage(this, 'foto_basement_preview')" capture="camera">
<button type="button" id="btnCamera" class="btn btn-light"
data-modal-toggle="#cameraModal">
<i class="ki-outline ki-abstract-33"></i> Camera
@@ -497,7 +497,9 @@
<div class="input-group w-full flex gap-2">
<input id="inputLingkungan_{{ $key }}" type="file"
name="foto_lingkungan[]" class="file-input file-input-bordered w-full"
accept="image/*" capture="camera">
accept="image/*" capture="camera"
onchange="previewImage(this, 'foto_lingkungan_preview_{{ $key }}')"
>
<button type="button" id="btnCamera" class="btn btn-light"
data-modal-toggle="#cameraModal">
<i class="ki-outline ki-abstract-33"></i> Camera
@@ -520,8 +522,12 @@
</label>
<div class="input-group w-full flex gap-2">
<input type="hidden" name="name_lingkungan[]" value="lingkungan">
<img id="foto_lingkungan_preview_0"
src="{{ isset($formFoto['lingkungan']) ? asset('storage/' . old('lingkungan', $formFoto['lingkungan'])) : '#' }}"
alt="Gambar Lingkungan" style="width: 30rem;" onerror="this.style.display='none';">
<input id="inputLingkungan_0" type="file" name="foto_lingkungan[]"
class="file-input file-input-bordered w-full" accept="image/*" capture="camera">
class="file-input file-input-bordered w-full" accept="image/*" capture="camera"
onchange="previewImage(this, 'foto_lingkungan_preview_0')" >
<button type="button" id="btnCamera" class="btn btn-light"
data-modal-toggle="#cameraModal">
<i class="ki-outline ki-abstract-33"></i> Camera
@@ -559,9 +565,12 @@
<div class="input-group w-full flex gap-2">
<input id="inputPendamping" type="file" name="pendamping"
class="file-input file-input-bordered w-full" accept="image/*" capture="camera">
class="file-input file-input-bordered w-full" accept="image/*"
onchange="previewImage(this, 'pendamping')"
capture="camera">
<button type="button" id="btnCamera" class="btn btn-light"
data-modal-toggle="#cameraModal">
data-modal-toggle="#cameraModal"
>
<i class="ki-outline ki-abstract-33"></i> Camera
</button>
</div>

View File

@@ -71,134 +71,131 @@
function setupInputHandlers(containerId, buttonId, labelText, inputDataClass, buttonDeleteClass) {
const addButton = document.getElementById(buttonId);
const inputContainer = document.getElementById(containerId);
const addButton = document.getElementById(buttonId);
const inputContainer = document.getElementById(containerId);
if (!addButton || !inputContainer) {
console.error(`Element with ID ${containerId} or ${buttonId} not found.`);
return;
}
if (!addButton || !inputContainer) {
console.error(`Element with ID ${containerId} or ${buttonId} not found.`);
return;
}
function updateLabels() {
const labels = inputContainer.querySelectorAll('.form-label span');
labels.forEach((label, index) => {
label.textContent = `${labelText} ${index + 1}`;
});
}
function updateLabels() {
const labels = inputContainer.querySelectorAll('.form-label span');
labels.forEach((label, index) => {
label.textContent = `${labelText} ${index + 1}`;
});
}
function handleDeleteButtons() {
const deleteBtns = inputContainer.querySelectorAll(`.${buttonDeleteClass}`);
deleteBtns.forEach(btn => {
btn.style.display = inputContainer.children.length > 1 ? 'block' : 'none';
});
}
function handleDeleteButtons() {
const deleteBtns = inputContainer.querySelectorAll(`.${buttonDeleteClass}`);
deleteBtns.forEach(btn => {
btn.style.display = inputContainer.children.length > 1 ? 'block' : 'none';
});
}
function createNewInput() {
const newDiv = inputContainer.children[0].cloneNode(true);
function createNewInput() {
const newDiv = inputContainer.children[0].cloneNode(true);
// Reset semua input dalam elemen baru
const inputFile = newDiv.querySelector(`.${inputDataClass}`);
if (inputFile) {
inputFile.id = `inputLingkungan-${inputContainer.children.length}`;
inputFile.value = ''; // Reset input file
// Reset semua input dalam elemen baru
const inputFile = newDiv.querySelector(`.${inputDataClass}`);
const previewContainer = newDiv.querySelector('.preview-container');
const imgPreview = previewContainer.querySelector('img');
// Tambahkan event listener untuk preview
inputFile.addEventListener('change', function() {
const file = this.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
const img = document.getElementById(
`foto_lingkungan_preview_${inputFile.id}`
);
img.src = e.target.result;
img.style.display = 'block';
};
reader.readAsDataURL(file);
}
});
}
if (inputFile) {
// Generate unique ID untuk input dan preview
const uniqueId = `${containerId}-${Date.now()}`;
inputFile.id = `input-${uniqueId}`;
imgPreview.id = `preview-${uniqueId}`;
// Tambahkan logika reset untuk elemen preview
const imgPreview = newDiv.querySelector('img');
if (imgPreview) {
imgPreview.src = '';
imgPreview.style.display = 'none';
}
// Reset input file
inputFile.value = '';
const deleteBtn = newDiv.querySelector(`.${buttonDeleteClass}`);
if (deleteBtn) {
deleteBtn.addEventListener('click', function() {
inputContainer.removeChild(newDiv);
handleDeleteButtons();
updateLabels();
});
}
// Tambahkan container preview jika tidak ada
let previewContainer = newDiv.querySelector('.preview-container');
if (!previewContainer) {
previewContainer = document.createElement('div');
previewContainer.className = 'preview-container';
const img = document.createElement('img');
img.id = `foto_lingkungan_preview_${inputFile.id}`;
img.src = '';
img.className = 'mt-2 h-auto';
img.style.display = 'none';
img.style.width = '30rem';
previewContainer.appendChild(img);
const inputGroup = newDiv.querySelector('.input-group');
inputGroup.appendChild(previewContainer);
}
newDiv.style.marginTop = '10px';
inputContainer.appendChild(newDiv);
updateLabels();
handleDeleteButtons();
}
addButton.addEventListener('click', createNewInput);
// Terapkan event listener pada elemen yang sudah ada
const existingInputs = inputContainer.querySelectorAll(`.${inputDataClass}`);
existingInputs.forEach((input, index) => {
const deleteBtn = input.closest('.flex').querySelector(`.${buttonDeleteClass}`);
if (deleteBtn) {
deleteBtn.addEventListener('click', function() {
if (inputContainer.children.length > 1) {
inputContainer.removeChild(this.closest('.flex'));
handleDeleteButtons();
updateLabels();
}
});
}
input.addEventListener('change', function() {
// Tambahkan event listener untuk preview
inputFile.addEventListener('change', function() {
const file = this.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
const img = document.getElementById(
`foto_lingkungan_preview_${index}`
);
img.src = e.target.result;
img.style.display = 'block';
imgPreview.src = e.target.result;
imgPreview.style.display = 'block';
};
reader.readAsDataURL(file);
}
});
});
}
// Reset preview
imgPreview.src = '';
imgPreview.style.display = 'none';
const deleteBtn = newDiv.querySelector(`.${buttonDeleteClass}`);
if (deleteBtn) {
deleteBtn.addEventListener('click', function() {
inputContainer.removeChild(newDiv);
handleDeleteButtons();
updateLabels();
});
}
newDiv.style.marginTop = '10px';
inputContainer.appendChild(newDiv);
updateLabels();
handleDeleteButtons();
}
setupInputHandlers('inputContainerRute', 'btnRute', 'Foto Rute Menuju Lokasi', 'file-input',
'delete-btn');
setupInputHandlers('inputContainerLantai', 'btnLantai', 'Foto Lantai', 'file-input', 'delete-btn');
setupInputHandlers('inputContainerLingkungan', 'btnLingkungan', 'Lingkungan', 'file-input',
'delete-btn');
// Event listener untuk tombol tambah
addButton.addEventListener('click', createNewInput);
// Inisialisasi preview untuk input yang sudah ada
const existingInputs = inputContainer.querySelectorAll(`.${inputDataClass}`);
existingInputs.forEach((input, index) => {
const previewContainer = input.closest('.flex').querySelector('.preview-container');
const imgPreview = previewContainer.querySelector('img');
input.addEventListener('change', function() {
const file = this.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
imgPreview.src = e.target.result;
imgPreview.style.display = 'block';
};
reader.readAsDataURL(file);
}
});
// Tambahkan event listener untuk tombol hapus
document.querySelectorAll('.delete-btn').forEach(deleteBtn => {
deleteBtn.addEventListener('click', function() {
// Temukan container terdekat yang akan dihapus
const containerToRemove = this.closest('.flex');
const inputContainer = this.closest('#inputContainerRute');
if (inputContainer.querySelectorAll('.flex').length > 1) {
containerToRemove.remove();
// Update nomor label setelah penghapusan
updateLabels(inputContainer);
} else {
// Jika hanya satu input, reset input tersebut
resetInput(containerToRemove);
}
});
});
});
updateLabels();
handleDeleteButtons();
}
setupInputHandlers('inputContainerRute', 'btnRute', 'Foto Rute Menuju Lokasi', 'file-input',
'delete-btn');
setupInputHandlers('inputContainerLantai', 'btnLantai', 'Foto Lantai', 'file-input',
'delete-btn');
setupInputHandlers('inputContainerLingkungan', 'btnLingkungan', 'Lingkungan', 'file-input',
'delete-btn');
});
</script>