document.addEventListener('DOMContentLoaded', async function() { const tpsContentContainer = document.getElementById('tps-content'); let activeTpsIndex = 0; let tpsData = []; let nomorSpj = 'SPJ/07-2025/PKM/000476'; const RECORD_DETAIL_ENDPOINT = '/upst/detail-penjemputan/api/records/detail'; let autoSaveTimer = null; let autoSaveStatusEl = null; let loadingOverlayEl = null; let isAutoSaving = false; let pendingAutoSave = false; let lastAutoSaveSignature = ""; function getLoadingOverlay() { if (loadingOverlayEl && document.body.contains(loadingOverlayEl)) { return loadingOverlayEl; } loadingOverlayEl = document.createElement('div'); loadingOverlayEl.id = 'detail-loading-overlay'; loadingOverlayEl.className = 'fixed inset-0 z-[9999] hidden bg-white/95 backdrop-blur-sm flex items-center justify-center px-6'; loadingOverlayEl.innerHTML = `
Mohon tunggu sebentar, data penjemputan sedang dipulihkan.
Isi nama petugas terlebih dahulu
`; } return ``; } function refreshPetugasUploadState(form) { const stateContainer = form.querySelector(".petugas-upload-state"); if (!stateContainer) return; const tps = tpsData[activeTpsIndex]; stateContainer.innerHTML = getPetugasUploadStateMarkup(tps); const btnUploadPetugas = stateContainer.querySelector( ".tps-btn-upload-petugas:not([disabled])", ); if (btnUploadPetugas) { btnUploadPetugas.addEventListener("click", uploadFotoPetugas); } refreshSubmitButtonState(form); } function getSubmitState(tps) { if (tps?.submitted) { return { canSubmit: false, message: '' }; } if (!tps.fotoKedatanganUploaded) { if (!tps.fotoKedatangan.length) return { canSubmit: false, message: 'Silakan pilih dan upload foto kedatangan.' }; return { canSubmit: false, message: 'Silakan upload foto kedatangan terlebih dahulu.' }; } if (!tps.fotoPetugasUploaded) { if (!tps.fotoPetugas.length) return { canSubmit: false, message: 'Silakan pilih dan upload foto petugas.' }; return { canSubmit: false, message: 'Silakan upload foto petugas terlebih dahulu.' }; } if (!tps.namaPetugas.trim()) { return { canSubmit: false, message: "Isi nama petugas dulu sebelum submit.", }; } return { canSubmit: true, message: "" }; } function refreshSubmitButtonState(form) { const submitButton = form.querySelector('button[type="submit"]'); const tps = tpsData[activeTpsIndex]; if (tps?.submitted || !submitButton) return; const helperText = form.querySelector(".submit-state-message"); const submitState = getSubmitState(tps); submitButton.disabled = !submitState.canSubmit; submitButton.className = `w-2/3 py-3 rounded-xl font-bold text-sm transition ${submitState.canSubmit ? "bg-upst text-white hover:brightness-110" : "bg-gray-300 text-gray-500 cursor-not-allowed"}`; let messageEl = helperText; if (!messageEl) { messageEl = document.createElement("p"); messageEl.className = "submit-state-message text-[11px] text-center text-red-500 font-medium"; submitButton .closest(".flex.gap-3") ?.insertAdjacentElement("afterend", messageEl); } if (submitState.canSubmit) { messageEl.textContent = ""; messageEl.classList.add("hidden"); } else { messageEl.textContent = submitState.message; messageEl.classList.remove("hidden"); } } function buildSubmitFormData(tps) { const formData = new FormData(); formData.append("NomorSpj", nomorSpj || ""); formData.append("TpsName", tps.name || DEFAULT_TPS_NAME); formData.append("LokasiAngkutId", tps.lokasiAngkutId || ""); formData.append("SpjDetailId", tps.spjDetailId || ""); formData.append("Latitude", tps.latitude); formData.append("Longitude", tps.longitude); formData.append("AlamatJalan", tps.alamatJalan); formData.append("WaktuKedatangan", tps.waktuKedatangan); formData.append("NamaPetugas", tps.namaPetugas); tps.fotoKedatangan.forEach((file) => { if (isBrowserFile(file)) { formData.append("FotoKedatangan", file); } }); tps.fotoPetugas.forEach((file) => { if (isBrowserFile(file)) { formData.append("FotoPetugas", file); } }); const antiForgeryTokenEl = document.querySelector( '#upst-antiforgery input[name="__RequestVerificationToken"]', ); if (antiForgeryTokenEl && antiForgeryTokenEl.value) { formData.append("__RequestVerificationToken", antiForgeryTokenEl.value); } return formData; } async function uploadFotoKedatangan() { const tps = tpsData[activeTpsIndex]; if (tps.fotoKedatangan.length === 0) { showToast('Belum ada foto kedatangan yang dipilih!', 'error'); return; } const form = tpsContentContainer.querySelector('form'); const btn = form ? form.querySelector('.tps-btn-upload-kedatangan') : null; if (btn) { btn.disabled = true; btn.textContent = 'Mengupload...'; } const formData = new FormData(); tps.fotoKedatangan.forEach(f => formData.append('FotoKedatangan', f)); formData.append('NomorSpj', nomorSpj || ''); formData.append('NamaTps', tps.name || DEFAULT_TPS_NAME); formData.append('SpjDetailId', tps.spjDetailId || ''); formData.append('LokasiAngkutId', tps.lokasiAngkutId || ''); formData.append('WaktuKedatangan', tps.waktuKedatangan || ''); formData.append('Latitude', tps.latitude || ''); formData.append('Longitude', tps.longitude || ''); formData.append('AlamatJalan', tps.alamatJalan || ''); try { const res = await fetch('/upst/detail-penjemputan/upload-foto-kedatangan-jgc', { method: 'POST', body: formData }); const data = await res.json(); if (res.ok && data.success) { tps.fotoKedatanganUploaded = true; tps.fotoKedatanganFileNames = data.fileUrls || data.fileNames || []; showToast(data.message || 'Foto kedatangan berhasil diupload.', 'success'); if (form) { const fotoInput = form.querySelector('.tps-foto-kedatangan'); if (fotoInput) fotoInput.value = ''; const previewWrap = form.querySelector('.tps-preview-kedatangan-wrap'); const previewImg = form.querySelector('.tps-preview-kedatangan-img'); if (previewWrap && previewImg && tps.fotoKedatanganFileNames.length > 0) { previewImg.src = tps.fotoKedatanganFileNames[0]; previewWrap.classList.remove('hidden'); } refreshKedatanganUploadState(form); } scheduleAutoSave(); } else { showToast(data.message || 'Gagal upload foto kedatangan.', 'error'); if (btn) { btn.disabled = false; btn.textContent = `Upload ${tps.fotoKedatangan.length} Foto Kedatangan`; } } } catch { showToast('Koneksi gagal saat upload foto kedatangan.', 'error'); if (btn) { btn.disabled = false; btn.textContent = `Upload ${tps.fotoKedatangan.length} Foto Kedatangan`; } } } async function uploadFotoPetugas() { const tps = tpsData[activeTpsIndex]; if (tps.fotoPetugas.length === 0) { showToast('Belum ada foto petugas yang dipilih!', 'error'); return; } if (!tps.namaPetugas.trim()) { showToast('Nama petugas wajib diisi sebelum upload foto petugas!', 'error'); return; } const form = tpsContentContainer.querySelector('form'); const btn = form ? form.querySelector('.tps-btn-upload-petugas:not([disabled])') : null; if (btn) { btn.disabled = true; btn.textContent = 'Mengupload...'; } const formData = new FormData(); tps.fotoPetugas.forEach(f => formData.append('FotoPetugas', f)); formData.append('NomorSpj', nomorSpj || ''); formData.append('NamaTps', tps.name || DEFAULT_TPS_NAME); formData.append('SpjDetailId', tps.spjDetailId || ''); formData.append('LokasiAngkutId', tps.lokasiAngkutId || ''); formData.append('NamaPetugas', tps.namaPetugas); try { const res = await fetch('/upst/detail-penjemputan/upload-foto-petugas-jgc', { method: 'POST', body: formData }); const data = await res.json(); if (res.ok && data.success) { tps.fotoPetugasUploaded = true; tps.fotoPetugasFileNames = data.fileUrls || data.fileNames || []; showToast(data.message || 'Foto petugas berhasil diupload.', 'success'); if (form) { const fotoInput = form.querySelector('.tps-foto-petugas'); if (fotoInput) fotoInput.value = ''; const previewWrap = form.querySelector('.tps-preview-petugas-wrap'); const previewImg = form.querySelector('.tps-preview-petugas-img'); if (previewWrap && previewImg && tps.fotoPetugasFileNames.length > 0) { previewImg.src = tps.fotoPetugasFileNames[0]; previewWrap.classList.remove('hidden'); } refreshPetugasUploadState(form); } scheduleAutoSave(); } else { showToast(data.message || 'Gagal upload foto petugas.', 'error'); if (btn) { btn.disabled = false; btn.textContent = `Upload ${tps.fotoPetugas.length} Foto Petugas`; } } } catch { showToast('Koneksi gagal saat upload foto petugas.', 'error'); if (btn) { btn.disabled = false; btn.textContent = `Upload ${tps.fotoPetugas.length} Foto Petugas`; } } } async function submitTpsData() { const tps = tpsData[activeTpsIndex]; const submitState = getSubmitState(tps); if (!submitState.canSubmit) { showToast(submitState.message, 'error'); return; } const form = tpsContentContainer.querySelector('form'); const submitBtn = form ? form.querySelector('button[type="submit"]') : null; if (submitBtn) { submitBtn.disabled = true; submitBtn.textContent = 'Menyimpan...'; } const formData = buildSubmitFormData(tps); try { const res = await fetch('/upst/detail-penjemputan/jgc-submit', { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' }, body: formData }); const result = await res.json().catch(() => null); if (res.ok && result?.success) { tps.submitted = true; showToast(result.message || 'Data berhasil disimpan!', 'success'); setTimeout(() => { window.location.href = '/upst/detail-penjemputan/detail-selesai-jgc'; }, 1500); } else { showToast(result?.message || 'Gagal submit data.', 'error'); if (submitBtn) { submitBtn.disabled = false; submitBtn.textContent = 'Submit'; } } } catch { showToast('Koneksi gagal saat submit.', 'error'); if (submitBtn) { submitBtn.disabled = false; submitBtn.textContent = 'Submit'; } } } function showToast(message, type = 'info') { let container = document.getElementById('espj-toast-container'); if (!container) { container = document.createElement('div'); container.id = 'espj-toast-container'; container.style.cssText = 'position:fixed;bottom:80px;left:50%;transform:translateX(-50%);z-index:9999;display:flex;flex-direction:column;align-items:center;gap:8px;pointer-events:none;'; document.body.appendChild(container); } const toast = document.createElement('div'); const bg = type === 'success' ? '#16a34a' : type === 'error' ? '#dc2626' : '#2563eb'; toast.style.cssText = `background:${bg};color:#fff;padding:10px 18px;border-radius:16px;font-size:13px;font-weight:600;box-shadow:0 4px 24px rgba(0,0,0,.18);opacity:0;transition:opacity .25s;max-width:320px;text-align:center;`; toast.textContent = message; container.appendChild(toast); requestAnimationFrame(() => { toast.style.opacity = '1'; }); setTimeout(() => { toast.style.opacity = '0'; setTimeout(() => toast.remove(), 300); }, 3200); } const nomorSpjEl = document.querySelector(".text-gray-600.font-mono"); if (nomorSpjEl && nomorSpjEl.textContent) { nomorSpj = nomorSpjEl.textContent.trim(); } showLoadingOverlay(); try { initializeLocation(); await loadDetailData(); await loadRecordForCurrentSpj(); renderTpsForm(); } finally { hideLoadingOverlay(); } function renderServerImagePreview(fileUrls, container) { container.innerHTML = ''; if (!fileUrls || fileUrls.length === 0) return; container.className = 'space-y-2'; fileUrls.forEach((url, index) => { const item = document.createElement('div'); item.className = 'rounded-xl border border-gray-200 overflow-hidden bg-black'; const isUrl = typeof url === 'string' && (url.startsWith('/') || url.startsWith('http')); if (isUrl) { item.innerHTML = `✓ Foto ${index + 1}
`; } container.appendChild(item); }); } });