diff --git a/Views/Admin/Transport/SpjDriverUpst/DetailPenjemputan/TanpaTps.cshtml b/Views/Admin/Transport/SpjDriverUpst/DetailPenjemputan/TanpaTps.cshtml index 3e3efd0..b76d838 100644 --- a/Views/Admin/Transport/SpjDriverUpst/DetailPenjemputan/TanpaTps.cshtml +++ b/Views/Admin/Transport/SpjDriverUpst/DetailPenjemputan/TanpaTps.cshtml @@ -1,6 +1,6 @@ @{ Layout = "~/Views/Admin/Transport/SpjDriverUpst/Shared/_Layout.cshtml"; - ViewData["Title"] = "Detail Penjemputan - Tanpa TPS"; + ViewData["Title"] = "Detail Penjemputan - TPS A"; }
@@ -13,7 +13,7 @@ -

Detail Lokasi

+

TPS A

@@ -27,7 +27,7 @@
No. Pintu -

JRC 005

+

JRC 005

@@ -35,24 +35,24 @@
- - TANPA TPS + + TPS A

Perusahaan

-

CV Tri Berkah Sejahtera

+

CV Tri Berkah Sejahtera

-

SPJ/07-2025/PKM/000476

+

SPJ/07-2025/PKM/000476

-

+

Kp. Pertanian II Rt.004 Rw.001 Kel. Klender Kec, Duren Sawit, Kota Adm. Jakarta Timur 13470

@@ -87,9 +87,8 @@
-

Form Pengangkutan

- Tanpa TPS + TPS A
diff --git a/Views/Admin/Transport/SpjDriverUpst/Home/Index.cshtml b/Views/Admin/Transport/SpjDriverUpst/Home/Index.cshtml index 6e2d57d..ce9a7f9 100644 --- a/Views/Admin/Transport/SpjDriverUpst/Home/Index.cshtml +++ b/Views/Admin/Transport/SpjDriverUpst/Home/Index.cshtml @@ -134,7 +134,25 @@

Jakarta Timur 13470

- Ada 3 TPS + 3 TPS +
+
+ + + +
+
+
+ Proses + +
+

CV Tri Berkah Sejahtera

+
+ +

Duren Sawit, Jakarta Timur

+
+
+ 1 TPS
@@ -149,7 +167,7 @@

CV Tri Mitra Utama - Shell Radio Dalam

Jakarta Selatan

- Ada 3 TPS + 3 TPS
@@ -164,7 +182,7 @@

CV Tri Berkah Sejahtera

Duren Sawit, Jakarta Timur

