1013 lines
41 KiB
PHP
1013 lines
41 KiB
PHP
@extends('layouts.main')
|
|
|
|
@section('breadcrumbs')
|
|
{{ Breadcrumbs::render(request()->route()->getName()) }}
|
|
@endsection
|
|
|
|
@section('content')
|
|
{{-- <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: 150px;
|
|
}
|
|
|
|
.dropzone .dz-message {
|
|
text-align: center;
|
|
margin: 50px 0;
|
|
}
|
|
|
|
.dropzone .dz-preview {
|
|
margin: 10px;
|
|
width: 16rem;
|
|
height: 16rem;
|
|
}
|
|
|
|
.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%
|
|
}
|
|
}
|
|
|
|
.dropzone-buttons {
|
|
position: absolute;
|
|
bottom: 10px;
|
|
/* Jarak dari bawah */
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
z-index: 10;
|
|
}
|
|
|
|
.dropzone-buttons button {
|
|
opacity: 0.9;
|
|
transition: opacity 0.3s ease;
|
|
}
|
|
|
|
.dropzone-buttons button:hover {
|
|
opacity: 1;
|
|
|
|
}
|
|
|
|
.dz-preview {
|
|
position: relative;
|
|
}
|
|
</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">
|
|
<div class="card-header bg-agi-50">
|
|
<h3 class="card-title">
|
|
Data Jaminan
|
|
</h3>
|
|
<div class="flex items-center gap-2">
|
|
<a href="{{ route('surveyor.show', ['id' => $permohonan->id]) }}" class="btn btn-xs btn-info">
|
|
<i class="ki-filled ki-exit-left"></i> Back
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<div class="card-body grid gap-5 grid-cols-2">
|
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
|
<label class="form-label max-w-56">Nama Debitur</label>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
@if (isset($permohonan->debiture))
|
|
<p class="text-2sm text-gray-700">{{ $permohonan->debiture->name }}</p>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
|
<label class="form-label max-w-56">Alamat Object</label>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
@foreach ($permohonan->documents as $dokumen)
|
|
<span class="text-2sm text-gray-700">
|
|
{{ formatAlamat($dokumen->pemilik) }}
|
|
</span>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
|
<label class="form-label max-w-56">Nomor Registrasi</label>
|
|
<div class="flex flex-wrap items-base line w-full">
|
|
<p class="text-2sm text-gray-700">{{ $permohonan->nomor_registrasi }}</p>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
|
<label class="form-label max-w-56">Cab/Direktorat</label>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
@if (isset($permohonan->branch))
|
|
<p class="text-2sm text-gray-700">{{ $permohonan->branch->name }}</p>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
|
<label class="form-label max-w-56">Nomor Laporan</label>
|
|
<div class="flex flex-wrap items-base line w-full">
|
|
<p class="text-2sm text-gray-700">{{ $permohonan->nomor_registrasi }}</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
|
<label class="form-label max-w-56">AO</label>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
@if (isset($permohonan->user))
|
|
<p class="text-2sm text-gray-700">{{ $permohonan->user->name }}</p>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<form id="formFoto" method="POST" class="grid gap-5" enctype="multipart/form-data">
|
|
<input type="hidden" name="permohonan_id" value="{{ $permohonan->id }}">
|
|
<input type="hidden" name="dokument_id" value="{{ request('dokument') }}">
|
|
<input type="hidden" name="nomor_registrasi" value="{{ $permohonan->nomor_registrasi }}">
|
|
|
|
|
|
<div class="card border border-agi-100 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">Upload Foto</h1>
|
|
</div>
|
|
|
|
<div class="dropzone" id="upload-dropzone">
|
|
<div class="dz-message needsclick" data-foto-type="upload_foto">
|
|
<i class="ki-duotone ki-file-up text-primary text-3xl"><span class="path1"></span><span
|
|
class="path2"></span></i>
|
|
<div class="ms-4">
|
|
<h3 class="fs-5 fw-bold text-gray-900 mb-1">Drop files here or click to upload.</h3>
|
|
<span class="fs-7 fw-semibold text-gray-500">Upload up to 10 files</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="drawer drawer-end flex flex-col max-w-[90%] w-[300px]" data-drawer="true" id="drawer_2_2">
|
|
<div class="flex items-center justify-between p-5 border-b">
|
|
<h3 class="text-base font-semibold text-gray-900">
|
|
Data Foto
|
|
</h3>
|
|
<button class="btn btn-xs btn-icon btn-icon-xl btn-light" data-drawer-dismiss="true">
|
|
<i class="ki-outline ki-cross">
|
|
</i>
|
|
</button>
|
|
</div>
|
|
<div class="p-5">
|
|
<form id="editDataForm">
|
|
<input type="hidden" id="editDataFilePath" name="file_path">
|
|
<div class="mb-4">
|
|
<label for="editDataName" class="block text-sm font-medium text-gray-700">Nama</label>
|
|
<input type="text" id="editDataName" name="name"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
|
|
</div>
|
|
<div class="mb-4">
|
|
<label for="editDataDescription" class="block text-sm font-medium text-gray-700">Deskripsi</label>
|
|
<textarea id="editDataDescription" name="description" rows="3"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"></textarea>
|
|
<span class="text-xs text-danger"> * Kosongkan jika tidak ada</span>
|
|
</div>
|
|
<div class="mb-4">
|
|
<label for="editDataCategory" class="block text-sm font-medium text-gray-700">Kategori</label>
|
|
<select id="editDataCategory" name="category" class="input"></select>
|
|
</div>
|
|
<div class="mb-4">
|
|
<label for="editDataCategory" class="block text-sm font-medium text-gray-700">Sub Kategori</label>
|
|
<input id="editDataSub" name="sub" type="text" class="input"
|
|
placeholder="Masukkan sub kategori" />
|
|
<span class="text-xs text-danger"> * Kosongkan jika tidak ada</span>
|
|
</div>
|
|
<div class="flex gap-2.5">
|
|
<button id="saveEditDataButton" type="button" class="btn btn-primary"
|
|
onclick="saveEditedFoto()">Simpan</button>
|
|
<button type="button" class="btn btn-light" data-modal-toggle="#modal_10"
|
|
data-drawer-dismiss="true">Edit Foto</button>
|
|
<button type="button" class="btn btn-danger" data-drawer-dismiss="true">Batal</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal" data-modal="true" id="modal_10">
|
|
<div class="modal-content modal-overlay">
|
|
{{-- <div class="modal-header">
|
|
<h3 class="modal-title">
|
|
Edit Foto
|
|
</h3>
|
|
<button class="btn btn-xs btn-icon btn-light" data-modal-dismiss="true">
|
|
<i class="ki-outline ki-cross">
|
|
</i>
|
|
</button>
|
|
</div> --}}
|
|
<div class="modal-body scrollable-y-auto">
|
|
<div id="editor_container" class="w-full h-full"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Kamera -->
|
|
@include('lpj::surveyor.components.modal-kamera')
|
|
@endsection
|
|
|
|
@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>
|
|
let jsonDataContoh = @json($formFoto);
|
|
Dropzone.autoDiscover = false;
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
let myDropzone = null;
|
|
let uploadQueue = 0;
|
|
let uploadBatch = [];
|
|
|
|
function initDropzone(selector, paramName) {
|
|
try {
|
|
const dropzoneElement = document.querySelector(selector);
|
|
if (!dropzoneElement) {
|
|
console.error(`Dropzone element not found: ${selector}`);
|
|
return null;
|
|
}
|
|
const processedFiles = new Set();
|
|
|
|
// Track files that are already on the server
|
|
const existingFiles = new Set();
|
|
|
|
addCameraOption(dropzoneElement, paramName);
|
|
|
|
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;
|
|
}
|
|
|
|
// Check if file already exists on server
|
|
if (existingFiles.has(file.name)) {
|
|
done('File dengan nama ini sudah ada.');
|
|
return;
|
|
}
|
|
|
|
// Add file to processed set
|
|
processedFiles.add(fileId);
|
|
done();
|
|
},
|
|
|
|
addedfiles: function(files) {
|
|
const validFiles = Array.from(files).filter(file => {
|
|
// Only count files that haven't been rejected
|
|
return !file.rejected;
|
|
});
|
|
|
|
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);
|
|
|
|
// Format error message
|
|
let errorMsg = typeof response === 'string' ? response :
|
|
(response.message || 'Gagal mengupload file');
|
|
|
|
handleUploadComplete(file, false, errorMsg);
|
|
},
|
|
|
|
success: function(file, response) {
|
|
if (response.success) {
|
|
const fileData = {
|
|
path: response.path || file.path,
|
|
name: file.name,
|
|
description: '',
|
|
category: 'lainnya',
|
|
sub: '',
|
|
param_name: paramName
|
|
};
|
|
|
|
// Add file to existing files set to prevent duplicates
|
|
existingFiles.add(file.name);
|
|
|
|
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, existingFiles);
|
|
}
|
|
});
|
|
|
|
return myDropzone;
|
|
} catch (error) {
|
|
console.error('Dropzone initialization error:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
function addCameraOption(dropzoneElement, paramName) {
|
|
if (dropzoneElement.querySelector('.upload-options')) {
|
|
return;
|
|
}
|
|
|
|
// Create the upload options container
|
|
const uploadOptionsContainer = document.createElement('div');
|
|
uploadOptionsContainer.className = 'upload-options';
|
|
uploadOptionsContainer.style.cssText = `
|
|
display: flex;
|
|
justify-content: center;
|
|
margin-top: 10px;
|
|
gap: 20px;
|
|
`;
|
|
|
|
// Create camera button
|
|
const cameraButton = document.createElement('button');
|
|
cameraButton.type = 'button';
|
|
cameraButton.className = 'camera-button';
|
|
cameraButton.innerHTML = '<i class="ki-duotone ki-camera fs-2"></i> Kamera';
|
|
cameraButton.style.cssText = `
|
|
padding: 8px 16px;
|
|
background-color: #f5f8fa;
|
|
border: 1px solid #e4e6ef;
|
|
border-radius: 6px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
cursor: pointer;
|
|
`;
|
|
|
|
// Create file button
|
|
const fileButton = document.createElement('button');
|
|
fileButton.type = 'button';
|
|
fileButton.className = 'file-button';
|
|
fileButton.innerHTML = '<i class="ki-duotone ki-folder fs-2"></i> File';
|
|
fileButton.style.cssText = `
|
|
padding: 8px 16px;
|
|
background-color: #f5f8fa;
|
|
border: 1px solid #e4e6ef;
|
|
border-radius: 6px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
cursor: pointer;
|
|
`;
|
|
|
|
|
|
const cameraInput = document.createElement('input');
|
|
cameraInput.type = 'file';
|
|
cameraInput.id = 'camera-input-' + paramName;
|
|
cameraInput.accept = 'image/*';
|
|
cameraInput.capture = 'environment';
|
|
cameraInput.style.display = 'none';
|
|
|
|
|
|
const fileInput = document.createElement('input');
|
|
fileInput.type = 'file';
|
|
fileInput.id = 'file-input-' + paramName;
|
|
fileInput.accept = 'image/*';
|
|
fileInput.style.display = 'none';
|
|
|
|
// Add event listeners - use only one instance per button
|
|
cameraButton.addEventListener('click', function(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
cameraInput.click();
|
|
}, false);
|
|
|
|
fileButton.addEventListener('click', function(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
fileInput.click();
|
|
}, false);
|
|
|
|
// Handle file selection for camera - clear input after use
|
|
cameraInput.addEventListener('change', function() {
|
|
if (this.files && this.files.length > 0) {
|
|
handleFileSelection(this.files, myDropzone);
|
|
|
|
this.value = '';
|
|
}
|
|
}, false);
|
|
|
|
// Handle file selection for gallery - clear input after use
|
|
fileInput.addEventListener('change', function() {
|
|
if (this.files && this.files.length > 0) {
|
|
handleFileSelection(this.files, myDropzone);
|
|
|
|
this.value = '';
|
|
}
|
|
}, false);
|
|
|
|
// Append elements
|
|
uploadOptionsContainer.appendChild(cameraButton);
|
|
uploadOptionsContainer.appendChild(fileButton);
|
|
document.body.appendChild(cameraInput);
|
|
document.body.appendChild(fileInput);
|
|
|
|
// Find the message element in dropzone and insert the options after it
|
|
const dzMessage = dropzoneElement.querySelector('.dz-message');
|
|
if (dzMessage) {
|
|
dzMessage.appendChild(uploadOptionsContainer);
|
|
} else {
|
|
dropzoneElement.appendChild(uploadOptionsContainer);
|
|
}
|
|
|
|
|
|
if (dzMessage) {
|
|
dzMessage.style.cssText += `
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
`;
|
|
}
|
|
}
|
|
|
|
|
|
function handleFileSelection(files, dropzone) {
|
|
if (!dropzone) return;
|
|
|
|
Array.from(files).forEach(file => {
|
|
dropzone.addFile(file);
|
|
});
|
|
}
|
|
|
|
function loadExistingPhotos(dropzone, paramName, existingFilesSet) {
|
|
showLoadingOverlay();
|
|
|
|
$.ajax({
|
|
url: "{{ route('surveyor.getFoto') }}",
|
|
method: 'GET',
|
|
data: {
|
|
permohonan_id: {{ $permohonan->id ?? 0 }},
|
|
dokument_id: '{{ request('dokument') ?? '' }}',
|
|
param_name: paramName
|
|
},
|
|
headers: {
|
|
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
|
},
|
|
success: function(response) {
|
|
if (response.fotos && response.fotos.length) {
|
|
response.fotos.forEach(function(foto) {
|
|
var mockFile = {
|
|
name: foto.name,
|
|
size: foto.size || 12345,
|
|
originalPath: foto.path
|
|
};
|
|
|
|
// 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 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'
|
|
});
|
|
}
|
|
|
|
|
|
// Check if device is mobile
|
|
function isMobileDevice() {
|
|
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
}
|
|
|
|
// 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);
|
|
|
|
// Fungsi untuk membuka modal dan mengatur data
|
|
window.openEditDrawer = function(file, response) {
|
|
// Mengisi data input berdasarkan respons
|
|
document.getElementById('editDataFilePath').value = response.path || '';
|
|
document.getElementById('editDataName').value = response.name || '';
|
|
document.getElementById('editDataDescription').value = response.description || '';
|
|
document.getElementById('editDataSub').value = response.sub || '';
|
|
|
|
// Ambil elemen select kategori
|
|
const selectElement = document.getElementById('editDataCategory');
|
|
|
|
// Bersihkan opsi sebelumnya agar tidak duplikat
|
|
selectElement.innerHTML = '';
|
|
|
|
// Tambahkan opsi dari fotoObjekJaminan
|
|
fotoObjekJaminan.forEach(item => {
|
|
const option = document.createElement('option');
|
|
option.value = item.name;
|
|
option.textContent = item.name;
|
|
selectElement.appendChild(option);
|
|
});
|
|
|
|
// Tambahkan opsi "lainnya"
|
|
const defaultOption = document.createElement('option');
|
|
defaultOption.value = 'lainnya';
|
|
defaultOption.textContent = 'Lainnya';
|
|
selectElement.appendChild(defaultOption);
|
|
|
|
// Setel nilai kategori dari respons atau default
|
|
selectElement.value = response.category || 'lainnya';
|
|
|
|
// Jika kategori dari respons tidak ada dalam opsi, tambahkan opsi baru
|
|
if (response.category && !Array.from(selectElement.options).some(option => option.value === response
|
|
.category)) {
|
|
const newOption = document.createElement('option');
|
|
newOption.value = response.category;
|
|
newOption.textContent = response.category;
|
|
selectElement.appendChild(newOption);
|
|
selectElement.value = response.category;
|
|
}
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Create container for Filerobot editor
|
|
const editorContainer = document.createElement('div');
|
|
editorContainer.id = 'editor_container';
|
|
editorContainer.style.width = '100%';
|
|
editorContainer.style.height = '100%';
|
|
|
|
// Add container to modal body
|
|
const modalBody = document.querySelector('#modal_10 .modal-body');
|
|
modalBody.innerHTML = '';
|
|
modalBody.appendChild(editorContainer);
|
|
|
|
// Update the Edit Foto button event handler
|
|
const editFotoButton = document.querySelector('[data-modal-toggle="#modal_10"]');
|
|
if (editFotoButton) {
|
|
editFotoButton.addEventListener('click', function(e) {
|
|
e.preventDefault();
|
|
// Get the file path from hidden input
|
|
const filePath = document.getElementById('editDataFilePath').value;
|
|
|
|
if (filePath) {
|
|
openFilerobotEditor(filePath);
|
|
} else {
|
|
alert('Tidak ada foto untuk diedit');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
|
|
function openFilerobotEditor(imagePath) {
|
|
// Get the editor container
|
|
const editorContainer = document.getElementById('editor_container');
|
|
|
|
if (!editorContainer) {
|
|
console.error('Editor container not found');
|
|
return;
|
|
}
|
|
// Configuration for the editor
|
|
const config = {
|
|
source: imagePath || '',
|
|
onSave: (editedImageObject, designState) => {
|
|
saveEditedImage(editedImageObject, document.getElementById('editDataFilePath').value);
|
|
window.FilerobotImageEditor.terminate();
|
|
|
|
},
|
|
annotationsCommon: {
|
|
fill: '#ff0000'
|
|
},
|
|
Text: {
|
|
text: 'Tambahkan teks...'
|
|
},
|
|
Rotate: {
|
|
angle: 90,
|
|
componentType: 'slider'
|
|
},
|
|
tabsIds: [
|
|
window.FilerobotImageEditor.TABS.ADJUST,
|
|
window.FilerobotImageEditor.TABS.FILTERS,
|
|
window.FilerobotImageEditor.TABS.FINETUNE,
|
|
window.FilerobotImageEditor.TABS.ANNOTATE,
|
|
window.FilerobotImageEditor.TABS.WATERMARK,
|
|
window.FilerobotImageEditor.TABS.RESIZE,
|
|
],
|
|
defaultTabId: window.FilerobotImageEditor.TABS.ADJUST,
|
|
Language: {
|
|
Save: 'Simpan',
|
|
Cancel: 'Batal',
|
|
Reset: 'Reset',
|
|
Edit: 'Edit',
|
|
Delete: 'Hapus'
|
|
}
|
|
};
|
|
|
|
// Initialize the Filerobot Image Editor
|
|
const filerobotImageEditor = new FilerobotImageEditor(
|
|
editorContainer,
|
|
config
|
|
);
|
|
|
|
|
|
filerobotImageEditor.render({
|
|
onClose: (closingReason) => {
|
|
console.log('Editor closed:', closingReason);
|
|
|
|
filerobotImageEditor.terminate();
|
|
|
|
let closeButton = document.getElementById('modal_10');
|
|
|
|
if (!closeButton) {
|
|
closeButton = document.createElement('button');
|
|
closeButton.setAttribute('data-modal-dismiss', 'true');
|
|
closeButton.setAttribute('type', 'button');
|
|
closeButton.setAttribute('class', 'btn btn-primary');
|
|
closeButton.setAttribute('data-modal-toggle', '#modal_10');
|
|
document.body.appendChild(closeButton);
|
|
}
|
|
|
|
closeButton.click();
|
|
console.log('Modal closed via close button simulation');
|
|
}
|
|
});
|
|
|
|
}
|
|
window.addEditAndDeleteButtons = function(file, response) {
|
|
|
|
const filePreviewElement = file.previewElement;
|
|
|
|
if (!filePreviewElement) {
|
|
console.error('File preview element not found for:', file);
|
|
return;
|
|
}
|
|
|
|
// Buat container untuk tombol Edit dan Delete
|
|
const buttonContainer = document.createElement('div');
|
|
buttonContainer.className = 'dropzone-buttons';
|
|
// Tombol Edit
|
|
const editButton = document.createElement("button");
|
|
editButton.className = "btn btn-sm btn-warning ms-2";
|
|
editButton.innerHTML = '<i class="ki-filled ki-notepad-edit"></i> Edit';
|
|
editButton.type = "button";
|
|
editButton.style.cursor = 'pointer';
|
|
editButton.setAttribute("data-drawer-toggle", "#drawer_2_2");
|
|
editButton.onclick = function() {
|
|
// e.preventDefault();
|
|
openEditDrawer(file, response);
|
|
};
|
|
|
|
// Tombol Hapus
|
|
const deleteButton = document.createElement('button');
|
|
deleteButton.innerHTML = '<i class="ki-filled ki-trash"></i> Delete';
|
|
deleteButton.className = 'btn btn-sm btn-danger';
|
|
deleteButton.style.cursor = 'pointer';
|
|
deleteButton.type = "button";
|
|
|
|
// Event untuk tombol Delete
|
|
deleteButton.addEventListener('click', function() {
|
|
Swal.fire({
|
|
title: 'Hapus Foto?',
|
|
text: "Foto ini akan dihapus secara permanen!",
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#3085d6',
|
|
cancelButtonColor: '#d33',
|
|
confirmButtonText: 'Ya, hapus!'
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
// Hapus foto dari server
|
|
$.ajax({
|
|
url: "{{ route('surveyor.hapusFoto') }}",
|
|
method: 'DELETE',
|
|
data: {
|
|
path: file.originalPath,
|
|
permohonan_id: {{ $permohonan->id ?? 0 }},
|
|
dokument_id: '{{ request('dokument') ?? '' }}',
|
|
param_name: response.param_name
|
|
},
|
|
headers: {
|
|
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
|
},
|
|
success: function() {
|
|
Swal.fire('Dihapus!', 'Foto berhasil dihapus.', 'success');
|
|
if (filePreviewElement) {
|
|
filePreviewElement.remove();
|
|
}
|
|
},
|
|
error: function() {
|
|
Swal.fire('Gagal!', 'Foto gagal dihapus.', 'error');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
// Tambahkan tombol ke preview element
|
|
buttonContainer.appendChild(editButton);
|
|
buttonContainer.appendChild(deleteButton);
|
|
filePreviewElement.appendChild(buttonContainer);
|
|
}
|
|
|
|
async function saveEditedFoto() {
|
|
$.ajax({
|
|
url: `{{ route('surveyor.updateFoto') }}`,
|
|
type: 'PUT',
|
|
headers: {
|
|
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
|
},
|
|
data: {
|
|
permohonan_id: {{ $permohonan->id }},
|
|
dokument_id: '{{ request('dokument') ?? '' }}',
|
|
name: $('#editDataName').val(),
|
|
description: $('#editDataDescription').val(),
|
|
category: $('#editDataCategory').val(),
|
|
sub: $('#editDataSub').val(),
|
|
path: $('#editDataFilePath').val()
|
|
},
|
|
success: function(response) {
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'Perubahan Disimpan',
|
|
text: response.message,
|
|
confirmButtonText: 'OK'
|
|
}).then((response) => {
|
|
if (response.isConfirmed) {
|
|
window.location.reload();
|
|
|
|
}
|
|
});;
|
|
|
|
},
|
|
error: function(xhr) {
|
|
const errorMessage = xhr.responseJSON?.message || 'Terjadi kesalahan';
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Gagal Menyimpan',
|
|
text: errorMessage,
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
function saveEditedImage(editedImageObject, originalFilePath) {
|
|
// Get the image data (base64 or canvas)
|
|
const imageData = editedImageObject.imageBase64 ||
|
|
(editedImageObject.imageCanvas ? editedImageObject.imageCanvas.toDataURL() : null);
|
|
|
|
if (!imageData) {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Gagal Menyimpan',
|
|
text: 'Tidak ada data gambar untuk disimpan',
|
|
});
|
|
return;
|
|
}
|
|
const formData = new FormData();
|
|
formData.append('edited_image', imageData);
|
|
formData.append('original_path', originalFilePath);
|
|
|
|
formData.forEach((value, key) => {
|
|
console.log(`${key}:`, value);
|
|
});
|
|
|
|
|
|
$.ajax({
|
|
url: `{{ route('surveyor.saveEditedImage') }}`,
|
|
type: 'POST',
|
|
headers: {
|
|
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
|
},
|
|
data: {
|
|
edited_image: imageData,
|
|
original_path: originalFilePath,
|
|
nomor_registrasi: '{{ $permohonan->nomor_registrasi }}'
|
|
},
|
|
|
|
success: function(response) {
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'Perubahan Disimpan',
|
|
text: response.message,
|
|
confirmButtonText: 'OK'
|
|
}).then((response) => {
|
|
if (response.isConfirmed) {
|
|
window.location.reload();
|
|
|
|
}
|
|
});
|
|
},
|
|
error: function(xhr) {
|
|
const errorMessage = xhr.responseJSON?.message || 'Terjadi kesalahan';
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Gagal Menyimpan',
|
|
text: errorMessage,
|
|
}).then((response) => {
|
|
if (response.isConfirmed) {
|
|
window.location.reload();
|
|
|
|
}
|
|
});
|
|
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
</script>
|
|
@endpush
|