update: fixing detail
parent
f9b74caedc
commit
5b71625672
|
|
@ -4,6 +4,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="w-full lg:max-w-sm mx-auto min-h-screen bg-gray-50 pb-24">
|
<div class="w-full lg:max-w-sm mx-auto min-h-screen bg-gray-50 pb-24">
|
||||||
|
<form id="upst-antiforgery" class="hidden" aria-hidden="true">
|
||||||
|
@Html.AntiForgeryToken()
|
||||||
|
</form>
|
||||||
|
|
||||||
<div class="bg-upst text-white px-6 pt-8 pb-16 rounded-b-[40px] shadow-lg relative">
|
<div class="bg-upst text-white px-6 pt-8 pb-16 rounded-b-[40px] shadow-lg relative">
|
||||||
<div class="flex items-center justify-between relative z-10">
|
<div class="flex items-center justify-between relative z-10">
|
||||||
<a href="@Url.Action("Index", "Home")" class="w-10 h-10 flex items-center justify-center bg-white/10 rounded-xl backdrop-blur-md">
|
<a href="@Url.Action("Index", "Home")" class="w-10 h-10 flex items-center justify-center bg-white/10 rounded-xl backdrop-blur-md">
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter+Tight:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter+Tight:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="@Url.Content("~/driver/css/watch.css")" asp-append-version="true" />
|
<link rel="stylesheet" href="@Url.Content("~/driver/css/watch.css")" asp-append-version="true" />
|
||||||
<link rel="stylesheet" href="@Url.Content("~/driver/css/website.css")" asp-append-version="true" />
|
|
||||||
<link rel="stylesheet" href="@Url.Content("~/driver/css/leaflet.css")" asp-append-version="true" />
|
<link rel="stylesheet" href="@Url.Content("~/driver/css/leaflet.css")" asp-append-version="true" />
|
||||||
<link rel="stylesheet" href="@Url.Content("~/driver/eSPJ.styles.css")" asp-append-version="true" />
|
<link rel="stylesheet" href="@Url.Content("~/driver/eSPJ.styles.css")" asp-append-version="true" />
|
||||||
@await RenderSectionAsync("Styles", required: false)
|
@await RenderSectionAsync("Styles", required: false)
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@
|
||||||
"tailwindcss": "^4.1.11"
|
"tailwindcss": "^4.1.11"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "npx tailwindcss -i ./wwwroot/driver/css/site.css -o ./wwwroot/driver/css/watch.css --watch & dotnet watch run",
|
"dev": "npx @tailwindcss/cli -i ./wwwroot/driver/css/site.css -o ./wwwroot/driver/css/watch.css --watch",
|
||||||
"watch": "npx @tailwindcss/cli -i ./wwwroot/driver/css/site.css -o ./wwwroot/driver/css/watch.css --watch",
|
|
||||||
"build": "npx @tailwindcss/cli -i ./wwwroot/driver/css/site.css -o ./wwwroot/driver/css/watch.css --minify"
|
"build": "npx @tailwindcss/cli -i ./wwwroot/driver/css/site.css -o ./wwwroot/driver/css/watch.css --minify"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,7 @@
|
||||||
.bg-upst-light {
|
.bg-upst-light {
|
||||||
@apply bg-[#e4f2e3];
|
@apply bg-[#e4f2e3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: "Inter Tight", sans-serif;
|
||||||
|
}
|
||||||
|
|
@ -905,6 +905,9 @@
|
||||||
.h-32 {
|
.h-32 {
|
||||||
height: calc(var(--spacing) * 32);
|
height: calc(var(--spacing) * 32);
|
||||||
}
|
}
|
||||||
|
.h-40 {
|
||||||
|
height: calc(var(--spacing) * 40);
|
||||||
|
}
|
||||||
.h-44 {
|
.h-44 {
|
||||||
height: calc(var(--spacing) * 44);
|
height: calc(var(--spacing) * 44);
|
||||||
}
|
}
|
||||||
|
|
@ -1157,6 +1160,9 @@
|
||||||
.grid-cols-2 {
|
.grid-cols-2 {
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
.grid-cols-3 {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
.grid-cols-4 {
|
.grid-cols-4 {
|
||||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
|
@ -1574,6 +1580,9 @@
|
||||||
.border-yellow-200 {
|
.border-yellow-200 {
|
||||||
border-color: var(--color-yellow-200);
|
border-color: var(--color-yellow-200);
|
||||||
}
|
}
|
||||||
|
.border-t-red-500 {
|
||||||
|
border-top-color: var(--color-red-500);
|
||||||
|
}
|
||||||
.border-t-transparent {
|
.border-t-transparent {
|
||||||
border-top-color: transparent;
|
border-top-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
@ -2854,11 +2863,21 @@
|
||||||
border-width: 0px;
|
border-width: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.file\:bg-red-500 {
|
||||||
|
&::file-selector-button {
|
||||||
|
background-color: var(--color-red-500);
|
||||||
|
}
|
||||||
|
}
|
||||||
.file\:px-3 {
|
.file\:px-3 {
|
||||||
&::file-selector-button {
|
&::file-selector-button {
|
||||||
padding-inline: calc(var(--spacing) * 3);
|
padding-inline: calc(var(--spacing) * 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.file\:px-4 {
|
||||||
|
&::file-selector-button {
|
||||||
|
padding-inline: calc(var(--spacing) * 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
.file\:py-2 {
|
.file\:py-2 {
|
||||||
&::file-selector-button {
|
&::file-selector-button {
|
||||||
padding-block: calc(var(--spacing) * 2);
|
padding-block: calc(var(--spacing) * 2);
|
||||||
|
|
@ -2979,6 +2998,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.hover\:bg-green-200 {
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
background-color: var(--color-green-200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.hover\:bg-green-600 {
|
.hover\:bg-green-600 {
|
||||||
&:hover {
|
&:hover {
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
|
|
@ -3068,6 +3094,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.hover\:to-gray-700 {
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
--tw-gradient-to: var(--color-gray-700);
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.hover\:to-orange-500 {
|
.hover\:to-orange-500 {
|
||||||
&:hover {
|
&:hover {
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
|
|
@ -3151,6 +3185,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.hover\:file\:bg-red-600 {
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
&::file-selector-button {
|
||||||
|
background-color: var(--color-red-600);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.focus\:border-gray-500 {
|
.focus\:border-gray-500 {
|
||||||
&:focus {
|
&:focus {
|
||||||
border-color: var(--color-gray-500);
|
border-color: var(--color-gray-500);
|
||||||
|
|
@ -3236,6 +3279,9 @@
|
||||||
.bg-upst-light {
|
.bg-upst-light {
|
||||||
background-color: #e4f2e3;
|
background-color: #e4f2e3;
|
||||||
}
|
}
|
||||||
|
body {
|
||||||
|
font-family: "Inter Tight", sans-serif;
|
||||||
|
}
|
||||||
@property --tw-translate-x {
|
@property --tw-translate-x {
|
||||||
syntax: "*";
|
syntax: "*";
|
||||||
inherits: false;
|
inherits: false;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
body {
|
|
||||||
font-family: "Inter Tight", sans-serif;
|
|
||||||
}
|
|
||||||
|
|
@ -157,11 +157,19 @@ const DetailPenjemputan = (function() {
|
||||||
state.tpsData.forEach((tps, index) => {
|
state.tpsData.forEach((tps, index) => {
|
||||||
const tab = document.createElement('button');
|
const tab = document.createElement('button');
|
||||||
tab.type = 'button';
|
tab.type = 'button';
|
||||||
tab.className = `px-4 py-2 rounded-xl font-bold text-sm whitespace-nowrap transition ${
|
const isActive = index === state.activeTpsIndex;
|
||||||
index === state.activeTpsIndex
|
const isSubmitted = !!tps.submitted;
|
||||||
? 'bg-upst text-white'
|
|
||||||
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
|
let tabClass = 'bg-gray-100 text-gray-600 hover:bg-gray-200';
|
||||||
}`;
|
if (isSubmitted) {
|
||||||
|
tabClass = isActive
|
||||||
|
? 'bg-green-600 text-white'
|
||||||
|
: 'bg-green-100 text-green-700 hover:bg-green-200';
|
||||||
|
} else if (isActive) {
|
||||||
|
tabClass = 'bg-upst text-white';
|
||||||
|
}
|
||||||
|
|
||||||
|
tab.className = `px-4 py-2 rounded-xl font-bold text-sm whitespace-nowrap transition ${tabClass}`;
|
||||||
tab.textContent = tps.name;
|
tab.textContent = tps.name;
|
||||||
if (tps.submitted) {
|
if (tps.submitted) {
|
||||||
tab.innerHTML += ' <span class="text-xs">✓</span>';
|
tab.innerHTML += ' <span class="text-xs">✓</span>';
|
||||||
|
|
@ -517,7 +525,6 @@ const DetailPenjemputan = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTimbanganItem(repeater, existingData = null) {
|
function createTimbanganItem(repeater, existingData = null) {
|
||||||
// Calculate photo number dynamically based on position
|
|
||||||
const photoNumber = repeater.children.length + 1;
|
const photoNumber = repeater.children.length + 1;
|
||||||
|
|
||||||
const item = document.createElement('div');
|
const item = document.createElement('div');
|
||||||
|
|
@ -586,7 +593,6 @@ const DetailPenjemputan = (function() {
|
||||||
|
|
||||||
const watermarkedFile = await applyWatermark(originalFile, photoNumber);
|
const watermarkedFile = await applyWatermark(originalFile, photoNumber);
|
||||||
|
|
||||||
// Update file input dengan watermarked file
|
|
||||||
const dataTransfer = new DataTransfer();
|
const dataTransfer = new DataTransfer();
|
||||||
dataTransfer.items.add(watermarkedFile);
|
dataTransfer.items.add(watermarkedFile);
|
||||||
fileInput.files = dataTransfer.files;
|
fileInput.files = dataTransfer.files;
|
||||||
|
|
@ -657,7 +663,6 @@ const DetailPenjemputan = (function() {
|
||||||
const form = elements.tpsContentContainer.querySelector('form');
|
const form = elements.tpsContentContainer.querySelector('form');
|
||||||
const repeater = form ? form.querySelector('.tps-timbangan-repeater') : null;
|
const repeater = form ? form.querySelector('.tps-timbangan-repeater') : null;
|
||||||
|
|
||||||
// Renumber all remaining items
|
|
||||||
if (repeater) {
|
if (repeater) {
|
||||||
renumberTimbanganItems(repeater);
|
renumberTimbanganItems(repeater);
|
||||||
if (repeater.children.length === 0) {
|
if (repeater.children.length === 0) {
|
||||||
|
|
@ -687,7 +692,6 @@ const DetailPenjemputan = (function() {
|
||||||
const newNumber = index + 1;
|
const newNumber = index + 1;
|
||||||
item.dataset.photoNumber = newNumber;
|
item.dataset.photoNumber = newNumber;
|
||||||
|
|
||||||
// Update label text
|
|
||||||
const label = item.querySelector('.text-xs.font-bold.text-gray-600');
|
const label = item.querySelector('.text-xs.font-bold.text-gray-600');
|
||||||
if (label) {
|
if (label) {
|
||||||
label.textContent = `Item Timbangan #${newNumber}`;
|
label.textContent = `Item Timbangan #${newNumber}`;
|
||||||
|
|
@ -769,7 +773,6 @@ async function applyWatermark(file, photoNumber) {
|
||||||
ctx.fillStyle = 'rgba(15, 23, 42, 0.85)';
|
ctx.fillStyle = 'rgba(15, 23, 42, 0.85)';
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
|
|
||||||
// Garis Aksen Vertikal
|
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
const accentWidth = baseFontSize * 0.3;
|
const accentWidth = baseFontSize * 0.3;
|
||||||
if (ctx.roundRect) {
|
if (ctx.roundRect) {
|
||||||
|
|
@ -1089,6 +1092,48 @@ async function applyWatermark(file, photoNumber) {
|
||||||
renderTpsForm();
|
renderTpsForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildSubmitFormData(tps) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('TpsName', tps.name);
|
||||||
|
formData.append('Latitude', tps.latitude);
|
||||||
|
formData.append('Longitude', tps.longitude);
|
||||||
|
formData.append('AlamatJalan', tps.alamatJalan);
|
||||||
|
formData.append('WaktuKedatangan', tps.waktuKedatangan);
|
||||||
|
formData.append('TotalTimbangan', tps.totalTimbangan);
|
||||||
|
formData.append('TotalOrganik', tps.totalOrganik);
|
||||||
|
formData.append('TotalAnorganik', tps.totalAnorganik);
|
||||||
|
formData.append('TotalResidu', tps.totalResidu);
|
||||||
|
formData.append('NamaPetugas', tps.namaPetugas);
|
||||||
|
|
||||||
|
tps.fotoKedatangan.forEach((file) => {
|
||||||
|
formData.append('FotoKedatangan', file);
|
||||||
|
});
|
||||||
|
|
||||||
|
tps.timbangan.forEach((timb) => {
|
||||||
|
if (timb.file) formData.append('FotoTimbangan', timb.file);
|
||||||
|
formData.append('BeratTimbangan', timb.weight);
|
||||||
|
formData.append('JenisSampahList', timb.jenisSampah);
|
||||||
|
});
|
||||||
|
|
||||||
|
tps.fotoPetugas.forEach((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;
|
||||||
|
}
|
||||||
|
|
||||||
|
function markTpsSubmitted(tps) {
|
||||||
|
tps.submitted = true;
|
||||||
|
if (state.selectedTpsList.length > 1) {
|
||||||
|
renderTabs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function submitTpsData() {
|
function submitTpsData() {
|
||||||
const tps = state.tpsData[state.activeTpsIndex];
|
const tps = state.tpsData[state.activeTpsIndex];
|
||||||
|
|
||||||
|
|
@ -1109,56 +1154,40 @@ async function applyWatermark(file, photoNumber) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const formData = new FormData();
|
// MODE STATIK (aktif sekarang)
|
||||||
formData.append('TpsName', tps.name);
|
// Cuma validasi + tandai TPS selesai, ga kirim ke backend.
|
||||||
formData.append('Latitude', tps.latitude);
|
markTpsSubmitted(tps);
|
||||||
formData.append('Longitude', tps.longitude);
|
alert(`Validasi ${tps.name} OK. Data belum dikirim ke server (mode statik).`);
|
||||||
formData.append('AlamatJalan', tps.alamatJalan);
|
|
||||||
formData.append('WaktuKedatangan', tps.waktuKedatangan);
|
|
||||||
formData.append('TotalTimbangan', tps.totalTimbangan);
|
|
||||||
formData.append('TotalOrganik', tps.totalOrganik);
|
|
||||||
formData.append('TotalAnorganik', tps.totalAnorganik);
|
|
||||||
formData.append('TotalResidu', tps.totalResidu);
|
|
||||||
formData.append('NamaPetugas', tps.namaPetugas);
|
|
||||||
|
|
||||||
tps.fotoKedatangan.forEach((file) => {
|
// MODE PRODUCTION (aktifkan kalau backend udah ready mas ebik)
|
||||||
formData.append(`FotoKedatangan`, file);
|
/*
|
||||||
});
|
const formData = buildSubmitFormData(tps);
|
||||||
|
|
||||||
tps.timbangan.forEach((timb) => {
|
|
||||||
if (timb.file) formData.append(`FotoTimbangan`, timb.file);
|
|
||||||
formData.append(`BeratTimbangan`, timb.weight);
|
|
||||||
formData.append(`JenisSampahList`, timb.jenisSampah);
|
|
||||||
});
|
|
||||||
|
|
||||||
tps.fotoPetugas.forEach((file) => {
|
|
||||||
formData.append(`FotoPetugas`, file);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Submit to server
|
|
||||||
fetch('/upst/detail-penjemputan', {
|
fetch('/upst/detail-penjemputan', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(async response => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
tps.submitted = true;
|
markTpsSubmitted(tps);
|
||||||
if (state.selectedTpsList.length > 1) {
|
|
||||||
renderTabs();
|
|
||||||
}
|
|
||||||
alert(`Data ${tps.name} berhasil disimpan!`);
|
alert(`Data ${tps.name} berhasil disimpan!`);
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
} else {
|
} else {
|
||||||
alert('Gagal menyimpan data. Silakan coba lagi.');
|
const errorText = await response.text();
|
||||||
|
if (response.status === 400) {
|
||||||
|
alert('Sesi submit tidak valid. Silakan refresh halaman lalu coba lagi.');
|
||||||
|
} else {
|
||||||
|
alert(errorText || 'Gagal menyimpan data. Silakan coba lagi.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
alert('Terjadi kesalahan saat menyimpan data.');
|
alert('Terjadi kesalahan saat menyimpan data.');
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility functions
|
|
||||||
function formatWeightDisplay(value) {
|
function formatWeightDisplay(value) {
|
||||||
if (isNaN(value)) return '0,00';
|
if (isNaN(value)) return '0,00';
|
||||||
return value.toFixed(2).replace('.', ',');
|
return value.toFixed(2).replace('.', ',');
|
||||||
|
|
@ -1176,7 +1205,6 @@ async function applyWatermark(file, photoNumber) {
|
||||||
return `${mb.toFixed(2)} MB`;
|
return `${mb.toFixed(2)} MB`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public API
|
|
||||||
return {
|
return {
|
||||||
init: init,
|
init: init,
|
||||||
setNomorSpj: function(nomorSpj) {
|
setNomorSpj: function(nomorSpj) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue