update: fixing detail

main
muamars 2026-03-05 15:42:22 +07:00
parent f9b74caedc
commit 5b71625672
7 changed files with 127 additions and 50 deletions

View File

@ -4,6 +4,10 @@
}
<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="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">

View File

@ -31,7 +31,6 @@
<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 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/eSPJ.styles.css")" asp-append-version="true" />
@await RenderSectionAsync("Styles", required: false)

View File

@ -4,8 +4,7 @@
"tailwindcss": "^4.1.11"
},
"scripts": {
"dev": "npx tailwindcss -i ./wwwroot/driver/css/site.css -o ./wwwroot/driver/css/watch.css --watch & dotnet watch run",
"watch": "npx @tailwindcss/cli -i ./wwwroot/driver/css/site.css -o ./wwwroot/driver/css/watch.css --watch",
"dev": "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"
}
}

View File

@ -7,3 +7,7 @@
.bg-upst-light {
@apply bg-[#e4f2e3];
}
body {
font-family: "Inter Tight", sans-serif;
}

View File

@ -905,6 +905,9 @@
.h-32 {
height: calc(var(--spacing) * 32);
}
.h-40 {
height: calc(var(--spacing) * 40);
}
.h-44 {
height: calc(var(--spacing) * 44);
}
@ -1157,6 +1160,9 @@
.grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.grid-cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
@ -1574,6 +1580,9 @@
.border-yellow-200 {
border-color: var(--color-yellow-200);
}
.border-t-red-500 {
border-top-color: var(--color-red-500);
}
.border-t-transparent {
border-top-color: transparent;
}
@ -2854,11 +2863,21 @@
border-width: 0px;
}
}
.file\:bg-red-500 {
&::file-selector-button {
background-color: var(--color-red-500);
}
}
.file\:px-3 {
&::file-selector-button {
padding-inline: calc(var(--spacing) * 3);
}
}
.file\:px-4 {
&::file-selector-button {
padding-inline: calc(var(--spacing) * 4);
}
}
.file\:py-2 {
&::file-selector-button {
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 {
@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 {
@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-color: var(--color-gray-500);
@ -3236,6 +3279,9 @@
.bg-upst-light {
background-color: #e4f2e3;
}
body {
font-family: "Inter Tight", sans-serif;
}
@property --tw-translate-x {
syntax: "*";
inherits: false;

View File

@ -1,3 +0,0 @@
body {
font-family: "Inter Tight", sans-serif;
}

View File

@ -157,11 +157,19 @@ const DetailPenjemputan = (function() {
state.tpsData.forEach((tps, index) => {
const tab = document.createElement('button');
tab.type = 'button';
tab.className = `px-4 py-2 rounded-xl font-bold text-sm whitespace-nowrap transition ${
index === state.activeTpsIndex
? 'bg-upst text-white'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
}`;
const isActive = index === state.activeTpsIndex;
const isSubmitted = !!tps.submitted;
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;
if (tps.submitted) {
tab.innerHTML += ' <span class="text-xs">✓</span>';
@ -517,7 +525,6 @@ const DetailPenjemputan = (function() {
}
function createTimbanganItem(repeater, existingData = null) {
// Calculate photo number dynamically based on position
const photoNumber = repeater.children.length + 1;
const item = document.createElement('div');
@ -586,7 +593,6 @@ const DetailPenjemputan = (function() {
const watermarkedFile = await applyWatermark(originalFile, photoNumber);
// Update file input dengan watermarked file
const dataTransfer = new DataTransfer();
dataTransfer.items.add(watermarkedFile);
fileInput.files = dataTransfer.files;
@ -657,7 +663,6 @@ const DetailPenjemputan = (function() {
const form = elements.tpsContentContainer.querySelector('form');
const repeater = form ? form.querySelector('.tps-timbangan-repeater') : null;
// Renumber all remaining items
if (repeater) {
renumberTimbanganItems(repeater);
if (repeater.children.length === 0) {
@ -687,7 +692,6 @@ const DetailPenjemputan = (function() {
const newNumber = index + 1;
item.dataset.photoNumber = newNumber;
// Update label text
const label = item.querySelector('.text-xs.font-bold.text-gray-600');
if (label) {
label.textContent = `Item Timbangan #${newNumber}`;
@ -769,7 +773,6 @@ async function applyWatermark(file, photoNumber) {
ctx.fillStyle = 'rgba(15, 23, 42, 0.85)';
ctx.fill();
// Garis Aksen Vertikal
ctx.beginPath();
const accentWidth = baseFontSize * 0.3;
if (ctx.roundRect) {
@ -1089,6 +1092,48 @@ async function applyWatermark(file, photoNumber) {
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() {
const tps = state.tpsData[state.activeTpsIndex];
@ -1109,56 +1154,40 @@ async function applyWatermark(file, photoNumber) {
return;
}
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);
// MODE STATIK (aktif sekarang)
// Cuma validasi + tandai TPS selesai, ga kirim ke backend.
markTpsSubmitted(tps);
alert(`Validasi ${tps.name} OK. Data belum dikirim ke server (mode statik).`);
tps.fotoKedatangan.forEach((file) => {
formData.append(`FotoKedatangan`, file);
});
// MODE PRODUCTION (aktifkan kalau backend udah ready mas ebik)
/*
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', {
method: 'POST',
body: formData
})
.then(response => {
.then(async response => {
if (response.ok) {
tps.submitted = true;
if (state.selectedTpsList.length > 1) {
renderTabs();
}
markTpsSubmitted(tps);
alert(`Data ${tps.name} berhasil disimpan!`);
window.location.reload();
} 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 => {
console.error('Error:', error);
alert('Terjadi kesalahan saat menyimpan data.');
});
*/
}
// Utility functions
function formatWeightDisplay(value) {
if (isNaN(value)) return '0,00';
return value.toFixed(2).replace('.', ',');
@ -1176,7 +1205,6 @@ async function applyWatermark(file, photoNumber) {
return `${mb.toFixed(2)} MB`;
}
// Public API
return {
init: init,
setNomorSpj: function(nomorSpj) {