perbaikan fominspeksi upload foto
This commit is contained in:
@@ -5,7 +5,76 @@
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
@include('lpj::assetsku.includenya')
|
||||
<link rel="stylesheet" href="https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" type="text/css" />
|
||||
<style>
|
||||
.dropzone {
|
||||
border: 2px dashed #3498db;
|
||||
border-radius: 10px;
|
||||
background: #f9f9f9;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.dropzone .dz-message {
|
||||
text-align: center;
|
||||
margin: 50px 0;
|
||||
}
|
||||
|
||||
.dropzone .dz-preview {
|
||||
margin: 10px;
|
||||
width: 17rem;
|
||||
height: 17rem;
|
||||
}
|
||||
|
||||
.dropzone .dz-preview .dz-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
position: static;
|
||||
}
|
||||
|
||||
.dropzone .dz-preview .dz-image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.dropzone .dz-preview .dz-details {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
/* HTML: <div class="loader"></div> */
|
||||
.loader {
|
||||
width: 60px;
|
||||
aspect-ratio: 2;
|
||||
--_g: no-repeat radial-gradient(circle closest-side, #35C1D0 90%, #0000);
|
||||
background:
|
||||
var(--_g) 0% 50%,
|
||||
var(--_g) 50% 50%,
|
||||
var(--_g) 100% 50%;
|
||||
background-size: calc(100%/3) 50%;
|
||||
animation: l3 1s infinite linear;
|
||||
}
|
||||
|
||||
@keyframes l3 {
|
||||
20% {
|
||||
background-position: 0% 0%, 50% 50%, 100% 50%
|
||||
}
|
||||
|
||||
40% {
|
||||
background-position: 0% 100%, 50% 0%, 100% 50%
|
||||
}
|
||||
|
||||
60% {
|
||||
background-position: 0% 50%, 50% 100%, 100% 0%
|
||||
}
|
||||
|
||||
80% {
|
||||
background-position: 0% 50%, 50% 50%, 100% 100%
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
|
||||
<div class="card border border-agi-100 min-w-full">
|
||||
<div class="card border border-agi-100 min-w-full">
|
||||
@@ -78,19 +147,21 @@
|
||||
<input type="hidden" name="permohonan_id" value="{{ $permohonan->id }}">
|
||||
<input type="hidden" name="dokument_id" value="{{ request('dokument') }}">
|
||||
|
||||
|
||||
|
||||
<div class="card border border-agi-100 bg-white rounded-lg shadow-md">
|
||||
<div class="card-body">
|
||||
<div class=" py-4 flex items-center justify-between">
|
||||
<h1 class="text-md font-medium text-gray-900">Rute Menuju Lokasi</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="inputContainerRute" style="margin-top: 10px">
|
||||
|
||||
|
||||
|
||||
<div class="dropzone" id="rute-dropzone">
|
||||
<div class="dz-message" data-foto-type="rute_menuju_lokasi">
|
||||
<span>Seret dan lepas file di sini atau klik untuk unggah</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="inputContainerGerbang" style="margin-top: 10px">
|
||||
<div class="flex items-baseline flex-wrap lg:flex-nowrap w-full gap-4 mb-4">
|
||||
<label class="form-label max-w-56">
|
||||
@@ -104,7 +175,8 @@
|
||||
style="{{ isset($formFoto['foto_gerbang']) ? '' : 'display: none;' }} width: 30rem;">
|
||||
<div class="input-group w-full flex gap-2">
|
||||
<input id="inputRute" type="file" name="foto_gerbang"
|
||||
class="file-input file-input-bordered w-full" accept=".jpg,.jpeg,.png,.gif,.bmp,.tiff,.tif,.webp,.svg"
|
||||
class="file-input file-input-bordered w-full"
|
||||
accept=".jpg,.jpeg,.png,.gif,.bmp,.tiff,.tif,.webp,.svg"
|
||||
onchange="previewImage(this, 'foto_gerbang-preview')">
|
||||
<button type="button" id="btnCamera" class="btn btn-light"
|
||||
data-modal-toggle="#cameraModal">
|
||||
@@ -137,7 +209,8 @@
|
||||
<div class="input-group w-full flex gap-2">
|
||||
<input type="file" name="foto_rute_lainnya[]"
|
||||
class="file-input file-input-bordered w-full"
|
||||
value="{{ $photo['foto_rute_lainnya'] }}" accept=".jpg,.jpeg,.png,.gif,.bmp,.tiff,.tif,.webp,.svg"
|
||||
value="{{ $photo['foto_rute_lainnya'] }}"
|
||||
accept=".jpg,.jpeg,.png,.gif,.bmp,.tiff,.tif,.webp,.svg"
|
||||
onchange="previewImage(this, 'foto_rute_lainnya-preview-{{ $index }}')">
|
||||
<button type="button" id="btnCamera-{{ $index }}"
|
||||
class="btn btn-light" data-modal-toggle="#cameraModal">
|
||||
@@ -156,8 +229,7 @@
|
||||
@endif
|
||||
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary btn-sm" id="btnAddMore"
|
||||
style="margin-top: 10px">
|
||||
<button type="button" class="btn btn-primary btn-sm" id="btnAddMore" style="margin-top: 10px">
|
||||
<i class="ki-outline ki-plus text-2sm"></i> Lainnya
|
||||
</button>
|
||||
|
||||
@@ -251,25 +323,36 @@
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
<div class="flex flex-wrap gap-4 w-full">
|
||||
<div class="w-full">
|
||||
<div class=" py-4 flex items-center justify-between w-full">
|
||||
<label class="form-label">
|
||||
<span class="form-label">Lantai</span>
|
||||
</label>
|
||||
<div id="lantaiContainer" class="mt-2">
|
||||
<!-- Lantai akan dinamis ditambahkan di sini -->
|
||||
<div class="lantai-item mb-4" id="lantai-item-1">
|
||||
|
||||
</div>
|
||||
|
||||
<div id="lantaiContainer" class="w-full">
|
||||
</div>
|
||||
<div class="py-4 flex items-center justify-end w-full">
|
||||
<button type="button" id="btnAddLantai" class="btn btn-primary btn-sm">
|
||||
<i class="ki-filled ki-plus text-lg"></i> Tambah Lantai
|
||||
<div class=" d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">Lantai 1</h5>
|
||||
<input type="hidden" name="lantai_nama[]" value="lantai_1">
|
||||
<button type="button" class="btn btn-danger btn-sm btn-remove-lantai" data-id="1"
|
||||
style="display:none;">
|
||||
<i class="fa fa-trash"></i> Hapus Lantai
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="dropzone" id="dropzone-lantai-1">
|
||||
<div class="dz-message">
|
||||
Seret dan lepas file di sini atau klik untuk unggah
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<button type="button" id="btnAddLantai" class="btn btn-primary">
|
||||
<i class="fa fa-plus"></i> Tambah Lantai
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="inputContainerBasement" class="w-full" style="margin-top: 10px">
|
||||
<div class="flex items-baseline flex-wrap lg:flex-nowrap w-full gap-4">
|
||||
<label class="form-label max-w-56">
|
||||
@@ -283,7 +366,8 @@
|
||||
onchange="previewImage(this, 'foto_basement_preview')">
|
||||
<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=".jpg,.jpeg,.png,.gif,.bmp,.tiff,.tif,.webp,.svg"
|
||||
class="file-input file-input-bordered w-full"
|
||||
accept=".jpg,.jpeg,.png,.gif,.bmp,.tiff,.tif,.webp,.svg"
|
||||
onchange="previewImage(this, 'foto_basement_preview')" capture="camera">
|
||||
<button type="button" id="btnCamera" class="btn btn-light"
|
||||
data-modal-toggle="#cameraModal">
|
||||
@@ -315,11 +399,16 @@
|
||||
<h1 class="text-md font-medium text-gray-900">Lingkungan</h1>
|
||||
</div>
|
||||
|
||||
<div id="inputContainerLingkungan" style="margin-top: 10px">
|
||||
<div class="dropzone" id="lingkungan-dropzone">
|
||||
<div class="dz-message" data-foto-type="foto_lingkungan">
|
||||
<span>Seret dan lepas file di sini atau klik untuk unggah</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="card rounded-lg shadow-md">
|
||||
<div class="card-body">
|
||||
<div class=" py-4 flex items-center justify-between">
|
||||
@@ -336,7 +425,8 @@
|
||||
|
||||
<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=".jpg,.jpeg,.png,.gif,.bmp,.tiff,.tif,.webp,.svg"
|
||||
class="file-input file-input-bordered w-full"
|
||||
accept=".jpg,.jpeg,.png,.gif,.bmp,.tiff,.tif,.webp,.svg"
|
||||
onchange="previewImage(this, 'pendamping')" capture="camera">
|
||||
<button type="button" id="btnCamera" class="btn btn-light"
|
||||
data-modal-toggle="#cameraModal">
|
||||
@@ -372,73 +462,569 @@
|
||||
@include('lpj::surveyor.js.fotojs')
|
||||
@include('lpj::surveyor.js.utils')
|
||||
@push('scripts')
|
||||
<script src="https://unpkg.com/dropzone@5/dist/min/dropzone.min.js"></script>
|
||||
<script>
|
||||
// console.log('@json($formFoto)');
|
||||
let jsonDataContoh = @json($formFoto);
|
||||
Dropzone.autoDiscover = false;
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
function initDropzone(selector, paramName) {
|
||||
try {
|
||||
// Pastikan elemen ada sebelum membuat Dropzone
|
||||
const dropzoneElement = document.querySelector(selector);
|
||||
if (!dropzoneElement) {
|
||||
console.error(`Dropzone element not found: ${selector}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Inisialisasi saat dokumen siap
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Transform and initialize files for each category
|
||||
return new Dropzone(selector, {
|
||||
url: "{{ route('surveyor.storeFoto') }}",
|
||||
paramName: paramName,
|
||||
maxFilesize: 5,
|
||||
acceptedFiles: 'image/*',
|
||||
uploadMultiple: false,
|
||||
parallelUploads: 1,
|
||||
maxFiles: 5,
|
||||
addRemoveLinks: true,
|
||||
autoProcessQueue: true,
|
||||
dictRemoveFile: 'Hapus',
|
||||
dictDefaultMessage: 'Seret foto atau klik untuk unggah',
|
||||
|
||||
// Foto Lantai Unit
|
||||
const existingFilesLantai = @json($formFoto['foto_lantai_unit'] ?? []);
|
||||
const processedFilesLantai = Object.entries(existingFilesLantai || {}).flatMap(([lantaiIndex, files]) =>
|
||||
files.map(file => ({
|
||||
...file,
|
||||
item: lantaiIndex,
|
||||
url: file.path ? `/storage/${file.path}` : null
|
||||
}))
|
||||
);
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
},
|
||||
|
||||
const lantaiUploader = new DynamicFileUploader({
|
||||
containerId: 'lantaiContainer',
|
||||
addButtonId: 'btnAddLantai',
|
||||
name: 'Lantai',
|
||||
fileInputName: 'foto_lantai_unit',
|
||||
existingFiles: processedFilesLantai,
|
||||
maxFiles: 10,
|
||||
accept: 'image/*',
|
||||
});
|
||||
params: {
|
||||
permohonan_id: {{ $permohonan->id ?? 0 }},
|
||||
dokument_id: '{{ request('dokument') ?? '' }}',
|
||||
param_name: paramName
|
||||
},
|
||||
|
||||
// Foto Lingkungan
|
||||
const existingFilesLingkungan = @json($formFoto['foto_lingkungan']['foto_lingkungan'] ?? []);
|
||||
const processedFilesLingkungan = existingFilesLingkungan.flatMap(files =>
|
||||
files.map(file => ({
|
||||
...file,
|
||||
url: file.path ? `/storage/${file.path}` : null
|
||||
}))
|
||||
);
|
||||
error: function(file, response) {
|
||||
console.error('Upload error:', response);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Upload Gagal',
|
||||
text: response.message || 'Error tidak diketahui'
|
||||
});
|
||||
},
|
||||
|
||||
const lingkunganUploader = new DynamicFileUploader({
|
||||
containerId: 'inputContainerLingkungan',
|
||||
fileInputName: 'foto_lingkungan',
|
||||
success: function(file, response) {
|
||||
if (response.success) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Upload Berhasil',
|
||||
toast: true,
|
||||
position: 'top-end',
|
||||
showConfirmButton: false,
|
||||
timer: 1500
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
existingFiles: processedFilesLingkungan,
|
||||
maxFiles: 10,
|
||||
accept: 'image/*',
|
||||
});
|
||||
removedfile: function(file) {
|
||||
if (file.originalPath) {
|
||||
$.ajax({
|
||||
url: "{{ route('surveyor.hapusFoto') }}",
|
||||
method: 'DELETE',
|
||||
data: {
|
||||
path: file.originalPath,
|
||||
permohonan_id: {{ $permohonan->id ?? 0 }},
|
||||
dokument_id: '{{ request('dokument') ?? '' }}',
|
||||
param_name: paramName
|
||||
},
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
},
|
||||
success: function(file, response) {
|
||||
if (response.success) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Hapus Foto Berhasil',
|
||||
toast: true,
|
||||
position: 'top-end',
|
||||
showConfirmButton: false,
|
||||
timer: 1500
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (file.previewElement) {
|
||||
file.previewElement.remove();
|
||||
}
|
||||
},
|
||||
|
||||
init: function() {
|
||||
var myDropzone = this;
|
||||
|
||||
var loadingIndicator = $(`
|
||||
<div class="loading-overlay" style="
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255,255,255,0.7);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
">
|
||||
<div class="loader"></div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
var $dropzoneElement = $(selector);
|
||||
$dropzoneElement.css('position', 'relative');
|
||||
$dropzoneElement.append(loadingIndicator);
|
||||
|
||||
$.ajax({
|
||||
url: "{{ route('surveyor.getFoto') }}",
|
||||
method: 'GET',
|
||||
data: {
|
||||
permohonan_id: {{ $permohonan->id ?? 0 }},
|
||||
dokument_id: '{{ request('dokument') ?? '' }}',
|
||||
param_name: paramName
|
||||
},
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
},
|
||||
beforeSend: function() {
|
||||
// Pastikan loading indicator terlihat
|
||||
loadingIndicator.show();
|
||||
},
|
||||
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
|
||||
};
|
||||
|
||||
myDropzone.emit("addedfile", mockFile);
|
||||
myDropzone.emit("thumbnail", mockFile,
|
||||
foto.path);
|
||||
myDropzone.emit("complete", mockFile);
|
||||
});
|
||||
} else {
|
||||
// Tambahkan pesan jika tidak ada foto
|
||||
console.log('Tidak ada foto yang ditemukan');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Gagal memuat foto:', error);
|
||||
|
||||
// Tampilkan pesan error
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Gagal Memuat Foto',
|
||||
text: 'Terjadi kesalahan saat mengambil foto. Silakan coba lagi.',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
},
|
||||
complete: function() {
|
||||
// Sembunyikan loading indicator
|
||||
loadingIndicator.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Dropzone initialization error:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 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('#rute-dropzone', 'rute_menuju_lokasi');
|
||||
safeInitDropzone('#lingkungan-dropzone', 'foto_lingkungan');
|
||||
|
||||
// Event listener untuk menambah lantai
|
||||
|
||||
});
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Rute Menuju Lokasi
|
||||
const existingFilesRute = @json($formFoto['rute_menuju_lokasi']['rute_menuju_lokasi'] ?? []);
|
||||
const processedFilesRute = existingFilesRute.flatMap(files =>
|
||||
files.map(file => ({
|
||||
...file,
|
||||
url: file.path ? `/storage/${file.path}` : null
|
||||
}))
|
||||
);
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const lantaiContainer = document.getElementById('lantaiContainer');
|
||||
const btnAddLantai = document.getElementById('btnAddLantai');
|
||||
let lantaiCounter = 1;
|
||||
let fotoLantaiUnit = {}; // Objek untuk menyimpan foto per lantai
|
||||
|
||||
const ruteUploader = new DynamicFileUploader({
|
||||
containerId: 'inputContainerRute',
|
||||
fileInputName: 'rute_menuju_lokasi',
|
||||
existingFiles: processedFilesRute,
|
||||
maxFiles: 10,
|
||||
accept: 'image/*',
|
||||
// Objek untuk menyimpan instance Dropzone
|
||||
const dropzoneInstances = {};
|
||||
|
||||
// Fungsi untuk memuat foto berdasarkan JSON
|
||||
function loadFotoFromJSON(jsonData) {
|
||||
if (jsonData && jsonData.foto_lantai_unit) {
|
||||
fotoLantaiUnit = jsonData.foto_lantai_unit;
|
||||
|
||||
// Render foto untuk setiap lantai
|
||||
Object.keys(fotoLantaiUnit).forEach(lantai => {
|
||||
// Pastikan dropzone untuk lantai ini sudah dibuat
|
||||
if (!dropzoneInstances[lantai]) {
|
||||
// Jika belum ada, tambahkan lantai baru
|
||||
while (lantaiCounter < lantai) {
|
||||
const newLantaiElement = createLantaiElement();
|
||||
lantaiContainer.appendChild(newLantaiElement);
|
||||
initDropzonelantai(lantaiCounter);
|
||||
}
|
||||
}
|
||||
|
||||
const dropzoneElement = document.querySelector(`#dropzone-lantai-${lantai}`);
|
||||
if (dropzoneElement) {
|
||||
var dzInstance = dropzoneInstances[lantai];
|
||||
|
||||
fotoLantaiUnit[lantai].forEach(foto => {
|
||||
// Normalisasi path
|
||||
let normalizedPath = foto.path;
|
||||
|
||||
// Hapus prefix 'surveyor/' jika ada
|
||||
if (normalizedPath.startsWith('surveyor/')) {
|
||||
normalizedPath = normalizedPath.replace('surveyor/', '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Buat mock file untuk ditampilkan di Dropzone
|
||||
var mockFile = {
|
||||
name: foto.name || 'Foto Lantai',
|
||||
size: foto.size || 12345,
|
||||
path: normalizedPath, // Simpan path yang sudah dinormalisasi
|
||||
originalPath: 'storage/surveyor/' + normalizedPath
|
||||
};
|
||||
|
||||
// Pastikan instance Dropzone ada
|
||||
if (dzInstance) {
|
||||
dzInstance.emit("addedfile", mockFile);
|
||||
dzInstance.emit("thumbnail", mockFile, 'storage/surveyor/' +
|
||||
normalizedPath);
|
||||
dzInstance.emit("complete", mockFile);
|
||||
} else {
|
||||
console.error(
|
||||
`Dropzone instance for floor ${lantai} not found`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.error(`Dropzone element for floor ${lantai} not found`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function ensureAllFloorsCreated(jsonData) {
|
||||
if (jsonData && jsonData.foto_lantai_unit) {
|
||||
const maxFloor = Math.max(...Object.keys(jsonData.foto_lantai_unit).map(Number));
|
||||
|
||||
while (lantaiCounter < maxFloor) {
|
||||
const newLantaiElement = createLantaiElement();
|
||||
lantaiContainer.appendChild(newLantaiElement);
|
||||
initDropzonelantai(lantaiCounter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function deleteFoto(lantai, fotoPath) {
|
||||
return fetch("{{ route('surveyor.hapusLantai') }}", {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
permohonan_id: {{ $permohonan->id ?? 0 }},
|
||||
dokument_id: '{{ request('dokument') ?? '' }}',
|
||||
lantai: lantai,
|
||||
foto_path: fotoPath
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
// Hapus foto dari objek fotoLantaiUnit
|
||||
fotoLantaiUnit[lantai] = fotoLantaiUnit[lantai].filter(
|
||||
foto => foto.path !== fotoPath
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Fungsi inisialisasi Dropzone
|
||||
function initDropzonelantai(counter) {
|
||||
dropzoneInstances[counter] = new Dropzone(`#dropzone-lantai-${counter}`, {
|
||||
url: "{{ route('surveyor.storeFoto') }}",
|
||||
paramName: "foto_lantai_unit[]",
|
||||
maxFilesize: 5,
|
||||
acceptedFiles: 'image/*',
|
||||
maxFiles: 5,
|
||||
addRemoveLinks: true,
|
||||
autoProcessQueue: true,
|
||||
parallelUploads: 5,
|
||||
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
},
|
||||
|
||||
params: function(files, xhr, chunk) {
|
||||
return {
|
||||
permohonan_id: {{ $permohonan->id ?? 0 }},
|
||||
dokument_id: '{{ request('dokument') ?? '' }}',
|
||||
lantai_nama: [`lantai_${counter}`]
|
||||
};
|
||||
},
|
||||
init: function() {
|
||||
this.lantaiCounter = counter;
|
||||
this.on("sending", function(file, xhr, formData) {
|
||||
formData.append('lantai_index', this.lantaiCounter);
|
||||
});
|
||||
},
|
||||
|
||||
dictDefaultMessage: 'Seret foto atau klik untuk unggah',
|
||||
dictRemoveFile: 'Hapus',
|
||||
dictMaxFilesExceeded: 'Maksimal 5 file per lantai',
|
||||
|
||||
removedfile: function(file) {
|
||||
// Gunakan lantaiCounter dari instance ini
|
||||
const lantai = this.lantaiCounter;
|
||||
if (file.path) {
|
||||
deleteFoto(lantai, file.path).then(success => {
|
||||
if (success) {
|
||||
file.previewElement.remove();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
file.previewElement.remove();
|
||||
}
|
||||
},
|
||||
|
||||
success: function(file, response) {
|
||||
const lantai = this.lantaiCounter;
|
||||
|
||||
if (!fotoLantaiUnit[lantai]) {
|
||||
fotoLantaiUnit[lantai] = [];
|
||||
}
|
||||
|
||||
fotoLantaiUnit[lantai].push({
|
||||
path: response.foto_path,
|
||||
name: file.name
|
||||
});
|
||||
if (response) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Upload Berhasil',
|
||||
toast: true,
|
||||
position: 'top-end',
|
||||
showConfirmButton: false,
|
||||
timer: 1500
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
error: function(file, errorMessage) {
|
||||
console.error('Upload error', errorMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Fungsi membuat elemen lantai baru
|
||||
function createLantaiElement() {
|
||||
lantaiCounter++;
|
||||
|
||||
const lantaiElement = document.createElement('div');
|
||||
lantaiElement.classList.add('lantai-item', 'mb-4');
|
||||
lantaiElement.id = `lantai-item-${lantaiCounter}`;
|
||||
|
||||
lantaiElement.innerHTML = `
|
||||
<div class="flex justify-between align-items-center">
|
||||
<h5 class="mb-0">Lantai ${lantaiCounter}</h5>
|
||||
<input type="hidden" name="lantai_nama[]" value="lantai_${lantaiCounter}">
|
||||
<button type="button" class="btn btn-danger btn-sm btn-remove-lantai" data-id="${lantaiCounter}">
|
||||
<i class="fa fa-trash"></i> Hapus Lantai
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="dropzone" id="dropzone-lantai-${lantaiCounter}">
|
||||
<div class="dz-message">
|
||||
Seret dan lepas file di sini atau klik untuk unggah
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Event listener untuk tombol hapus lantai
|
||||
const removeButton = lantaiElement.querySelector('.btn-remove-lantai');
|
||||
removeButton.addEventListener('click', function() {
|
||||
const lantaiToRemove = parseInt(this.getAttribute('data-id'));
|
||||
hapusLantai(lantaiToRemove);
|
||||
});
|
||||
|
||||
return lantaiElement;
|
||||
}
|
||||
|
||||
// Fungsi hapus lantai yang diperbaiki
|
||||
function hapusLantai(lantai) {
|
||||
// Konfirmasi penghapusan
|
||||
Swal.fire({
|
||||
title: `Apakah Anda yakin ingin menghapus Lantai ${lantai}?`,
|
||||
text: "Semua foto pada lantai ini akan dihapus permanen!",
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Ya, Hapus!',
|
||||
cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
// Cek apakah ada foto di lantai ini
|
||||
const fotosLantai = fotoLantaiUnit[lantai] || [];
|
||||
|
||||
// Fungsi untuk menghapus foto-foto di lantai
|
||||
const hapusFotoLantai = () => {
|
||||
// Hapus instance Dropzone
|
||||
if (dropzoneInstances[lantai]) {
|
||||
dropzoneInstances[lantai].destroy();
|
||||
delete dropzoneInstances[lantai];
|
||||
}
|
||||
|
||||
// Hapus elemen lantai dari DOM
|
||||
const lantaiElement = document.getElementById(`lantai-item-${lantai}`);
|
||||
if (lantaiElement) {
|
||||
lantaiElement.remove();
|
||||
}
|
||||
|
||||
// Hapus dari objek fotoLantaiUnit
|
||||
delete fotoLantaiUnit[lantai];
|
||||
|
||||
// Perbarui counter dan tampilan
|
||||
updateLantaiCounter();
|
||||
|
||||
// Tampilkan notifikasi sukses
|
||||
Swal.fire(
|
||||
'Dihapus!',
|
||||
`Lantai ${lantai} telah dihapus.`,
|
||||
'success'
|
||||
);
|
||||
};
|
||||
|
||||
// Jika ada foto, hapus terlebih dahulu
|
||||
if (fotosLantai.length > 0) {
|
||||
// Buat promise untuk menghapus setiap foto
|
||||
const deletePromises = fotosLantai.map(foto =>
|
||||
deleteFoto(lantai, foto.path)
|
||||
);
|
||||
|
||||
// Tunggu semua foto terhapus
|
||||
Promise.all(deletePromises)
|
||||
.then(() => {
|
||||
// Setelah semua foto dihapus, lanjutkan proses penghapusan lantai
|
||||
hapusFotoLantai();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Gagal menghapus foto:', error);
|
||||
Swal.fire(
|
||||
'Gagal!',
|
||||
'Terjadi kesalahan saat menghapus foto.',
|
||||
'error'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Jika tidak ada foto, langsung hapus lantai
|
||||
hapusFotoLantai();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Fungsi updateLantaiCounter yang diperbaiki
|
||||
function updateLantaiCounter() {
|
||||
// Dapatkan semua elemen lantai yang tersisa
|
||||
const lantaiElements = document.querySelectorAll('.lantai-item');
|
||||
|
||||
// Perbarui nomor lantai dan ID
|
||||
lantaiElements.forEach((element, index) => {
|
||||
const currentIndex = index + 1;
|
||||
|
||||
// Perbarui judul lantai
|
||||
const lantaiTitle = element.querySelector('h5');
|
||||
if (lantaiTitle) {
|
||||
lantaiTitle.textContent = `Lantai ${currentIndex}`;
|
||||
}
|
||||
|
||||
// Perbarui input hidden
|
||||
const hiddenInput = element.querySelector('input[name="lantai_nama[]"]');
|
||||
if (hiddenInput) {
|
||||
hiddenInput.value = `lantai_${currentIndex}`;
|
||||
}
|
||||
|
||||
// Perbarui ID elemen
|
||||
element.id = `lantai-item-${currentIndex}`;
|
||||
|
||||
// Perbarui data-id pada tombol hapus
|
||||
const removeButton = element.querySelector('.btn-remove-lantai');
|
||||
if (removeButton) {
|
||||
removeButton.setAttribute('data-id', currentIndex);
|
||||
|
||||
// Tambahkan event listener baru
|
||||
removeButton.onclick = function() {
|
||||
hapusLantai(currentIndex);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Sembunyikan tombol hapus pada lantai pertama jika hanya satu lantai
|
||||
if (lantaiElements.length === 1) {
|
||||
const firstRemoveButton = document.querySelector('.btn-remove-lantai[data-id="1"]');
|
||||
if (firstRemoveButton) {
|
||||
firstRemoveButton.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Update lantaiCounter global
|
||||
lantaiCounter = lantaiElements.length;
|
||||
}
|
||||
|
||||
// Modifikasi event listener untuk tombol tambah lantai
|
||||
btnAddLantai.addEventListener('click', function() {
|
||||
const newLantaiElement = createLantaiElement();
|
||||
lantaiContainer.appendChild(newLantaiElement);
|
||||
|
||||
// Inisialisasi Dropzone untuk lantai baru
|
||||
initDropzonelantai(lantaiCounter);
|
||||
|
||||
// Tampilkan tombol hapus untuk lantai pertama
|
||||
const firstFloorRemoveBtn = document.querySelector('.btn-remove-lantai[data-id="1"]');
|
||||
if (firstFloorRemoveBtn) {
|
||||
firstFloorRemoveBtn.style.display = 'block';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
initDropzonelantai(lantaiCounter);
|
||||
|
||||
// Pastikan semua lantai dibuat
|
||||
ensureAllFloorsCreated(jsonDataContoh);
|
||||
|
||||
// Muat foto
|
||||
loadFotoFromJSON(jsonDataContoh);
|
||||
});
|
||||
|
||||
|
||||
function submitFoto() {
|
||||
@@ -446,13 +1032,6 @@
|
||||
|
||||
const formElement = $('#formFoto')[0];
|
||||
const formData = new FormData(formElement);
|
||||
for (let [key, value] of formData.entries()) {
|
||||
if (value instanceof File) {
|
||||
console.log(`${key}: File name = ${value.name}, File size = ${value.size}, File type = ${value.type}`);
|
||||
} else {
|
||||
console.log(`${key}: ${value}`);
|
||||
}
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '{{ route('surveyor.storeFoto') }}',
|
||||
@@ -474,10 +1053,10 @@
|
||||
confirmButtonText: 'OK'
|
||||
}).then((response) => {
|
||||
if (response.isConfirmed) {
|
||||
// window.location.href =
|
||||
// '{{ route('surveyor.show', ['id' => $permohonan->id]) }}';
|
||||
window.location.href =
|
||||
'{{ route('surveyor.show', ['id' => $permohonan->id]) }}';
|
||||
}
|
||||
console.log(response);
|
||||
// console.log(response);
|
||||
|
||||
});
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user