- Tidak ada TPS + 1 TPS
diff --git a/wwwroot/driver/css/watch.css b/wwwroot/driver/css/watch.css index e68ab2c..c8ae70d 100644 --- a/wwwroot/driver/css/watch.css +++ b/wwwroot/driver/css/watch.css @@ -109,8 +109,6 @@ --text-xl--line-height: calc(1.75 / 1.25); --text-2xl: 1.5rem; --text-2xl--line-height: calc(2 / 1.5); - --text-5xl: 3rem; - --text-5xl--line-height: 1; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; @@ -569,12 +567,6 @@ .col-auto { grid-column: auto; } - .col-span-1 { - grid-column: span 1 / span 1; - } - .col-span-2 { - grid-column: span 2 / span 2; - } .float-end { float: inline-end; } @@ -806,12 +798,6 @@ .ml-auto { margin-left: auto; } - .line-clamp-2 { - overflow: hidden; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 2; - } .line-clamp-3 { overflow: hidden; display: -webkit-box; @@ -875,9 +861,6 @@ .h-3 { height: calc(var(--spacing) * 3); } - .h-3\.5 { - height: calc(var(--spacing) * 3.5); - } .h-4 { height: calc(var(--spacing) * 4); } @@ -986,9 +969,6 @@ .w-3 { width: calc(var(--spacing) * 3); } - .w-3\.5 { - width: calc(var(--spacing) * 3.5); - } .w-4 { width: calc(var(--spacing) * 4); } @@ -1235,9 +1215,6 @@ .gap-1 { gap: calc(var(--spacing) * 1); } - .gap-1\.5 { - gap: calc(var(--spacing) * 1.5); - } .gap-2 { gap: calc(var(--spacing) * 2); } @@ -1691,6 +1668,9 @@ .bg-gray-200 { background-color: var(--color-gray-200); } + .bg-gray-300 { + background-color: var(--color-gray-300); + } .bg-gray-400 { background-color: var(--color-gray-400); } @@ -2138,9 +2118,6 @@ .py-1 { padding-block: calc(var(--spacing) * 1); } - .py-1\.5 { - padding-block: calc(var(--spacing) * 1.5); - } .py-2 { padding-block: calc(var(--spacing) * 2); } @@ -2159,9 +2136,6 @@ .py-6 { padding-block: calc(var(--spacing) * 6); } - .py-10 { - padding-block: calc(var(--spacing) * 10); - } .py-12 { padding-block: calc(var(--spacing) * 12); } @@ -2436,12 +2410,6 @@ .text-blue-700 { color: var(--color-blue-700); } - .text-blue-700\/60 { - color: color-mix(in srgb, oklch(48.8% 0.243 264.376) 60%, transparent); - @supports (color: color-mix(in lab, red, red)) { - color: color-mix(in oklab, var(--color-blue-700) 60%, transparent); - } - } .text-blue-800 { color: var(--color-blue-800); } @@ -2859,13 +2827,6 @@ } } } - .group-hover\:border-gray-200 { - &:is(:where(.group):hover *) { - @media (hover: hover) { - border-color: var(--color-gray-200); - } - } - } .group-hover\:text-gray-500 { &:is(:where(.group):hover *) { @media (hover: hover) { @@ -2887,14 +2848,6 @@ } } } - .group-hover\:shadow { - &:is(:where(.group):hover *) { - @media (hover: hover) { - --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); - box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); - } - } - } .group-hover\:shadow-md { &:is(:where(.group):hover *) { @media (hover: hover) { @@ -3021,13 +2974,6 @@ } } } - .hover\:border-gray-200 { - &:hover { - @media (hover: hover) { - border-color: var(--color-gray-200); - } - } - } .hover\:border-orange-200 { &:hover { @media (hover: hover) { @@ -3346,11 +3292,6 @@ scale: var(--tw-scale-x) var(--tw-scale-y); } } - .sm\:grid-cols-4 { - @media (width >= 40rem) { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - } .lg\:max-w-sm { @media (width >= 64rem) { max-width: var(--container-sm); diff --git a/wwwroot/driver/js/detail-penjemputan-non-tps.js b/wwwroot/driver/js/detail-penjemputan-non-tps.js index 23ee36d..e0be3c2 100644 --- a/wwwroot/driver/js/detail-penjemputan-non-tps.js +++ b/wwwroot/driver/js/detail-penjemputan-non-tps.js @@ -16,10 +16,12 @@ document.addEventListener('DOMContentLoaded', function() { ]; const JENIS_SAMPAH = ['Organik', 'Anorganik', 'Residu']; const DEFAULT_JENIS = 'Residu'; + const DETAIL_DATA_URL = '/driver/json/detail-penjemputan-non-tps.json'; + const DEFAULT_TPS_NAME = 'Lokasi Pengangkutan 1'; function initializeLocation() { tpsData = [{ - name: '', + name: DEFAULT_TPS_NAME, index: 0, lokasiAngkutId: '', spjDetailId: '', @@ -43,6 +45,53 @@ document.addEventListener('DOMContentLoaded', function() { renderTpsForm(); } + async function loadDetailData() { + try { + const response = await fetch(DETAIL_DATA_URL, { cache: 'no-store' }); + if (!response.ok) { + return; + } + + const payload = await response.json(); + const detail = payload.detailPenjemputan || payload; + const namaTps = detail.namaTps || detail.tpsName || detail.name || DEFAULT_TPS_NAME; + const namaPerusahaan = detail.namaPerusahaan || detail.companyName || ''; + + if (tpsData[0]) { + tpsData[0].name = namaTps; + tpsData[0].lokasiAngkutId = detail.lokasiAngkutId || detail.LokasiAngkutID || tpsData[0].lokasiAngkutId; + tpsData[0].spjDetailId = detail.spjDetailId || detail.SpjDetailID || tpsData[0].spjDetailId; + } + + nomorSpj = detail.nomorSpj || nomorSpj; + applyDetailDataToView(detail, namaTps, namaPerusahaan); + renderTpsForm(); + } catch (error) { + console.warn('Gagal memuat detail penjemputan non-TPS:', error); + } + } + + function applyDetailDataToView(detail, namaTps, namaPerusahaan) { + const titleEl = document.getElementById('detail-page-title'); + const badgeEl = document.getElementById('detail-tps-badge'); + const formBadgeEl = document.getElementById('detail-form-badge'); + const companyEl = document.getElementById('detail-company-name'); + const spjEl = document.getElementById('detail-spj-number'); + const addressEl = document.getElementById('detail-address'); + const platEl = document.getElementById('plat-nomor'); + const doorEl = document.getElementById('detail-nomor-pintu'); + + if (titleEl) titleEl.textContent = namaTps; + if (badgeEl) badgeEl.textContent = namaTps; + if (formBadgeEl) formBadgeEl.textContent = namaTps; + if (companyEl && namaPerusahaan) companyEl.textContent = namaPerusahaan; + if (spjEl && detail.nomorSpj) spjEl.textContent = detail.nomorSpj; + if (addressEl && detail.alamat) addressEl.textContent = detail.alamat; + if (platEl && detail.platNomor) platEl.textContent = detail.platNomor; + if (doorEl && detail.nomorPintu) doorEl.textContent = detail.nomorPintu; + document.title = `Detail Penjemputan - ${namaTps}`; + } + function renderTpsForm() { const tps = tpsData[activeTpsIndex]; @@ -62,7 +111,7 @@ document.addEventListener('DOMContentLoaded', function() {
1
-

Foto Kedatangan

+

Foto Kedatangan

Upload foto kedatangan

@@ -102,7 +151,7 @@ document.addEventListener('DOMContentLoaded', function() {
2
-

Foto Timbang Sampah

+

Foto Timbang Sampah

Upload foto timbangan, berat auto terisi

@@ -118,7 +167,7 @@ document.addEventListener('DOMContentLoaded', function() {
3
-

Foto Petugas

+

Foto Petugas

Upload dokumentasi petugas

@@ -127,15 +176,7 @@ document.addEventListener('DOMContentLoaded', function() {
- ${tps.fotoPetugas.length > 0 && !tps.fotoPetugasUploaded ? ` - - ` : tps.fotoPetugasUploaded ? ` -
- ✓ Foto petugas sudah diupload -
- ` : ''} +
${getPetugasUploadStateMarkup(tps)}
@@ -227,6 +268,7 @@ document.addEventListener('DOMContentLoaded', function() { namaPetugasInput.addEventListener('input', function() { tps.namaPetugas = this.value; + refreshPetugasUploadState(form); }); btnAddTimbangan.addEventListener('click', function() { @@ -526,7 +568,7 @@ document.addEventListener('DOMContentLoaded', function() { async function autoFillWeight(file, weightInput, ocrInfoEl) { let guessedWeight = 0; weightInput.placeholder = 'Membaca angka dari foto...'; - if (ocrInfoEl) ocrInfoEl.textContent = 'AI OCR: memproses gambar...'; + if (ocrInfoEl) ocrInfoEl.textContent = 'AI: memproses gambar...'; try { const img = await readFileAsImage(file); @@ -551,12 +593,12 @@ document.addEventListener('DOMContentLoaded', function() { if (ocrInfoEl) { const cleaned = (bestRawText || '').replace(/\s+/g, ' ').trim(); ocrInfoEl.textContent = isSuccess - ? `AI OCR terbaca: ${cleaned}` - : (cleaned ? `AI OCR tidak valid: ${cleaned}` : 'AI OCR tidak menemukan angka valid.'); + ? `AI terbaca: ${cleaned}` + : (cleaned ? `AI tidak valid: ${cleaned}` : 'AI tidak menemukan angka valid.'); } } catch (_) { guessedWeight = 0; - if (ocrInfoEl) ocrInfoEl.textContent = 'AI OCR gagal diproses.'; + if (ocrInfoEl) ocrInfoEl.textContent = 'AI gagal diproses.'; } if (guessedWeight > 0) { @@ -606,18 +648,119 @@ document.addEventListener('DOMContentLoaded', function() { if (grandTotalResiduDisplay) grandTotalResiduDisplay.textContent = formatWeightDisplay(totalResidu); } + function getTimbanganUploadStateMarkup(hasFile, isUploaded, hasValidWeight) { + if (!hasFile) { + return '

Pilih foto timbangan terlebih dahulu

'; + } + + if (isUploaded) { + return ` +
✓ Foto timbangan sudah diupload
+

Kalau mau revisi, pilih file baru di atas. Status upload akan direset otomatis.

+ `; + } + + if (!hasValidWeight) { + return ` + +

Isi berat manual dulu sebelum upload jika berat tidak terbaca.

+ `; + } + + return ` + +

Foto siap diupload.

+ `; + } + + function getPetugasUploadStateMarkup(tps) { + if (tps.fotoPetugasUploaded) { + return '
✓ Foto petugas sudah diupload
'; + } + + if (!tps.fotoPetugas.length) { + return ''; + } + + if (!tps.namaPetugas.trim()) { + return ` + +

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); + } + } + + function refreshTimbanganUploadState(item) { + const stateContainer = item.querySelector('.timbangan-upload-state'); + if (!stateContainer) return; + + const repeater = item.parentElement; + const itemIndex = repeater ? Array.from(repeater.children).indexOf(item) : -1; + const tps = tpsData[activeTpsIndex]; + const currentData = itemIndex >= 0 ? tps.timbangan[itemIndex] : null; + const fileInput = item.querySelector('.input-foto-timbangan'); + const hasFile = Boolean(currentData?.file || fileInput?.files?.[0]); + const isUploaded = Boolean(currentData?.uploaded); + const weightInputValue = item.querySelector('.input-berat-timbangan-value'); + const currentWeight = currentData?.berat && currentData.berat.length > 0 + ? currentData.berat[0] + : parseWeightInput(weightInputValue?.value || '0'); + const hasValidWeight = currentWeight > 0; + + stateContainer.innerHTML = getTimbanganUploadStateMarkup(hasFile, isUploaded, hasValidWeight); + + const uploadBtn = stateContainer.querySelector('.btn-upload-timbangan'); + if (uploadBtn) { + uploadBtn.addEventListener('click', function() { + const latestIndex = repeater ? Array.from(repeater.children).indexOf(item) : -1; + uploadSingleFotoTimbangan(latestIndex, item); + }); + } + } + + function renumberTimbanganItems(repeater) { + const items = repeater.querySelectorAll('.timbangan-item'); + items.forEach((item, index) => { + const newNumber = index + 1; + item.dataset.photoNumber = newNumber; + + const label = item.querySelector('.text-xs.font-bold.text-gray-600'); + if (label) { + label.textContent = `Item Timbangan #${newNumber}`; + } + }); + } + function createTimbanganItem(repeater, existingData = null) { + const photoNumber = repeater.children.length + 1; const item = document.createElement('div'); item.className = 'timbangan-item rounded-2xl border border-gray-200 p-3 space-y-2 bg-gray-50'; + item.dataset.photoNumber = photoNumber; const weight = existingData ? (existingData.berat && existingData.berat.length > 0 ? existingData.berat[0] : 0) : 0; const jenisSampah = existingData ? (existingData.jenisSampah && existingData.jenisSampah.length > 0 ? existingData.jenisSampah[0] : DEFAULT_JENIS) : DEFAULT_JENIS; const hasFile = existingData && existingData.file; const isUploaded = existingData && existingData.uploaded; + const ocrInfoText = existingData && existingData.ocrInfo ? existingData.ocrInfo : (hasFile ? 'OCR: diproses.' : 'OCR: belum diproses.'); item.innerHTML = `
-

Item Timbangan

+

Item Timbangan #${photoNumber}

@@ -625,10 +768,8 @@ document.addEventListener('DOMContentLoaded', function() { Preview foto timbangan
-

${hasFile ? 'OCR: diproses.' : 'OCR: belum diproses.'}

- ${hasFile && !isUploaded ? ` - - ` : isUploaded ? `
✓ Foto timbangan sudah diupload
` : ''} +

${ocrInfoText}

+
${getTimbanganUploadStateMarkup(hasFile, isUploaded, weight > 0)}
@@ -662,7 +803,7 @@ document.addEventListener('DOMContentLoaded', function() { fileInput.addEventListener('change', async function() { if (fileInput.files && fileInput.files[0]) { const originalFile = fileInput.files[0]; - const photoNumber = Array.from(repeater.children).indexOf(item) + 1; + const photoNumber = Number(item.dataset.photoNumber || (Array.from(repeater.children).indexOf(item) + 1)); const watermarkedFile = await applyWatermark(originalFile, photoNumber); const dataTransfer = new DataTransfer(); @@ -684,16 +825,7 @@ document.addEventListener('DOMContentLoaded', function() { const itemIndex = Array.from(repeater.children).indexOf(item); if (itemIndex >= 0 && tps.timbangan[itemIndex]) { tps.timbangan[itemIndex].uploaded = false; - const existingUploadBtn = item.querySelector('.btn-upload-timbangan'); - if (!existingUploadBtn) { - const ocrInfo = item.querySelector('.input-ocr-info'); - const uploadBtn = document.createElement('button'); - uploadBtn.type = 'button'; - uploadBtn.className = 'btn-upload-timbangan w-full bg-blue-500 text-white py-2 rounded-xl font-bold text-xs hover:brightness-110'; - uploadBtn.textContent = 'Upload Foto Timbangan Ini'; - uploadBtn.addEventListener('click', function() { uploadSingleFotoTimbangan(itemIndex); }); - ocrInfo.parentNode.insertBefore(uploadBtn, ocrInfo.nextSibling); - } + refreshTimbanganUploadState(item); } } }); @@ -705,6 +837,7 @@ document.addEventListener('DOMContentLoaded', function() { weightInputValue.value = parsed.toFixed(2); updateTpsTotalTimbangan(); syncTimbanganToTpsData(); + refreshTimbanganUploadState(item); }); weightInputDisplay.addEventListener('blur', function() { @@ -718,6 +851,7 @@ document.addEventListener('DOMContentLoaded', function() { } updateTpsTotalTimbangan(); syncTimbanganToTpsData(); + refreshTimbanganUploadState(item); }); jenisSampahSelect.addEventListener('change', function() { @@ -729,20 +863,16 @@ document.addEventListener('DOMContentLoaded', function() { item.remove(); const form = tpsContentContainer.querySelector('form'); const rep = form ? form.querySelector('.tps-timbangan-repeater') : null; - if (rep && rep.children.length === 0) createTimbanganItem(rep); + if (rep) { + renumberTimbanganItems(rep); + if (rep.children.length === 0) createTimbanganItem(rep); + } updateTpsTotalTimbangan(); syncTimbanganToTpsData(); }); - const btnUploadTimbangan = item.querySelector('.btn-upload-timbangan'); - if (btnUploadTimbangan) { - btnUploadTimbangan.addEventListener('click', function() { - const itemIndex = Array.from(repeater.children).indexOf(item); - uploadSingleFotoTimbangan(itemIndex); - }); - } - repeater.appendChild(item); + refreshTimbanganUploadState(item); return item; } @@ -753,20 +883,23 @@ document.addEventListener('DOMContentLoaded', function() { const repeater = form.querySelector('.tps-timbangan-repeater'); const items = repeater.querySelectorAll('.timbangan-item'); + const previousTimbangan = [...tps.timbangan]; tps.timbangan = []; - items.forEach(item => { + items.forEach((item, index) => { const fileInput = item.querySelector('.input-foto-timbangan'); const weightValue = item.querySelector('.input-berat-timbangan-value'); const weight = parseWeightInput(weightValue.value); const jenisSampah = item.querySelector('.input-jenis-sampah').value; + const ocrInfo = item.querySelector('.input-ocr-info')?.textContent || 'OCR: belum diproses.'; tps.timbangan.push({ file: fileInput.files[0] || null, berat: [weight], jenisSampah: [jenisSampah], lokasiAngkut: [], - uploaded: false + uploaded: previousTimbangan[index]?.uploaded ?? false, + ocrInfo }); }); } @@ -803,14 +936,32 @@ document.addEventListener('DOMContentLoaded', function() { return formData; } - function uploadSingleFotoTimbangan(itemIndex) { + function uploadSingleFotoTimbangan(itemIndex, targetItem = null) { const tps = tpsData[activeTpsIndex]; if (!tps.timbangan[itemIndex] || !tps.timbangan[itemIndex].file) { alert('Belum ada foto timbangan yang dipilih!'); return; } - alert(`Upload foto timbangan #${itemIndex + 1}\nBerat: ${tps.timbangan[itemIndex].weight} kg\n(Implementasi upload ke server)`); + const weight = tps.timbangan[itemIndex].berat && tps.timbangan[itemIndex].berat.length > 0 + ? tps.timbangan[itemIndex].berat[0] + : 0; + if (weight <= 0) { + alert('Berat belum valid. Isi manual dulu sebelum upload foto timbangan.'); + return; + } + alert(`Upload foto timbangan #${itemIndex + 1}\nBerat: ${formatWeightDisplay(weight)} kg\n(Implementasi upload ke server)`); tps.timbangan[itemIndex].uploaded = true; + + if (!targetItem) { + const form = tpsContentContainer.querySelector('form'); + const repeater = form ? form.querySelector('.tps-timbangan-repeater') : null; + const items = repeater ? repeater.querySelectorAll('.timbangan-item') : []; + targetItem = items[itemIndex] || null; + } + + if (targetItem) { + refreshTimbanganUploadState(targetItem); + } } function uploadFotoKedatangan() { @@ -830,7 +981,11 @@ document.addEventListener('DOMContentLoaded', function() { alert('Belum ada foto petugas yang dipilih!'); return; } - alert(`Upload ${tps.fotoPetugas.length} foto petugas\n(Implementasi upload ke server)`); + if (!tps.namaPetugas.trim()) { + alert('Nama petugas wajib diisi sebelum upload foto petugas!'); + return; + } + alert(`Upload ${tps.fotoPetugas.length} foto petugas untuk ${tps.name}\n(Implementasi upload ke server)`); tps.fotoPetugasUploaded = true; renderTpsForm(); } @@ -842,7 +997,7 @@ document.addEventListener('DOMContentLoaded', function() { if (!tps.fotoPetugas.length) return alert('Foto petugas belum diupload!'); if (!tps.namaPetugas.trim()) return alert('Nama petugas belum diisi!'); - alert(`Validasi OK (Tanpa TPS).\n- Organik: ${formatWeightDisplay(tps.totalOrganik)} kg\n- Anorganik: ${formatWeightDisplay(tps.totalAnorganik)} kg\n- Residu: ${formatWeightDisplay(tps.totalResidu)} kg\n- Total: ${formatWeightDisplay(tps.totalTimbangan)} kg\n- Petugas: ${tps.namaPetugas}`); + alert(`Validasi OK (${tps.name}).\n- Organik: ${formatWeightDisplay(tps.totalOrganik)} kg\n- Anorganik: ${formatWeightDisplay(tps.totalAnorganik)} kg\n- Residu: ${formatWeightDisplay(tps.totalResidu)} kg\n- Total: ${formatWeightDisplay(tps.totalTimbangan)} kg\n- Petugas: ${tps.namaPetugas}`); tps.submitted = true; /* @@ -857,4 +1012,5 @@ document.addEventListener('DOMContentLoaded', function() { } initializeLocation(); + loadDetailData(); }); diff --git a/wwwroot/driver/js/detail-penjemputan-tps.js b/wwwroot/driver/js/detail-penjemputan-tps.js index bc961a3..fe86162 100644 --- a/wwwroot/driver/js/detail-penjemputan-tps.js +++ b/wwwroot/driver/js/detail-penjemputan-tps.js @@ -312,15 +312,7 @@ const DetailPenjemputan = (function() {
- ${tps.fotoPetugas.length > 0 && !tps.fotoPetugasUploaded ? ` - - ` : tps.fotoPetugasUploaded ? ` -
- ✓ Foto petugas sudah diupload -
- ` : ''} +
${getPetugasUploadStateMarkup(tps)}
@@ -356,6 +348,7 @@ const DetailPenjemputan = (function() { namaPetugasInput.addEventListener('input', function() { tps.namaPetugas = this.value; + refreshPetugasUploadState(form); }); btnAddTimbangan.addEventListener('click', function() { @@ -546,6 +539,7 @@ const DetailPenjemputan = (function() { const jenisSampah = existingData ? existingData.jenisSampah : CONFIG.DEFAULT_JENIS; const hasFile = existingData && existingData.file; const isUploaded = existingData && existingData.uploaded; + const ocrInfoText = existingData && existingData.ocrInfo ? existingData.ocrInfo : (hasFile ? 'OCR: diproses.' : 'OCR: belum diproses.'); item.innerHTML = `
@@ -556,16 +550,8 @@ const DetailPenjemputan = (function() {
Preview foto timbangan
-

${hasFile ? 'OCR: diproses.' : 'OCR: belum diproses.'}

- ${hasFile && !isUploaded ? ` - - ` : isUploaded ? ` -
- ✓ Foto timbangan sudah diupload -
- ` : ''} +

${ocrInfoText}

+
${getTimbanganUploadStateMarkup(hasFile, isUploaded, weight > 0)}
@@ -625,19 +611,7 @@ const DetailPenjemputan = (function() { const itemIndex = Array.from(repeater.children).indexOf(item); if (itemIndex >= 0 && tps.timbangan[itemIndex]) { tps.timbangan[itemIndex].uploaded = false; - - const existingUploadBtn = item.querySelector('.btn-upload-timbangan'); - if (!existingUploadBtn) { - const ocrInfo = item.querySelector('.input-ocr-info'); - const uploadBtn = document.createElement('button'); - uploadBtn.type = 'button'; - uploadBtn.className = 'btn-upload-timbangan w-full bg-blue-500 text-white py-2 rounded-xl font-bold text-xs hover:brightness-110'; - uploadBtn.textContent = 'Upload Foto Timbangan Ini'; - uploadBtn.addEventListener('click', function() { - uploadSingleFotoTimbangan(itemIndex); - }); - ocrInfo.parentNode.insertBefore(uploadBtn, ocrInfo.nextSibling); - } + refreshTimbanganUploadState(item); } } }); @@ -649,6 +623,7 @@ const DetailPenjemputan = (function() { weightInputValue.value = parsed.toFixed(2); updateTpsTotalTimbangan(); syncTimbanganToTpsData(); + refreshTimbanganUploadState(item); }); weightInputDisplay.addEventListener('blur', function() { @@ -662,6 +637,7 @@ const DetailPenjemputan = (function() { } updateTpsTotalTimbangan(); syncTimbanganToTpsData(); + refreshTimbanganUploadState(item); }); jenisSampahSelect.addEventListener('change', function() { @@ -685,16 +661,92 @@ const DetailPenjemputan = (function() { syncTimbanganToTpsData(); }); - const btnUploadTimbangan = item.querySelector('.btn-upload-timbangan'); - if (btnUploadTimbangan) { - btnUploadTimbangan.addEventListener('click', function() { - const itemIndex = Array.from(repeater.children).indexOf(item); - uploadSingleFotoTimbangan(itemIndex); - }); + repeater.appendChild(item); + refreshTimbanganUploadState(item); + return item; + } + + function getTimbanganUploadStateMarkup(hasFile, isUploaded, hasValidWeight) { + if (!hasFile) { + return '

Pilih foto timbangan terlebih dahulu

'; } - repeater.appendChild(item); - return item; + if (isUploaded) { + return ` +
✓ Foto timbangan sudah diupload
+

Kalau mau revisi, pilih file baru di atas. Status upload akan direset otomatis.

+ `; + } + + if (!hasValidWeight) { + return ` + +

Isi berat manual dulu sebelum upload jika berat tidak terbaca.

+ `; + } + + return ` + +

Foto siap diupload.

+ `; + } + + function getPetugasUploadStateMarkup(tps) { + if (tps.fotoPetugasUploaded) { + return '
✓ Foto petugas sudah diupload
'; + } + + if (!tps.fotoPetugas.length) { + return ''; + } + + if (!tps.namaPetugas.trim()) { + return ` + +

Isi nama petugas terlebih dahulu

+ `; + } + + return ``; + } + + function refreshPetugasUploadState(form) { + const stateContainer = form.querySelector('.petugas-upload-state'); + if (!stateContainer) return; + + const tps = state.tpsData[state.activeTpsIndex]; + stateContainer.innerHTML = getPetugasUploadStateMarkup(tps); + + const btnUploadPetugas = stateContainer.querySelector('.tps-btn-upload-petugas:not([disabled])'); + if (btnUploadPetugas) { + btnUploadPetugas.addEventListener('click', uploadFotoPetugas); + } + } + + function refreshTimbanganUploadState(item) { + const stateContainer = item.querySelector('.timbangan-upload-state'); + if (!stateContainer) return; + + const repeater = item.parentElement; + const itemIndex = repeater ? Array.from(repeater.children).indexOf(item) : -1; + const tps = state.tpsData[state.activeTpsIndex]; + const currentData = itemIndex >= 0 ? tps.timbangan[itemIndex] : null; + const fileInput = item.querySelector('.input-foto-timbangan'); + const hasFile = Boolean(currentData?.file || fileInput?.files?.[0]); + const isUploaded = Boolean(currentData?.uploaded); + const weightInputValue = item.querySelector('.input-berat-timbangan-value'); + const currentWeight = currentData?.weight ?? parseWeightInput(weightInputValue?.value || '0'); + const hasValidWeight = currentWeight > 0; + + stateContainer.innerHTML = getTimbanganUploadStateMarkup(hasFile, isUploaded, hasValidWeight); + + const uploadBtn = stateContainer.querySelector('.btn-upload-timbangan'); + if (uploadBtn) { + uploadBtn.addEventListener('click', function() { + const latestIndex = repeater ? Array.from(repeater.children).indexOf(item) : -1; + uploadSingleFotoTimbangan(latestIndex, item); + }); + } } function renumberTimbanganItems(repeater) { @@ -1023,26 +1075,27 @@ async function applyWatermark(file, photoNumber) { const repeater = form.querySelector('.tps-timbangan-repeater'); const items = repeater.querySelectorAll('.timbangan-item'); + const previousTimbangan = [...tps.timbangan]; tps.timbangan = []; - items.forEach(item => { + items.forEach((item, index) => { const fileInput = item.querySelector('.input-foto-timbangan'); const weightValue = item.querySelector('.input-berat-timbangan-value'); const jenisSampahSelect = item.querySelector('.input-jenis-sampah'); - - const existingIndex = tps.timbangan.length; - const existingData = tps.timbangan[existingIndex]; + const ocrInfo = item.querySelector('.input-ocr-info')?.textContent || 'OCR: belum diproses.'; + const existingData = previousTimbangan[index]; tps.timbangan.push({ file: fileInput.files[0] || (existingData ? existingData.file : null), weight: parseWeightInput(weightValue.value), jenisSampah: jenisSampahSelect.value, - uploaded: existingData ? existingData.uploaded : false + uploaded: existingData ? existingData.uploaded : false, + ocrInfo }); }); } - function uploadSingleFotoTimbangan(itemIndex) { + function uploadSingleFotoTimbangan(itemIndex, targetItem = null) { const tps = state.tpsData[state.activeTpsIndex]; if (!tps.timbangan[itemIndex] || !tps.timbangan[itemIndex].file) { @@ -1051,29 +1104,24 @@ async function applyWatermark(file, photoNumber) { } const timbanganItem = tps.timbangan[itemIndex]; + if (timbanganItem.weight <= 0) { + alert('Berat belum valid. Isi manual dulu sebelum upload foto timbangan.'); + return; + } alert(`Upload foto timbangan #${itemIndex + 1} untuk ${tps.name}\nJenis: ${timbanganItem.jenisSampah}\nBerat: ${timbanganItem.weight} kg\n(Implementasi upload ke server)`); timbanganItem.uploaded = true; - - const form = elements.tpsContentContainer.querySelector('form'); - const repeater = form.querySelector('.tps-timbangan-repeater'); - const items = repeater.querySelectorAll('.timbangan-item'); - const targetItem = items[itemIndex]; - + + if (!targetItem) { + const form = elements.tpsContentContainer.querySelector('form'); + const repeater = form ? form.querySelector('.tps-timbangan-repeater') : null; + const items = repeater ? repeater.querySelectorAll('.timbangan-item') : []; + targetItem = items[itemIndex] || null; + } + if (targetItem) { - const uploadBtn = targetItem.querySelector('.btn-upload-timbangan'); - if (uploadBtn) { - uploadBtn.remove(); - } - - const ocrInfo = targetItem.querySelector('.input-ocr-info'); - if (ocrInfo && !targetItem.querySelector('.upload-success-message')) { - const successMsg = document.createElement('div'); - successMsg.className = 'text-center text-xs text-green-600 font-bold py-2 upload-success-message'; - successMsg.textContent = '✓ Foto timbangan sudah diupload'; - ocrInfo.parentNode.insertBefore(successMsg, ocrInfo.nextSibling); - } + refreshTimbanganUploadState(targetItem); } } @@ -1096,6 +1144,10 @@ async function applyWatermark(file, photoNumber) { alert('Belum ada foto petugas yang dipilih!'); return; } + if (!tps.namaPetugas.trim()) { + alert('Nama petugas wajib diisi sebelum upload foto petugas!'); + return; + } alert(`Upload ${tps.fotoPetugas.length} foto petugas untuk ${tps.name}\n(Implementasi upload ke server)`); diff --git a/wwwroot/driver/json/detail-penjemputan-non-tps.json b/wwwroot/driver/json/detail-penjemputan-non-tps.json new file mode 100644 index 0000000..c2f91f5 --- /dev/null +++ b/wwwroot/driver/json/detail-penjemputan-non-tps.json @@ -0,0 +1,12 @@ +{ + "detailPenjemputan": { + "namaTps": "TPS A", + "namaPerusahaan": "CV Tri Berkah Sejahtera", + "nomorSpj": "SPJ/07-2025/PKM/000476", + "platNomor": "B 9632 TOR", + "nomorPintu": "JRC 005", + "alamat": "Kp. Pertanian II Rt.004 Rw.001 Kel. Klender Kec, Duren Sawit, Kota Adm. Jakarta Timur 13470", + "lokasiAngkutId": "", + "spjDetailId": "" + } +} \ No newline at end of file