update: css dan regex struk
parent
512eb82743
commit
e9a82f8665
|
@ -3,7 +3,7 @@
|
||||||
ViewData["Title"] = "Detail Perjalanan - DLH";
|
ViewData["Title"] = "Detail Perjalanan - DLH";
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto bg-gray-50 min-h-screen">
|
<div class="w-full lg:max-w-sm mx-auto bg-gray-50 min-h-screen">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-4 py-4 sticky top-0 z-10 shadow-lg">
|
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-4 py-4 sticky top-0 z-10 shadow-lg">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
ViewData["Title"] = "History - DLH";
|
ViewData["Title"] = "History - DLH";
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto bg-gray-50 min-h-screen">
|
<div class="w-full lg:max-w-sm mx-auto bg-gray-50 min-h-screen">
|
||||||
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-4 py-4 sticky top-0 z-10 shadow-lg">
|
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-4 py-4 sticky top-0 z-10 shadow-lg">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<a href="@Url.Action("Index", "Admin")" class="p-2 hover:bg-white/10 rounded-full transition-all duration-200">
|
<a href="@Url.Action("Index", "Admin")" class="p-2 hover:bg-white/10 rounded-full transition-all duration-200">
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
ViewData["Title"] = "Admin Dashboard";
|
ViewData["Title"] = "Admin Dashboard";
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="container max-w-sm mx-auto bg-gradient-to-br from-gray-50 to-gray-100 min-h-screen relative overflow-hidden">
|
<div class="w-full lg:max-w-sm mx-auto bg-gradient-to-br from-gray-50 to-gray-100 min-h-screen relative overflow-hidden">
|
||||||
|
|
||||||
<div class="relative z-10">
|
<div class="relative z-10">
|
||||||
<div class="bg-gradient-to-br from-orange-500 via-orange-600 to-red-500 rounded-b-[2rem] shadow-2xl p-6 mb-6">
|
<div class="bg-gradient-to-br from-orange-500 via-orange-600 to-red-500 rounded-b-[2rem] shadow-2xl p-6 mb-6">
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto bg-white min-h-screen">
|
<div class="w-full lg:max-w-sm mx-auto bg-white min-h-screen">
|
||||||
<div class="bg-orange-500 text-white px-3 py-4 rounded-b-2xl relative pb-12">
|
<div class="bg-orange-500 text-white px-3 py-4 rounded-b-2xl relative pb-12">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<a href="@Url.Action("Index", "Home")" class="p-1 hover:bg-white/10 rounded-full transition-colors">
|
<a href="@Url.Action("Index", "Home")" class="p-1 hover:bg-white/10 rounded-full transition-colors">
|
||||||
|
@ -49,6 +49,14 @@
|
||||||
<p class="text-sm">Memuat scanner...</p>
|
<p class="text-sm">Memuat scanner...</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Status indicator ketika scanning aktif -->
|
||||||
|
<div id="scanning-indicator" class="absolute top-2 left-2 bg-green-500 text-white px-3 py-1 rounded-full text-xs font-medium z-20 hidden animate-pulse">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="w-2 h-2 bg-white rounded-full mr-2 animate-ping"></div>
|
||||||
|
Scanner Aktif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -58,7 +66,7 @@
|
||||||
Mulai Scan
|
Mulai Scan
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button id="stop-scanner" class="w-full bg-gray-500 hover:bg-gray-600 text-white font-medium py-3 px-4 rounded-lg transition-colors btn-scanner hidden">
|
<button id="stop-scanner" class="w-full bg-red-500 hover:bg-red-600 text-white font-medium py-3 px-4 rounded-lg transition-colors btn-scanner hidden">
|
||||||
<i class="w-5 h-5 inline mr-2" data-lucide="camera-off"></i>
|
<i class="w-5 h-5 inline mr-2" data-lucide="camera-off"></i>
|
||||||
Hentikan Scan
|
Hentikan Scan
|
||||||
</button>
|
</button>
|
||||||
|
@ -139,7 +147,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="scan-modal" class="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 hidden flex items-center justify-center">
|
<div id="scan-modal" class="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 hidden items-center justify-center">
|
||||||
<div class="bg-white py-4 rounded-2xl shadow-2xl max-w-sm w-full border border-gray-100">
|
<div class="bg-white py-4 rounded-2xl shadow-2xl max-w-sm w-full border border-gray-100">
|
||||||
<div class="p-8 text-center">
|
<div class="p-8 text-center">
|
||||||
<div id="modal-icon" class="mx-auto mb-6">
|
<div id="modal-icon" class="mx-auto mb-6">
|
||||||
|
@ -190,6 +198,7 @@
|
||||||
this.manualInput = document.getElementById('manual-barcode');
|
this.manualInput = document.getElementById('manual-barcode');
|
||||||
this.permissionInfo = document.getElementById('permission-info');
|
this.permissionInfo = document.getElementById('permission-info');
|
||||||
this.permissionDenied = document.getElementById('permission-denied');
|
this.permissionDenied = document.getElementById('permission-denied');
|
||||||
|
this.scanningIndicator = document.getElementById('scanning-indicator');
|
||||||
}
|
}
|
||||||
|
|
||||||
bindEvents() {
|
bindEvents() {
|
||||||
|
@ -243,6 +252,7 @@
|
||||||
this.isScanning = true;
|
this.isScanning = true;
|
||||||
this.startBtn.classList.add('hidden');
|
this.startBtn.classList.add('hidden');
|
||||||
this.stopBtn.classList.remove('hidden');
|
this.stopBtn.classList.remove('hidden');
|
||||||
|
this.scanningIndicator.classList.remove('hidden');
|
||||||
this.hideLoading();
|
this.hideLoading();
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -343,7 +353,7 @@
|
||||||
this.vibrate();
|
this.vibrate();
|
||||||
|
|
||||||
this.detectedCode = decodedText;
|
this.detectedCode = decodedText;
|
||||||
this.stopScanner();
|
// Jangan stop scanner, biarkan tetap aktif untuk scan berikutnya
|
||||||
|
|
||||||
this.processScanCode(decodedText);
|
this.processScanCode(decodedText);
|
||||||
} else {
|
} else {
|
||||||
|
@ -362,6 +372,7 @@
|
||||||
|
|
||||||
this.startBtn.classList.remove('hidden');
|
this.startBtn.classList.remove('hidden');
|
||||||
this.stopBtn.classList.add('hidden');
|
this.stopBtn.classList.add('hidden');
|
||||||
|
this.scanningIndicator.classList.add('hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
flashSuccess() {
|
flashSuccess() {
|
||||||
|
@ -464,6 +475,7 @@
|
||||||
|
|
||||||
this.showSuccessModal(code, tanggal, waktu);
|
this.showSuccessModal(code, tanggal, waktu);
|
||||||
|
|
||||||
|
// Scanner tetap aktif, tidak perlu reset tombol
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.hideResult();
|
this.hideResult();
|
||||||
this.manualInput.value = '';
|
this.manualInput.value = '';
|
||||||
|
@ -481,10 +493,13 @@
|
||||||
this.hidePermissionMessages();
|
this.hidePermissionMessages();
|
||||||
this.detectedCode = null;
|
this.detectedCode = null;
|
||||||
|
|
||||||
if (this.isScanning && this.html5QrCode) {
|
// Jika scanner sudah aktif, tidak perlu restart
|
||||||
await this.stopScanner();
|
if (this.isScanning) {
|
||||||
|
console.log("Scanner sudah aktif, tidak perlu restart");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hanya restart jika scanner tidak aktif
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.startScanner();
|
this.startScanner();
|
||||||
}, 500);
|
}, 500);
|
||||||
|
@ -577,6 +592,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#scan-modal').removeClass('hidden');
|
$('#scan-modal').removeClass('hidden');
|
||||||
|
$('#scan-modal').addClass('flex');
|
||||||
|
|
||||||
$('#scan-modal').css('opacity', '0').animate({'opacity': '1'}, 300);
|
$('#scan-modal').css('opacity', '0').animate({'opacity': '1'}, 300);
|
||||||
$('#scan-modal .bg-white').css('transform', 'scale(0.8)').animate({
|
$('#scan-modal .bg-white').css('transform', 'scale(0.8)').animate({
|
||||||
|
@ -629,6 +645,7 @@
|
||||||
$('#modal-close').hide(); // Sembunyikan tombol
|
$('#modal-close').hide(); // Sembunyikan tombol
|
||||||
|
|
||||||
$('#scan-modal').removeClass('hidden');
|
$('#scan-modal').removeClass('hidden');
|
||||||
|
$('#scan-modal').addClass('flex');
|
||||||
|
|
||||||
$('#scan-modal').css('opacity', '0').animate({'opacity': '1'}, 300);
|
$('#scan-modal').css('opacity', '0').animate({'opacity': '1'}, 300);
|
||||||
$('#scan-modal .bg-white').css('transform', 'scale(0.8)').animate({
|
$('#scan-modal .bg-white').css('transform', 'scale(0.8)').animate({
|
||||||
|
@ -637,6 +654,7 @@
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.hideModal();
|
this.hideModal();
|
||||||
|
// Scanner tetap aktif setelah modal ditutup
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,6 +696,7 @@
|
||||||
$('#modal-close').hide(); // Sembunyikan tombol
|
$('#modal-close').hide(); // Sembunyikan tombol
|
||||||
|
|
||||||
$('#scan-modal').removeClass('hidden');
|
$('#scan-modal').removeClass('hidden');
|
||||||
|
$('#scan-modal').addClass('flex');
|
||||||
|
|
||||||
$('#scan-modal').css('opacity', '0').animate({'opacity': '1'}, 300);
|
$('#scan-modal').css('opacity', '0').animate({'opacity': '1'}, 300);
|
||||||
$('#scan-modal .bg-white').css('transform', 'scale(0.8)').animate({
|
$('#scan-modal .bg-white').css('transform', 'scale(0.8)').animate({
|
||||||
|
@ -686,12 +705,14 @@
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.hideModal();
|
this.hideModal();
|
||||||
|
// Scanner tetap aktif setelah modal error ditutup
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
hideModal() {
|
hideModal() {
|
||||||
$('#scan-modal').animate({'opacity': '0'}, 200, function() {
|
$('#scan-modal').animate({'opacity': '0'}, 200, function() {
|
||||||
$('#scan-modal').addClass('hidden');
|
$('#scan-modal').addClass('hidden');
|
||||||
|
$('#scan-modal').removeClass('flex');
|
||||||
$('#scan-modal').css('opacity', '');
|
$('#scan-modal').css('opacity', '');
|
||||||
$('#scan-modal .bg-white').css('transform', '');
|
$('#scan-modal .bg-white').css('transform', '');
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="fixed bottom-0 left-1/2 transform -translate-x-1/2 w-full max-w-sm z-99">
|
<div class="fixed bottom-0 left-1/2 transform -translate-x-1/2 w-full lg:max-w-sm z-99">
|
||||||
<div class="relative backdrop-blur-lg border border-gray-200/50 rounded-t-3xl shadow-xl overflow-hidden">
|
<div class="relative backdrop-blur-lg border border-gray-200/50 rounded-t-3xl shadow-xl overflow-hidden">
|
||||||
<div class="absolute -top-0 left-1/2 transform -translate-x-1/2 w-20 h-10">
|
<div class="absolute -top-0 left-1/2 transform -translate-x-1/2 w-20 h-10">
|
||||||
<div class="w-full h-full bg-transparent relative">
|
<div class="w-full h-full bg-transparent relative">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
ViewData["Title"] = "Detail Batal Penjemputan";
|
ViewData["Title"] = "Detail Batal Penjemputan";
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto bg-gray-50 min-h-screen">
|
<div class="w-full lg:max-w-sm mx-auto bg-gray-50 min-h-screen">
|
||||||
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-4 py-4 sticky top-0 z-10 shadow-lg">
|
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-4 py-4 sticky top-0 z-10 shadow-lg">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<a href="@Url.Action("Index", "Home")" class="p-2 hover:bg-white/10 rounded-full transition-all duration-200">
|
<a href="@Url.Action("Index", "Home")" class="p-2 hover:bg-white/10 rounded-full transition-all duration-200">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
ViewData["Title"] = "Detail Penjemputan";
|
ViewData["Title"] = "Detail Penjemputan";
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto min-h-screen">
|
<div class="w-full lg:max-w-sm mx-auto min-h-screen">
|
||||||
<div class="bg-orange-500 text-white px-4 py-6 rounded-b-3xl relative pb-12">
|
<div class="bg-orange-500 text-white px-4 py-6 rounded-b-3xl relative pb-12">
|
||||||
<div class="flex items-center justify-center relative">
|
<div class="flex items-center justify-center relative">
|
||||||
<a href="@Url.Action("Index", "Home")" class="absolute left-0 p-1 hover:bg-white/10 rounded-full transition-colors">
|
<a href="@Url.Action("Index", "Home")" class="absolute left-0 p-1 hover:bg-white/10 rounded-full transition-colors">
|
||||||
|
@ -97,7 +97,22 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
const inputAlamat = document.getElementById('input-alamat-jalan');
|
const inputAlamat = document.getElementById('input-alamat-jalan');
|
||||||
|
|
||||||
function reverseGeocode(lat, lng) {
|
function reverseGeocode(lat, lng) {
|
||||||
fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}`)
|
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||||
|
|
||||||
|
const fetchOptions = {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'User-Agent': 'eSPJ-App/1.0'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isFirefox) {
|
||||||
|
fetchOptions.cache = 'force-cache';
|
||||||
|
fetchOptions.keepalive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}`, fetchOptions)
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
const address = data.display_name || `${lat}, ${lng}`;
|
const address = data.display_name || `${lat}, ${lng}`;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
ViewData["Title"] = "Detail Perjalanan - DLH";
|
ViewData["Title"] = "Detail Perjalanan - DLH";
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto bg-gray-50 min-h-screen">
|
<div class="w-full lg:max-w-sm mx-auto bg-gray-50 min-h-screen">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-4 py-4 sticky top-0 z-10 shadow-lg">
|
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-4 py-4 sticky top-0 z-10 shadow-lg">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
ViewData["Title"] = "History - DLH";
|
ViewData["Title"] = "History - DLH";
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto bg-gray-50 min-h-screen">
|
<div class="w-full lg:max-w-sm mx-auto bg-gray-50 min-h-screen">
|
||||||
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-4 py-4 sticky top-0 z-10 shadow-lg">
|
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-4 py-4 sticky top-0 z-10 shadow-lg">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<a href="@Url.Action("Index", "Home")" class="p-2 hover:bg-white/10 rounded-full transition-all duration-200">
|
<a href="@Url.Action("Index", "Home")" class="p-2 hover:bg-white/10 rounded-full transition-all duration-200">
|
||||||
|
|
|
@ -1,155 +0,0 @@
|
||||||
@{
|
|
||||||
Layout = "~/Views/Admin/Transport/SpjDriver/Shared/_Layout.cshtml";
|
|
||||||
ViewData["Title"] = "History - DLH";
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto bg-gray-50 min-h-screen">
|
|
||||||
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-4 py-4 sticky top-0 z-10 shadow-lg">
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<a href="@Url.Action("Index", "Home")" class="p-2 hover:bg-white/10 rounded-full transition-all duration-200">
|
|
||||||
<i class="w-5 h-5" data-lucide="chevron-left"></i>
|
|
||||||
</a>
|
|
||||||
<h1 class="text-lg font-bold">Riwayat Perjalanan</h1>
|
|
||||||
<div class="w-9"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@{
|
|
||||||
var spjList = new[]
|
|
||||||
{
|
|
||||||
new {
|
|
||||||
Id = 1,
|
|
||||||
NoSpj = "SPJ/07-2025/PKM/000478",
|
|
||||||
Plat = "B 5678 ABC",
|
|
||||||
Kode = "JRC 007",
|
|
||||||
Tujuan = "Bantar Gebang",
|
|
||||||
Status = "In Progress",
|
|
||||||
Tanggal = "28 Jul 2025",
|
|
||||||
Waktu = "16:45"
|
|
||||||
},
|
|
||||||
new {
|
|
||||||
Id = 2,
|
|
||||||
NoSpj = "SPJ/07-2025/PKM/000476",
|
|
||||||
Plat = "B 9632 TOR",
|
|
||||||
Kode = "JRC 005",
|
|
||||||
Tujuan = "RDF Rorotan",
|
|
||||||
Status = "Completed",
|
|
||||||
Tanggal = "27 Jul 2025",
|
|
||||||
Waktu = "14:30"
|
|
||||||
},
|
|
||||||
new {
|
|
||||||
Id = 3,
|
|
||||||
NoSpj = "SPJ/07-2025/PKM/000477",
|
|
||||||
Plat = "B 1234 XYZ",
|
|
||||||
Kode = "JRC 006",
|
|
||||||
Tujuan = "RDF Pesanggarahan",
|
|
||||||
Status = "Completed",
|
|
||||||
Tanggal = "26 Jul 2025",
|
|
||||||
Waktu = "09:15"
|
|
||||||
},
|
|
||||||
new {
|
|
||||||
Id = 4,
|
|
||||||
NoSpj = "SPJ/07-2025/PKM/000479",
|
|
||||||
Plat = "B 9876 DEF",
|
|
||||||
Kode = "JRC 008",
|
|
||||||
Tujuan = "RDF Sunter",
|
|
||||||
Status = "Completed",
|
|
||||||
Tanggal = "25 Jul 2025",
|
|
||||||
Waktu = "11:20"
|
|
||||||
},
|
|
||||||
new {
|
|
||||||
Id = 5,
|
|
||||||
NoSpj = "SPJ/07-2025/PKM/000480",
|
|
||||||
Plat = "B 4321 GHI",
|
|
||||||
Kode = "JRC 009",
|
|
||||||
Tujuan = "Bantar Gebang",
|
|
||||||
Status = "Completed",
|
|
||||||
Tanggal = "24 Jul 2025",
|
|
||||||
Waktu = "08:45"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="px-4 py-4 space-y-3">
|
|
||||||
@foreach (var spj in spjList)
|
|
||||||
{
|
|
||||||
<a href="@Url.Action("Details", "History", new { id = spj.Id })" class="block">
|
|
||||||
<div class="bg-white rounded-2xl p-4 shadow-sm border border-gray-100 hover:shadow-lg hover:border-orange-200 transition-all duration-300 relative overflow-hidden">
|
|
||||||
<div class="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-orange-400 to-orange-500"></div>
|
|
||||||
|
|
||||||
<div class="flex items-start justify-between mb-3">
|
|
||||||
<div class="flex-1 min-w-0">
|
|
||||||
<div class="flex items-center gap-2 mb-1">
|
|
||||||
<div class="w-2 h-2 bg-orange-400 rounded-full"></div>
|
|
||||||
<span class="text-xs font-medium text-gray-500 uppercase tracking-wider">No. SPJ</span>
|
|
||||||
</div>
|
|
||||||
<div class="font-bold text-gray-900 text-sm">@spj.NoSpj</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col items-end gap-1">
|
|
||||||
@if (spj.Status == "Completed")
|
|
||||||
{
|
|
||||||
<span class="bg-green-100 text-green-700 px-2 py-1 rounded-full text-xs font-semibold flex items-center gap-1">
|
|
||||||
<div class="w-2 h-2 bg-green-500 rounded-full"></div>
|
|
||||||
Selesai
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<span class="bg-blue-100 text-blue-700 px-2 py-1 rounded-full text-xs font-semibold flex items-center gap-1">
|
|
||||||
<div class="w-2 h-2 bg-blue-500 rounded-full animate-pulse"></div>
|
|
||||||
Berlangsung
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-gray-50 rounded-xl p-3 mb-3">
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<div class="flex items-center gap-3">
|
|
||||||
<div class="w-10 h-10 bg-orange-100 rounded-lg flex items-center justify-center">
|
|
||||||
<i class="w-5 h-5 text-orange-600" data-lucide="car"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="font-bold text-gray-900 text-sm">@spj.Plat</div>
|
|
||||||
<div class="text-xs text-gray-500">@spj.Kode</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-right">
|
|
||||||
<div class="text-xs text-gray-500">@spj.Tanggal</div>
|
|
||||||
<div class="text-xs font-medium text-gray-700">@spj.Waktu</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center gap-3 pt-2 border-t border-gray-100">
|
|
||||||
<div class="w-8 h-8 bg-green-100 rounded-full flex items-center justify-center flex-shrink-0">
|
|
||||||
<i class="w-4 h-4 text-green-600" data-lucide="map-pin"></i>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 min-w-0">
|
|
||||||
<div class="text-xs text-gray-500 mb-1">Tujuan</div>
|
|
||||||
<div class="font-semibold text-gray-900 text-sm">@spj.Tujuan</div>
|
|
||||||
</div>
|
|
||||||
<div class="p-2 hover:bg-gray-100 rounded-full transition-colors">
|
|
||||||
<i class="w-4 h-4 text-gray-400" data-lucide="chevron-right"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Bottom Navigation -->
|
|
||||||
<partial name="~/Views/Admin/Transport/SpjDriver/Shared/Components/_Navigation.cshtml" />
|
|
||||||
|
|
||||||
<!-- Kalau butuh tampilan kosong (jika tidak ada data) -->
|
|
||||||
|
|
||||||
@* <div class="flex flex-col items-center justify-center py-16 px-4">
|
|
||||||
<div class="w-24 h-24 bg-gray-100 rounded-full flex items-center justify-center mb-4">
|
|
||||||
<i class="w-12 h-12 text-gray-400" data-lucide="clock"></i>
|
|
||||||
</div>
|
|
||||||
<h3 class="text-lg font-semibold text-gray-900 mb-2">Belum Ada Riwayat</h3>
|
|
||||||
<p class="text-gray-500 text-center text-sm">Riwayat perjalanan Anda akan muncul di sini setelah melakukan perjalanan pertama.</p>
|
|
||||||
</div> *@
|
|
||||||
|
|
||||||
</div>
|
|
|
@ -3,10 +3,10 @@
|
||||||
ViewData["Title"] = "Home Page";
|
ViewData["Title"] = "Home Page";
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="container max-w-sm mx-auto bg-white min-h-screen">
|
<div class="w-full lg:max-w-sm mx-auto bg-white min-h-screen">
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="absolute top-0 max-w-sm container mx-auto bg-orange-500 text-white rounded-br-[125px] h-[250px] flex flex-row justify-between items-start px-6 py-6 shadow-lg z-20">
|
<div class="absolute top-0 w-full lg:max-w-sm mx-auto bg-orange-500 text-white rounded-br-[125px] h-[250px] flex flex-row justify-between items-start px-6 py-6 shadow-lg z-20">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<h1 class="text-md font-bold leading-tight text-white">Bonny Agung Putra</h1>
|
<h1 class="text-md font-bold leading-tight text-white">Bonny Agung Putra</h1>
|
||||||
<p class="text-xs opacity-90 font-medium text-orange-100">Driver UPST</span></p>
|
<p class="text-xs opacity-90 font-medium text-orange-100">Driver UPST</span></p>
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<partial name="~/Views/Admin/Transport/SpjDriver/Shared/Components/_NavigationAdmin.cshtml" />
|
<partial name="~/Views/Admin/Transport/SpjDriver/Shared/Components/_Navigation.cshtml" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="fixed bottom-0 left-1/2 transform -translate-x-1/2 w-full max-w-sm z-99">
|
<div class="fixed bottom-0 left-1/2 transform -translate-x-1/2 w-full lg:max-w-sm z-99">
|
||||||
<div class="relative backdrop-blur-lg border border-gray-200/50 rounded-t-3xl shadow-xl overflow-hidden">
|
<div class="relative backdrop-blur-lg border border-gray-200/50 rounded-t-3xl shadow-xl overflow-hidden">
|
||||||
<div class="absolute -top-0 left-1/2 transform -translate-x-1/2 w-20 h-10">
|
<div class="absolute -top-0 left-1/2 transform -translate-x-1/2 w-20 h-10">
|
||||||
<div class="w-full h-full bg-transparent relative">
|
<div class="w-full h-full bg-transparent relative">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
ViewData["Title"] = "Submit Foto Muatan";
|
ViewData["Title"] = "Submit Foto Muatan";
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto bg-white min-h-screen">
|
<div class="w-full lg:max-w-sm mx-auto bg-white min-h-screen">
|
||||||
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-3 py-4 rounded-b-2xl relative pb-12">
|
<div class="bg-gradient-to-r from-orange-500 to-orange-600 text-white px-3 py-4 rounded-b-2xl relative pb-12">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<a href="@Url.Action("Index", "Home")" class="p-1 hover:bg-white/10 rounded-full transition-colors">
|
<a href="@Url.Action("Index", "Home")" class="p-1 hover:bg-white/10 rounded-full transition-colors">
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,7 +7,7 @@
|
||||||
<link rel="stylesheet" href="@Url.Content("~/driver/css/scanner.css")" asp-append-version="true" />
|
<link rel="stylesheet" href="@Url.Content("~/driver/css/scanner.css")" asp-append-version="true" />
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="max-w-sm mx-auto bg-white min-h-screen">
|
<div class="w-full lg:max-w-sm mx-auto bg-white min-h-screen">
|
||||||
<div class="bg-orange-500 text-white px-3 py-4 rounded-b-2xl relative pb-12">
|
<div class="bg-orange-500 text-white px-3 py-4 rounded-b-2xl relative pb-12">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<a href="@Url.Action("Index", "Home")" class="p-1 hover:bg-white/10 rounded-full transition-colors">
|
<a href="@Url.Action("Index", "Home")" class="p-1 hover:bg-white/10 rounded-full transition-colors">
|
||||||
|
@ -253,7 +253,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<register-block dynamic-section="scripts" key="jsSubmitStruk">
|
<register-block dynamic-section="scripts" key="jsSubmitStruk">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/tesseract.js@4.1.1/dist/tesseract.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/tesseract.js@5.1.1/dist/tesseract.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const nomorStrukInput = document.getElementById('NomorStruk');
|
const nomorStrukInput = document.getElementById('NomorStruk');
|
||||||
|
@ -576,37 +576,40 @@
|
||||||
let weightOut = '';
|
let weightOut = '';
|
||||||
let weightNett = '';
|
let weightNett = '';
|
||||||
|
|
||||||
|
// Enhanced receipt number detection - prioritize month prefix patterns
|
||||||
const receiptPatterns = [
|
const receiptPatterns = [
|
||||||
/(\d{2})\s+(\d{7,})/gi,
|
/(\d{2})_(\d{6,})/gi, // "08_7999566" - underscore pattern (highest priority)
|
||||||
/(\d{2})_(\d{7,})/gi,
|
/(\d{2})\s+(\d{6,})/gi, // "08 7999566" - space pattern
|
||||||
/(?:no.*struk|nomor.*struk|receipt)[\s.:]*(\d{7,})/gi,
|
/(?:no.*struk|nomor.*struk|receipt)[\s.:]*(\d{6,})/gi, // Context-based pattern
|
||||||
/(?:^|\s)(\d{7,10})(?:\s|$)/g,
|
/(?:^|\s)(\d{6,10})(?:\s|$)/g, // Standalone number pattern
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
console.log(`Processing line for receipt: "${line}"`);
|
console.log(`Processing line for receipt: "${line}"`);
|
||||||
|
|
||||||
const monthNumberMatch = line.match(/(\d{2})\s+(\d{7,})/);
|
// Pattern 1: Month_Number format (08_7999566) - HIGHEST PRIORITY
|
||||||
if (monthNumberMatch && monthNumberMatch[2]) {
|
const monthUnderscoreMatch = line.match(/(\d{2})_(\d{6,})/);
|
||||||
receiptNumber = monthNumberMatch[2]; // Take the number after space/underscore
|
|
||||||
console.log(`Found receipt number: ${receiptNumber} using month-number pattern`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const monthUnderscoreMatch = line.match(/(\d{2})_(\d{7,})/);
|
|
||||||
if (monthUnderscoreMatch && monthUnderscoreMatch[2]) {
|
if (monthUnderscoreMatch && monthUnderscoreMatch[2]) {
|
||||||
receiptNumber = monthUnderscoreMatch[2]; // Take the number after underscore
|
receiptNumber = monthUnderscoreMatch[2]; // Take ONLY the number after underscore
|
||||||
console.log(`Found receipt number: ${receiptNumber} using month-underscore pattern`);
|
console.log(`Found receipt number: ${receiptNumber} using month-underscore pattern (removed prefix: ${monthUnderscoreMatch[1]}_)`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other patterns
|
// Pattern 2: Month Number format (08 7999566)
|
||||||
for (const pattern of receiptPatterns.slice(2)) { // Skip first 2 patterns already handled above
|
const monthSpaceMatch = line.match(/(\d{2})\s+(\d{6,})/);
|
||||||
|
if (monthSpaceMatch && monthSpaceMatch[2]) {
|
||||||
|
receiptNumber = monthSpaceMatch[2]; // Take ONLY the number after space
|
||||||
|
console.log(`Found receipt number: ${receiptNumber} using month-space pattern (removed prefix: ${monthSpaceMatch[1]} )`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pattern 3: Context-based patterns (fallback)
|
||||||
|
for (const pattern of receiptPatterns.slice(2)) {
|
||||||
const matches = [...line.matchAll(pattern)];
|
const matches = [...line.matchAll(pattern)];
|
||||||
for (const match of matches) {
|
for (const match of matches) {
|
||||||
if (match[1] && match[1].length >= 7) {
|
if (match[1] && match[1].length >= 6) {
|
||||||
receiptNumber = match[1];
|
receiptNumber = match[1];
|
||||||
console.log(`Found receipt number: ${receiptNumber} using pattern: ${pattern}`);
|
console.log(`Found receipt number: ${receiptNumber} using context pattern: ${pattern}`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -668,106 +671,54 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!truckNumber) {
|
if (!truckNumber) {
|
||||||
console.log('No truck number found in context lines, trying all lines...');
|
// Ambil semua karakter setelah label "No Truk" tanpa filter khusus
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
console.log(`Scanning line for truck pattern: "${line}"`);
|
if (line.toLowerCase().includes('no truk')) {
|
||||||
|
// Contoh: "No Truk : B 9501 TOQ"
|
||||||
if (line.match(/[A-Z]\s*\d+\s*[A-Z]{2,3}/i)) {
|
const match = line.match(/no\s*truk\s*:?\s*(.+)/i);
|
||||||
console.log('Potential truck pattern found:', line);
|
if (match && match[1]) {
|
||||||
|
truckNumber = match[1].trim();
|
||||||
for (const pattern of truckPatterns) {
|
console.log(`Found truck number: ${truckNumber} (ambil semua karakter setelah label No Truk)`);
|
||||||
const match = line.match(pattern);
|
|
||||||
if (match) {
|
|
||||||
let foundTruck = '';
|
|
||||||
|
|
||||||
if (match.length === 4 && match[1] && match[2] && match[3]) {
|
|
||||||
foundTruck = `${match[1]} ${match[2]} ${match[3]}`;
|
|
||||||
} else if (match[1]) {
|
|
||||||
foundTruck = match[1].trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundTruck) {
|
|
||||||
foundTruck = foundTruck.replace(/([A-Z])(\d+)(\s+[A-Z]{2,3})/g, '$1 $2$3');
|
|
||||||
foundTruck = foundTruck.replace(/([A-Z]{1,2})(\d{3,4})([A-Z]{2,3})/g, '$1 $2 $3');
|
|
||||||
foundTruck = foundTruck.replace(/\s+/g, ' ').trim();
|
|
||||||
|
|
||||||
if (foundTruck.match(/^[A-Z]{1,2}\s+\d{3,4}\s+[A-Z]{2,3}$/)) {
|
|
||||||
truckNumber = foundTruck;
|
|
||||||
console.log(`Found truck number: "${truckNumber}" using general pattern`);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// Jika tidak ditemukan, fallback ke pattern lama (awalan B)
|
||||||
if (truckNumber) break;
|
if (!truckNumber) {
|
||||||
}
|
for (const line of lines) {
|
||||||
}
|
const match = line.match(/\bB\s*\d{3,5}\s*[A-Z]{2,4}\b/i);
|
||||||
}
|
if (match && match[0]) {
|
||||||
|
truckNumber = match[0].trim();
|
||||||
if (!truckNumber) {
|
console.log(`Fallback truck number: ${truckNumber}`);
|
||||||
console.log('Still no truck number, trying loose patterns...');
|
break;
|
||||||
for (const line of lines) {
|
}
|
||||||
const looseMatch = line.match(/([A-Z]{1,2})\s*(\d{3,4})\s*([A-Z]{2,3})/i);
|
}
|
||||||
if (looseMatch && looseMatch[1] && looseMatch[2] && looseMatch[3]) {
|
}
|
||||||
const candidate = `${looseMatch[1].toUpperCase()} ${looseMatch[2]} ${looseMatch[3].toUpperCase()}`;
|
|
||||||
console.log(`Found potential truck number with loose pattern: "${candidate}"`);
|
|
||||||
|
|
||||||
if (looseMatch[1].length <= 2 &&
|
|
||||||
looseMatch[2].length >= 3 && looseMatch[2].length <= 4 &&
|
|
||||||
looseMatch[3].length >= 2 && looseMatch[3].length <= 3) {
|
|
||||||
truckNumber = candidate;
|
|
||||||
console.log(`Accepted truck number: "${truckNumber}"`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Truck detection results:', { truckNumber });
|
|
||||||
|
|
||||||
console.log('Truck detection result:', truckNumber);
|
console.log('Truck detection result:', truckNumber);
|
||||||
|
|
||||||
const assignmentPatterns = [
|
// Assignment detection - ambil semua karakter setelah label "Penugasan"
|
||||||
/(?:penugasan|assignment)[\s.:]*([A-Z\s]+?)(?:\n|$)/gi,
|
|
||||||
/(JAKARTA\s+\w+)/gi, // Specific pattern for Jakarta areas
|
|
||||||
/(BANDUNG|SURABAYA|MEDAN|SEMARANG|PALEMBANG|MAKASSAR)[\s\w]*/gi,
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
console.log(`Processing line for assignment: "${line}"`);
|
console.log(`Processing line for assignment: "${line}"`);
|
||||||
|
|
||||||
if (line.toLowerCase().includes('penugasan')) {
|
if (line.toLowerCase().includes('penugasan')) {
|
||||||
console.log('Found penugasan line:', line);
|
console.log('Found penugasan line:', line);
|
||||||
|
|
||||||
const assignmentMatch = line.match(/penugasan\s*:\s*(.+)/i);
|
// Contoh: "Penugasan : JAKARTA TIMUR" atau "Penugasan: UPST DLH"
|
||||||
if (assignmentMatch && assignmentMatch[1]) {
|
const match = line.match(/penugasan\s*:?\s*(.+)/i);
|
||||||
assignment = assignmentMatch[1].trim();
|
|
||||||
console.log(`Found assignment: ${assignment}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.toUpperCase().includes('JAKARTA') && line.toUpperCase().includes('BARAT')) {
|
|
||||||
assignment = 'JAKARTA BARAT';
|
|
||||||
console.log(`Found assignment: ${assignment} from Jakarta Barat line`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const pattern of assignmentPatterns) {
|
|
||||||
const match = line.match(pattern);
|
|
||||||
if (match && match[1]) {
|
if (match && match[1]) {
|
||||||
assignment = match[1].trim();
|
assignment = match[1].trim();
|
||||||
console.log(`Found assignment: ${assignment} using pattern: ${pattern}`);
|
console.log(`Found assignment: ${assignment} (ambil semua karakter setelah label Penugasan)`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (assignment) break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Assignment detection result:', assignment);
|
console.log('Assignment detection result:', assignment);
|
||||||
|
|
||||||
// Enhanced time patterns
|
// Enhanced time patterns - prioritize YYYY-MM-DD HH:MM:SS format
|
||||||
const timePatterns = [
|
const timePatterns = [
|
||||||
|
/(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})/gi, // 2025-08-02 12:35:34 (highest priority)
|
||||||
/(\d{1,2}\s+\w{3}\s+\d{4},\s*\d{1,2}:\d{2}:\d{2})/gi, // 04 Aug 2025, 08:13:51
|
/(\d{1,2}\s+\w{3}\s+\d{4},\s*\d{1,2}:\d{2}:\d{2})/gi, // 04 Aug 2025, 08:13:51
|
||||||
/(\d{1,2}\s+\w{3}\s+\d{4}\s+\d{1,2}:\d{2}:\d{2})/gi, // 04 Aug 2025 08:13:51
|
/(\d{1,2}\s+\w{3}\s+\d{4}\s+\d{1,2}:\d{2}:\d{2})/gi, // 04 Aug 2025 08:13:51
|
||||||
/(\d{1,2}\/\d{1,2}\/\d{4}\s+\d{1,2}:\d{2}:\d{2})/gi, // 04/08/2025 08:13:51
|
/(\d{1,2}\/\d{1,2}\/\d{4}\s+\d{1,2}:\d{2}:\d{2})/gi, // 04/08/2025 08:13:51
|
||||||
|
@ -780,12 +731,21 @@
|
||||||
// Entry time - look for "Masuk :" pattern
|
// Entry time - look for "Masuk :" pattern
|
||||||
if (line.toLowerCase().includes('masuk') && line.includes(':')) {
|
if (line.toLowerCase().includes('masuk') && line.includes(':')) {
|
||||||
console.log('Found masuk line:', line);
|
console.log('Found masuk line:', line);
|
||||||
for (const pattern of timePatterns) {
|
|
||||||
const match = line.match(pattern);
|
// First try to find exact YYYY-MM-DD HH:MM:SS format after "Masuk :"
|
||||||
if (match && match[1]) {
|
const masukMatch = line.match(/masuk\s*:\s*(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})/i);
|
||||||
entryTime = match[1].trim();
|
if (masukMatch && masukMatch[1]) {
|
||||||
console.log(`Found entry time: ${entryTime}`);
|
entryTime = masukMatch[1].trim();
|
||||||
break;
|
console.log(`Found entry time via masuk pattern: ${entryTime} (format: YYYY-MM-DD HH:MM:SS)`);
|
||||||
|
} else {
|
||||||
|
// Fallback to general patterns
|
||||||
|
for (const pattern of timePatterns) {
|
||||||
|
const match = line.match(pattern);
|
||||||
|
if (match && match[1]) {
|
||||||
|
entryTime = match[1].trim();
|
||||||
|
console.log(`Found entry time: ${entryTime}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Also try to extract after "Masuk : "
|
// Also try to extract after "Masuk : "
|
||||||
|
@ -799,19 +759,22 @@
|
||||||
// Exit time - look for "Keluar :" pattern
|
// Exit time - look for "Keluar :" pattern
|
||||||
if (line.toLowerCase().includes('keluar') && line.includes(':')) {
|
if (line.toLowerCase().includes('keluar') && line.includes(':')) {
|
||||||
console.log('Found keluar line:', line);
|
console.log('Found keluar line:', line);
|
||||||
for (const pattern of timePatterns) {
|
|
||||||
const match = line.match(pattern);
|
// First try to find exact YYYY-MM-DD HH:MM:SS format after "Keluar :"
|
||||||
if (match && match[1]) {
|
const keluarMatch = line.match(/keluar\s*:\s*(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})/i);
|
||||||
exitTime = match[1].trim();
|
if (keluarMatch && keluarMatch[1]) {
|
||||||
console.log(`Found exit time: ${exitTime}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Also try to extract after "Keluar : "
|
|
||||||
const keluarMatch = line.match(/keluar\s*:\s*(.+)/i);
|
|
||||||
if (keluarMatch && keluarMatch[1] && !exitTime) {
|
|
||||||
exitTime = keluarMatch[1].trim();
|
exitTime = keluarMatch[1].trim();
|
||||||
console.log(`Found exit time via keluar pattern: ${exitTime}`);
|
console.log(`Found exit time via keluar pattern: ${exitTime} (format: YYYY-MM-DD HH:MM:SS)`);
|
||||||
|
} else {
|
||||||
|
// Fallback to general patterns
|
||||||
|
for (const pattern of timePatterns) {
|
||||||
|
const match = line.match(pattern);
|
||||||
|
if (match && match[1]) {
|
||||||
|
exitTime = match[1].trim();
|
||||||
|
console.log(`Found exit time: ${exitTime}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -841,16 +804,16 @@
|
||||||
if (specificMatch) {
|
if (specificMatch) {
|
||||||
const numbers = specificMatch[0].match(/(\d+)/);
|
const numbers = specificMatch[0].match(/(\d+)/);
|
||||||
if (numbers && numbers[1]) {
|
if (numbers && numbers[1]) {
|
||||||
weightIn = numbers[1];
|
weightIn = numbers[1]; // Hanya angka, tanpa "kg"
|
||||||
console.log(`Found weight in via specific pattern: ${weightIn} kg`);
|
console.log(`Found weight in via specific pattern: ${weightIn} (removed kg)`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Try general patterns
|
// Try general patterns
|
||||||
for (const pattern of weightPatterns) {
|
for (const pattern of weightPatterns) {
|
||||||
const match = line.match(pattern);
|
const match = line.match(pattern);
|
||||||
if (match && match[1] && parseInt(match[1]) > 1000) {
|
if (match && match[1] && parseInt(match[1]) > 1000) {
|
||||||
weightIn = match[1];
|
weightIn = match[1]; // Hanya angka
|
||||||
console.log(`Found weight in via general pattern: ${weightIn} kg`);
|
console.log(`Found weight in via general pattern: ${weightIn} (removed kg)`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -866,16 +829,16 @@
|
||||||
if (specificMatch) {
|
if (specificMatch) {
|
||||||
const numbers = specificMatch[0].match(/(\d+)/);
|
const numbers = specificMatch[0].match(/(\d+)/);
|
||||||
if (numbers && numbers[1]) {
|
if (numbers && numbers[1]) {
|
||||||
weightOut = numbers[1];
|
weightOut = numbers[1]; // Hanya angka, tanpa "kg"
|
||||||
console.log(`Found weight out via specific pattern: ${weightOut} kg`);
|
console.log(`Found weight out via specific pattern: ${weightOut} (removed kg)`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Try general patterns
|
// Try general patterns
|
||||||
for (const pattern of weightPatterns) {
|
for (const pattern of weightPatterns) {
|
||||||
const match = line.match(pattern);
|
const match = line.match(pattern);
|
||||||
if (match && match[1] && parseInt(match[1]) > 1000) {
|
if (match && match[1] && parseInt(match[1]) > 1000) {
|
||||||
weightOut = match[1];
|
weightOut = match[1]; // Hanya angka
|
||||||
console.log(`Found weight out via general pattern: ${weightOut} kg`);
|
console.log(`Found weight out via general pattern: ${weightOut} (removed kg)`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -891,16 +854,16 @@
|
||||||
if (specificMatch) {
|
if (specificMatch) {
|
||||||
const numbers = specificMatch[0].match(/(\d+)/);
|
const numbers = specificMatch[0].match(/(\d+)/);
|
||||||
if (numbers && numbers[1]) {
|
if (numbers && numbers[1]) {
|
||||||
weightNett = numbers[1];
|
weightNett = numbers[1]; // Hanya angka, tanpa "kg"
|
||||||
console.log(`Found weight nett via specific pattern: ${weightNett} kg`);
|
console.log(`Found weight nett via specific pattern: ${weightNett} (removed kg)`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Try general patterns
|
// Try general patterns
|
||||||
for (const pattern of weightPatterns) {
|
for (const pattern of weightPatterns) {
|
||||||
const match = line.match(pattern);
|
const match = line.match(pattern);
|
||||||
if (match && match[1] && parseInt(match[1]) > 100) {
|
if (match && match[1] && parseInt(match[1]) > 100) {
|
||||||
weightNett = match[1];
|
weightNett = match[1]; // Hanya angka
|
||||||
console.log(`Found weight nett via general pattern: ${weightNett} kg`);
|
console.log(`Found weight nett via general pattern: ${weightNett} (removed kg)`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -908,6 +871,24 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validasi Berat Nett = Berat Masuk - Berat Keluar
|
||||||
|
if (weightIn && weightOut && weightNett) {
|
||||||
|
const calculatedNett = parseInt(weightIn) - parseInt(weightOut);
|
||||||
|
const detectedNett = parseInt(weightNett);
|
||||||
|
|
||||||
|
console.log(`Weight validation: ${weightIn} - ${weightOut} = ${calculatedNett}, detected: ${detectedNett}`);
|
||||||
|
|
||||||
|
if (calculatedNett !== detectedNett) {
|
||||||
|
console.warn(`WARNING: Berat Nett tidak sesuai! Perhitungan: ${calculatedNett}, Terdeteksi: ${detectedNett}`);
|
||||||
|
// Gunakan hasil perhitungan yang benar
|
||||||
|
weightNett = calculatedNett.toString();
|
||||||
|
console.log(`Using calculated weight nett: ${weightNett}`);
|
||||||
|
|
||||||
|
// Alert akan ditampilkan di frontend saat apply data
|
||||||
|
this.weightValidationError = `Berat Nett tidak sesuai! Perhitungan: ${calculatedNett} kg, Terdeteksi: ${detectedNett} kg. Menggunakan hasil perhitungan.`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log('Weight detection results:', { weightIn, weightOut, weightNett });
|
console.log('Weight detection results:', { weightIn, weightOut, weightNett });
|
||||||
|
|
||||||
console.log('Final Detected Data before assignment:', {
|
console.log('Final Detected Data before assignment:', {
|
||||||
|
@ -960,9 +941,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
applyDetectedDataDirectly() {
|
applyDetectedDataDirectly() {
|
||||||
console.log('=== APPLYING DATA DIRECTLY TO FORM ===');
|
console.log(`=== APPLYING DATA DIRECTLY TO FORM ===`);
|
||||||
console.log('Data to apply:', this.detectedData);
|
console.log('Data to apply:', this.detectedData);
|
||||||
|
|
||||||
|
// Tampilkan alert jika ada error validasi berat nett
|
||||||
|
if (this.weightValidationError) {
|
||||||
|
alert(this.weightValidationError);
|
||||||
|
this.weightValidationError = null; // Reset error
|
||||||
|
}
|
||||||
|
|
||||||
// Get input elements by ID directly
|
// Get input elements by ID directly
|
||||||
const nomorStrukInput = document.getElementById('NomorStruk');
|
const nomorStrukInput = document.getElementById('NomorStruk');
|
||||||
const nomorPolisiInput = document.getElementById('NomorPolisi');
|
const nomorPolisiInput = document.getElementById('NomorPolisi');
|
||||||
|
|
|
@ -87,6 +87,7 @@
|
||||||
--color-white: #fff;
|
--color-white: #fff;
|
||||||
--spacing: 0.25rem;
|
--spacing: 0.25rem;
|
||||||
--container-sm: 24rem;
|
--container-sm: 24rem;
|
||||||
|
--container-md: 28rem;
|
||||||
--text-xs: 0.75rem;
|
--text-xs: 0.75rem;
|
||||||
--text-xs--line-height: calc(1 / 0.75);
|
--text-xs--line-height: calc(1 / 0.75);
|
||||||
--text-sm: 0.875rem;
|
--text-sm: 0.875rem;
|
||||||
|
@ -113,7 +114,6 @@
|
||||||
--radius-xl: 0.75rem;
|
--radius-xl: 0.75rem;
|
||||||
--radius-2xl: 1rem;
|
--radius-2xl: 1rem;
|
||||||
--radius-3xl: 1.5rem;
|
--radius-3xl: 1.5rem;
|
||||||
--radius-4xl: 2rem;
|
|
||||||
--drop-shadow-lg: 0 4px 4px rgb(0 0 0 / 0.15);
|
--drop-shadow-lg: 0 4px 4px rgb(0 0 0 / 0.15);
|
||||||
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
||||||
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
@ -1213,9 +1213,6 @@
|
||||||
.rounded-3xl {
|
.rounded-3xl {
|
||||||
border-radius: var(--radius-3xl);
|
border-radius: var(--radius-3xl);
|
||||||
}
|
}
|
||||||
.rounded-4xl {
|
|
||||||
border-radius: var(--radius-4xl);
|
|
||||||
}
|
|
||||||
.rounded-full {
|
.rounded-full {
|
||||||
border-radius: calc(infinity * 1px);
|
border-radius: calc(infinity * 1px);
|
||||||
}
|
}
|
||||||
|
@ -2639,6 +2636,21 @@
|
||||||
outline-style: none;
|
outline-style: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.md\:max-w-md {
|
||||||
|
@media (width >= 48rem) {
|
||||||
|
max-width: var(--container-md);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.md\:max-w-sm {
|
||||||
|
@media (width >= 48rem) {
|
||||||
|
max-width: var(--container-sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.lg\:max-w-sm {
|
||||||
|
@media (width >= 64rem) {
|
||||||
|
max-width: var(--container-sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@property --tw-translate-x {
|
@property --tw-translate-x {
|
||||||
syntax: "*";
|
syntax: "*";
|
||||||
|
|
Loading…
Reference in New Issue