update: js upload foto, input jalan lat long on odometer
parent
7099077e47
commit
1391437bd5
|
@ -3,8 +3,7 @@
|
|||
ViewData["Title"] = "Detail Penjemputan";
|
||||
}
|
||||
|
||||
<div class="max-w-sm mx-auto bg-white min-h-screen">
|
||||
<!-- Header -->
|
||||
<div class="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="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">
|
||||
|
@ -14,7 +13,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- License Plate - Overlapping -->
|
||||
<div class="flex justify-center -mt-10 mb-6 relative">
|
||||
<div class="bg-orange-100 border border-orange-400 px-4 py-2 rounded-xl shadow flex flex-col items-center">
|
||||
<span class="text-green-700 font-bold text-lg">B 9632 TOR</span>
|
||||
|
@ -22,22 +20,18 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="px-6 space-y-3">
|
||||
<!-- Status Badge -->
|
||||
<div class="px-6">
|
||||
<div class="flex justify-center">
|
||||
<span class="inline-flex items-center px-4 py-1 bg-gradient-to-r from-green-500 to-green-400 text-white rounded-full text-xs font-semibold shadow-md">
|
||||
PENGANGKUTAN
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Company Info -->
|
||||
<div class="text-center space-y-2">
|
||||
<h2 class="text-xl font-extrabold text-gray-800 tracking-wide drop-shadow">CV Tri Berkah Sejahtera</h2>
|
||||
<p class="text-gray-500 text-sm bg-gray-100 rounded px-2 py-1 inline-block shadow">SPJ/07-2025/PKM/000476</p>
|
||||
</div>
|
||||
|
||||
<!-- Address -->
|
||||
<div class="space-y-2">
|
||||
<h3 class="font-semibold text-gray-800 text-center tracking-wider">Alamat</h3>
|
||||
<p class="text-gray-600 text-sm text-center leading-relaxed px-4">
|
||||
|
@ -45,47 +39,101 @@
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Odometer Section -->
|
||||
<div class="space-y-6">
|
||||
<h3 class="font-bold text-gray-800 text-center text-lg tracking-wide">Masukkan Odometer</h3>
|
||||
<div class="flex justify-center">
|
||||
<div class="relative flex items-center justify-center">
|
||||
<img src="@Url.Content("~/driver/odo_simple.svg")" class="overflow-visible drop-shadow-lg scale-110" alt="">
|
||||
<!-- Digital display -->
|
||||
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2">
|
||||
<input type="text" maxlength="7" class="bg-gray-900 text-green-400 px-4 py-2 rounded-lg text-lg font-mono tracking-widest text-center w-36 outline-none border-2 border-green-400 focus:ring-2 focus:ring-orange-400 transition" placeholder="000000" />
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<h3 class="font-bold text-gray-800 text-center text-lg tracking-wide mb-4">Masukkan Odometer</h3>
|
||||
<div class="flex justify-center">
|
||||
<div class="relative flex items-center justify-center">
|
||||
<img src="@Url.Content("~/driver/odo_simple.svg")" class="overflow-visible drop-shadow-lg scale-110" alt="">
|
||||
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2">
|
||||
<input type="text" inputmode="numeric" pattern="[0-9]*" maxlength="7" name="Odometer" id="input-odometer" class="bg-gray-900 text-green-400 px-4 py-2 rounded-lg text-lg font-mono tracking-widest text-center w-36 outline-none border-2 border-green-400 focus:ring-2 focus:ring-orange-400 transition" placeholder="000000" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="pt-6 flex gap-3">
|
||||
<a href="@Url.Action("Batal", "DetailPenjemputan")" class="w-full bg-gray-200 text-gray-700 py-3 rounded-xl font-bold text-lg shadow hover:scale-105 hover:bg-gray-300 transition-all duration-200 flex items-center justify-center gap-2">
|
||||
Batal Angkut
|
||||
</a>
|
||||
<button class="hover:cursor-pointer w-full bg-gradient-to-r from-orange-500 to-orange-400 text-white py-3 rounded-xl font-bold text-lg shadow-xl hover:scale-105 hover:bg-orange-600 transition-all duration-200 flex items-center justify-center gap-2">
|
||||
Submit
|
||||
</button>
|
||||
|
||||
</div>
|
||||
<input type="hidden" name="Latitude" id="input-latitude" />
|
||||
<input type="hidden" name="Longitude" id="input-longitude" />
|
||||
<input type="hidden" name="AlamatJalan" id="input-alamat-jalan" />
|
||||
<div class="pt-6 flex gap-3">
|
||||
<a href="@Url.Action("Batal", "DetailPenjemputan")" class="w-full bg-red-500 text-white py-3 rounded-xl font-bold text-lg shadow hover:scale-105 hover:bg-red-600 transition-all duration-200 flex items-center justify-center gap-2">
|
||||
Batal Angkut
|
||||
</a>
|
||||
<button type="submit" class="hover:cursor-pointer w-full bg-gradient-to-r from-orange-500 to-orange-400 text-white py-3 rounded-xl font-bold text-lg shadow-xl hover:scale-105 hover:bg-orange-600 transition-all duration-200 flex items-center justify-center gap-2">
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<partial name="~/Views/Admin/Transport/SpjDriver/Shared/Components/_Navigation.cshtml" />
|
||||
</div>
|
||||
|
||||
<register-block dynamic-section="scripts" key="jsDetailPenjemputan">
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var odoInput = document.querySelector('input[maxlength="6"]');
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var odoInput = document.getElementById('input-odometer');
|
||||
if (odoInput) {
|
||||
odoInput.addEventListener('focus', function() {
|
||||
setTimeout(function() {
|
||||
odoInput.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}, 300);
|
||||
});
|
||||
odoInput.addEventListener('focus', function() {
|
||||
setTimeout(function() {
|
||||
odoInput.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}, 300);
|
||||
});
|
||||
odoInput.addEventListener('input', function(e) {
|
||||
this.value = this.value.replace(/[^0-9]/g, '');
|
||||
});
|
||||
odoInput.addEventListener('paste', function(e) {
|
||||
e.preventDefault();
|
||||
var text = (e.clipboardData || window.clipboardData).getData('text');
|
||||
this.value = text.replace(/[^0-9]/g, '');
|
||||
});
|
||||
odoInput.addEventListener('keypress', function(e) {
|
||||
if (e.key.length === 1 && !/[0-9]/.test(e.key)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const inputLat = document.getElementById('input-latitude');
|
||||
const inputLng = document.getElementById('input-longitude');
|
||||
const inputAlamat = document.getElementById('input-alamat-jalan');
|
||||
|
||||
function reverseGeocode(lat, lng) {
|
||||
fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}`)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
const address = data.display_name || `${lat}, ${lng}`;
|
||||
if (inputLat) inputLat.value = lat;
|
||||
if (inputLng) inputLng.value = lng;
|
||||
if (inputAlamat) inputAlamat.value = address;
|
||||
})
|
||||
.catch(() => {
|
||||
if (inputLat) inputLat.value = lat;
|
||||
if (inputLng) inputLng.value = lng;
|
||||
if (inputAlamat) inputAlamat.value = `${lat}, ${lng}`;
|
||||
});
|
||||
}
|
||||
|
||||
function getLocationUpdate() {
|
||||
if ('geolocation' in navigator) {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
function (position) {
|
||||
const lat = position.coords.latitude.toFixed(6);
|
||||
const lng = position.coords.longitude.toFixed(6);
|
||||
reverseGeocode(lat, lng);
|
||||
},
|
||||
function () {
|
||||
if (inputLat) inputLat.value = '';
|
||||
if (inputLng) inputLng.value = '';
|
||||
if (inputAlamat) inputAlamat.value = 'Lokasi tidak diizinkan';
|
||||
}
|
||||
);
|
||||
} else {
|
||||
if (inputLat) inputLat.value = '';
|
||||
if (inputLng) inputLng.value = '';
|
||||
if (inputAlamat) inputAlamat.value = 'Browser tidak mendukung lokasi';
|
||||
}
|
||||
}
|
||||
|
||||
getLocationUpdate();
|
||||
});
|
||||
</script>
|
||||
</register-block>
|
|
@ -3,9 +3,8 @@
|
|||
ViewData["Title"] = "Submit Foto Muatan";
|
||||
}
|
||||
|
||||
|
||||
<div class="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-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">
|
||||
<a href="@Url.Action("Index", "Home")" class="p-1 hover:bg-white/10 rounded-full transition-colors">
|
||||
<i class="w-5 h-5" data-lucide="chevron-left"></i>
|
||||
|
@ -15,59 +14,257 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="px-4 py-6">
|
||||
<div class="px-4 py-6 -mt-6 relative z-10">
|
||||
<div class="bg-white rounded-2xl p-5 border border-gray-100">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-10 h-10 bg-orange-100 rounded-full flex items-center justify-center">
|
||||
<i class="w-5 h-5 text-orange-600" data-lucide="file-text"></i>
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-12 h-12 bg-gradient-to-br from-orange-100 to-orange-200 rounded-2xl flex items-center justify-center">
|
||||
<i class="w-6 h-6 text-orange-600" data-lucide="camera"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-lg font-bold text-gray-900">Foto Muatan Kendaraan</h2>
|
||||
<p class="text-xs text-gray-500 flex items-center gap-1">
|
||||
<i class="w-3 h-3" data-lucide="info"></i>
|
||||
Optional
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="upload-area border-2 border-dashed border-gray-300 rounded-xl p-6 text-center hover:border-orange-400 transition-colors cursor-pointer" id="upload-area">
|
||||
<input type="file" name="FotoKondisiKendaraan" accept="image/jpeg,image/png" class="hidden" id="foto-upload">
|
||||
<label for="foto-upload" class="cursor-pointer w-full block">
|
||||
<div class="relative w-full h-32 bg-gray-100 rounded-xl flex items-center justify-center mx-auto mb-3 overflow-hidden preview-container" id="preview-container">
|
||||
<div id="default-state">
|
||||
<div class="upload-icon-container">
|
||||
<i class="w-8 h-8 text-orange-600" data-lucide="upload-cloud" id="preview-icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
<img id="preview-image" src="#" alt="Preview" style="display:none;position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;" />
|
||||
|
||||
<!-- Overlay buttons -->
|
||||
<div class="preview-overlay" id="preview-overlay" style="display:none;">
|
||||
<button type="button" class="overlay-btn" id="edit-preview" aria-label="Edit gambar">
|
||||
<i class="w-5 h-5" data-lucide="edit-3"></i>
|
||||
</button>
|
||||
<button type="button" class="overlay-btn delete" id="close-preview" aria-label="Hapus gambar">
|
||||
<i class="w-5 h-5" data-lucide="trash-2"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- File info -->
|
||||
<div class="file-info" id="file-info" style="display:none;">
|
||||
<span id="file-name">image.jpg</span> • <span id="file-size">0 MB</span>
|
||||
</div>
|
||||
|
||||
<!-- Upload progress -->
|
||||
<div class="upload-progress" id="upload-progress"></div>
|
||||
</div>
|
||||
<div id="upload-text">
|
||||
<p class="text-sm text-gray-600 font-medium">Tap untuk unggah foto</p>
|
||||
<p class="text-xs text-gray-400 mt-1">atau drag & drop file di sini</p>
|
||||
<p class="text-xs text-gray-400 mt-2 flex items-center justify-center gap-1">
|
||||
<i class="w-3 h-3" data-lucide="file-type"></i>
|
||||
JPG, JPEG, PNG maksimal 10MB
|
||||
</p>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 mb-2">
|
||||
<div class="location-badge rounded-2xl p-4">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<div class="w-8 h-8 bg-gradient-to-br from-blue-100 to-blue-200 rounded-full flex items-center justify-center">
|
||||
<i class="w-4 h-4 text-blue-600" data-lucide="map-pin"></i>
|
||||
</div>
|
||||
<span class="text-sm font-medium text-gray-700">Lokasi Anda:</span>
|
||||
<button type="button" id="refresh-location" class="ml-auto p-1 hover:bg-gray-100 rounded-full transition-colors">
|
||||
<i class="w-4 h-4 text-gray-500" data-lucide="refresh-cw"></i>
|
||||
</button>
|
||||
</div>
|
||||
<p id="userLocationSubmit" class="font-semibold text-xs tracking-wide cursor-pointer underline text-orange-600 hover:text-orange-800 transition mt-1 flex items-center gap-2">
|
||||
<span>Mendeteksi lokasi...</span>
|
||||
</p>
|
||||
<p class="text-xs text-gray-400 mt-1">Klik lokasi di atas untuk update posisi Anda</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 class="text-lg font-bold text-gray-900">Foto Muatan Kendaraan</h2>
|
||||
<p class="text-xs text-gray-500">Optional</p>
|
||||
<form asp-action="UploadFotoMuatan" method="post" enctype="multipart/form-data" class="mt-6" id="upload-form">
|
||||
<input type="hidden" name="Latitude" id="input-latitude" />
|
||||
<input type="hidden" name="Longitude" id="input-longitude" />
|
||||
<input type="hidden" name="AlamatJalan" id="input-alamat-jalan" />
|
||||
<div class="flex gap-3 pt-4">
|
||||
<button type="submit" id="submit-btn"
|
||||
class="floating-button flex-1 bg-gradient-to-r from-orange-500 to-orange-600 text-white font-semibold py-3 rounded-xl hover:from-orange-600 hover:to-orange-700 transition-all duration-200 shadow-lg flex items-center justify-center gap-2">
|
||||
<i class="w-5 h-5" data-lucide="upload"></i>
|
||||
<span>Unggah</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-2 border-dashed border-gray-300 rounded-xl p-6 text-center hover:border-red-400 transition-colors">
|
||||
<input type="file" name="FotoKondisiKendaraan" accept="image/*" class="hidden" id="foto-upload">
|
||||
<label for="foto-upload" class="cursor-pointer">
|
||||
<div class="w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-3">
|
||||
<i class="w-6 h-6 text-gray-400" data-lucide="camera"></i>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600">Tap untuk unggah foto</p>
|
||||
<p class="text-xs text-gray-400 mt-1">JPG, PNG maksimal 5MB</p>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 mb-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<i class="w-4 h-4 text-orange-500" data-lucide="map-pin"></i>
|
||||
<span class="text-sm text-gray-700">Lokasi Anda:</span>
|
||||
</div>
|
||||
<p id="userLocationSubmit" class="font-semibold text-xs tracking-wide cursor-pointer underline text-orange-600 hover:text-orange-800 transition mt-1">
|
||||
Mendeteksi lokasi...
|
||||
</p>
|
||||
<p class="text-xs text-gray-400 mt-1">Klik lokasi di atas untuk update posisi Anda</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<form asp-action="UploadFotoMuatan" method="post" enctype="multipart/form-data" class="mt-6">
|
||||
<input type="hidden" name="Latitude" id="input-latitude" />
|
||||
<input type="hidden" name="Longitude" id="input-longitude" />
|
||||
<input type="hidden" name="AlamatJalan" id="input-alamat-jalan" />
|
||||
<div class="flex gap-3 pt-4">
|
||||
<button type="submit"
|
||||
class="flex-1 bg-gradient-to-r from-orange-500 to-orange-600 text-white font-semibold py-3 rounded-xl hover:from-orange-600 hover:to-orange-700 transition-all duration-200 shadow-lg">
|
||||
Unggah
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<partial name="~/Views/Admin/Transport/SpjDriver/Shared/Components/_Navigation.cshtml" />
|
||||
</div>
|
||||
|
||||
|
||||
<register-block dynamic-section="styles" key="cssSubmit">
|
||||
<style>
|
||||
.upload-area {
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.upload-area:hover {
|
||||
background: linear-gradient(135deg, #fef7ed 0%, #fed7aa 100%);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.upload-area.dragover {
|
||||
background: linear-gradient(135deg, #fef7ed 0%, #fed7aa 100%);
|
||||
border-color: #f97316 !important;
|
||||
transform: scale(1.02);
|
||||
box-shadow: 0 25px 50px -12px rgba(251, 146, 60, 0.25);
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
||||
}
|
||||
|
||||
.preview-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.preview-container:hover .preview-overlay {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.overlay-btn {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 12px;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.overlay-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.overlay-btn.delete:hover {
|
||||
background: rgba(239, 68, 68, 0.8);
|
||||
}
|
||||
|
||||
.upload-progress {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, #f97316, #fb923c);
|
||||
transition: width 0.3s ease;
|
||||
border-radius: 0 0 12px 12px;
|
||||
width: 0%;
|
||||
}
|
||||
|
||||
.pulse-animation {
|
||||
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
}
|
||||
|
||||
@@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: .5; }
|
||||
}
|
||||
|
||||
.success-animation {
|
||||
animation: successPulse 0.6s ease;
|
||||
}
|
||||
|
||||
@@keyframes successPulse {
|
||||
0% { transform: scale(1); }
|
||||
50% { transform: scale(1.05); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
.file-info {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
left: 8px;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
color: white;
|
||||
padding: 4px 8px;
|
||||
border-radius: 6px;
|
||||
font-size: 10px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.preview-container:hover .file-info {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.location-badge {
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.floating-button {
|
||||
box-shadow: 0 10px 25px -5px rgba(251, 146, 60, 0.4);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.floating-button:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 20px 40px -5px rgba(251, 146, 60, 0.6);
|
||||
}
|
||||
|
||||
.upload-icon-container {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
background: linear-gradient(135deg, #fef7ed 0%, #fed7aa 100%);
|
||||
border-radius: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 16px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.upload-area:hover .upload-icon-container {
|
||||
transform: scale(1.1);
|
||||
background: linear-gradient(135deg, #fb923c 0%, #f97316 100%);
|
||||
}
|
||||
|
||||
.upload-area:hover .upload-icon-container i {
|
||||
color: white !important;
|
||||
}
|
||||
</style>
|
||||
</register-block>
|
||||
|
||||
<register-block dynamic-section="scripts" key="jsSubmit">
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
|
@ -75,13 +272,137 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
const inputLat = document.getElementById("input-latitude");
|
||||
const inputLng = document.getElementById("input-longitude");
|
||||
const inputAlamat = document.getElementById("input-alamat-jalan");
|
||||
const refreshLocationBtn = document.getElementById("refresh-location");
|
||||
|
||||
const uploadArea = document.getElementById("upload-area");
|
||||
const fotoInput = document.getElementById("foto-upload");
|
||||
const previewImage = document.getElementById("preview-image");
|
||||
const previewIcon = document.getElementById("preview-icon");
|
||||
const closePreview = document.getElementById("close-preview");
|
||||
const editPreview = document.getElementById("edit-preview");
|
||||
const previewOverlay = document.getElementById("preview-overlay");
|
||||
const defaultState = document.getElementById("default-state");
|
||||
const uploadText = document.getElementById("upload-text");
|
||||
const fileInfo = document.getElementById("file-info");
|
||||
const fileName = document.getElementById("file-name");
|
||||
const fileSize = document.getElementById("file-size");
|
||||
const uploadProgress = document.getElementById("upload-progress");
|
||||
const submitBtn = document.getElementById("submit-btn");
|
||||
|
||||
uploadArea.addEventListener("dragover", function(e) {
|
||||
e.preventDefault();
|
||||
uploadArea.classList.add("dragover");
|
||||
});
|
||||
|
||||
uploadArea.addEventListener("dragleave", function(e) {
|
||||
e.preventDefault();
|
||||
uploadArea.classList.remove("dragover");
|
||||
});
|
||||
|
||||
uploadArea.addEventListener("drop", function(e) {
|
||||
e.preventDefault();
|
||||
uploadArea.classList.remove("dragover");
|
||||
const files = e.dataTransfer.files;
|
||||
if (files.length > 0) {
|
||||
handleFileSelect(files[0]);
|
||||
}
|
||||
});
|
||||
|
||||
uploadArea.addEventListener("click", function(e) {
|
||||
if (e.target.tagName !== 'LABEL' && !e.target.closest('label')) {
|
||||
fotoInput.click();
|
||||
}
|
||||
});
|
||||
|
||||
fotoInput.addEventListener("change", function(e) {
|
||||
const file = e.target.files[0];
|
||||
if (file) {
|
||||
handleFileSelect(file);
|
||||
}
|
||||
});
|
||||
|
||||
function handleFileSelect(file) {
|
||||
const allowedTypes = ["image/jpeg", "image/png", "image/jpg"];
|
||||
if (!allowedTypes.includes(file.type)) {
|
||||
showAlert("File harus JPG, JPEG, atau PNG.", "error");
|
||||
fotoInput.value = "";
|
||||
return;
|
||||
}
|
||||
if (file.size > 10 * 1024 * 1024) {
|
||||
showAlert("Ukuran maksimal 10MB.", "error");
|
||||
fotoInput.value = "";
|
||||
return;
|
||||
}
|
||||
|
||||
showUploadProgress(file);
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(ev) {
|
||||
previewImage.src = ev.target.result;
|
||||
fileName.textContent = file.name;
|
||||
fileSize.textContent = formatFileSize(file.size);
|
||||
|
||||
let progress = 0;
|
||||
const interval = setInterval(() => {
|
||||
progress += Math.random() * 15;
|
||||
if (progress >= 100) {
|
||||
progress = 100;
|
||||
clearInterval(interval);
|
||||
setTimeout(() => {
|
||||
showPreview();
|
||||
uploadProgress.style.width = "0%";
|
||||
}, 500);
|
||||
}
|
||||
uploadProgress.style.width = progress + "%";
|
||||
}, 100);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
function showUploadProgress(file) {
|
||||
defaultState.style.display = "none";
|
||||
uploadText.style.display = "none";
|
||||
uploadProgress.style.width = "0%";
|
||||
}
|
||||
|
||||
function showPreview() {
|
||||
previewImage.style.display = "block";
|
||||
previewOverlay.style.display = "flex";
|
||||
fileInfo.style.display = "block";
|
||||
uploadArea.classList.add("success-animation");
|
||||
showAlert("Foto berhasil dimuat!", "success");
|
||||
}
|
||||
|
||||
function resetUpload() {
|
||||
fotoInput.value = "";
|
||||
previewImage.src = "#";
|
||||
previewImage.style.display = "none";
|
||||
previewOverlay.style.display = "none";
|
||||
fileInfo.style.display = "none";
|
||||
defaultState.style.display = "block";
|
||||
uploadText.style.display = "block";
|
||||
uploadArea.classList.remove("success-animation");
|
||||
uploadProgress.style.width = "0%";
|
||||
}
|
||||
|
||||
editPreview.addEventListener("click", function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
fotoInput.click();
|
||||
});
|
||||
|
||||
closePreview.addEventListener("click", function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
resetUpload();
|
||||
});
|
||||
|
||||
function reverseGeocode(lat, lng) {
|
||||
fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}`)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
const address = data.display_name || `${lat}, ${lng}`;
|
||||
userLocationEl.textContent = address;
|
||||
userLocationEl.innerHTML = `<span>${address}</span>`;
|
||||
localStorage.setItem("user_latitude", lat);
|
||||
localStorage.setItem("user_longitude", lng);
|
||||
localStorage.setItem("user_address", address);
|
||||
|
@ -90,7 +411,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
if (inputAlamat) inputAlamat.value = address;
|
||||
})
|
||||
.catch(() => {
|
||||
userLocationEl.textContent = `${lat}, ${lng}`;
|
||||
userLocationEl.innerHTML = `<span>${lat}, ${lng}</span>`;
|
||||
if (inputLat) inputLat.value = lat;
|
||||
if (inputLng) inputLng.value = lng;
|
||||
if (inputAlamat) inputAlamat.value = `${lat}, ${lng}`;
|
||||
|
@ -99,7 +420,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
|
||||
function getLocationUpdate() {
|
||||
if ("geolocation" in navigator) {
|
||||
userLocationEl.textContent = "Mendeteksi lokasi baru...";
|
||||
userLocationEl.innerHTML = `<span>Mendeteksi lokasi...</span>`;
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
function (position) {
|
||||
const lat = position.coords.latitude.toFixed(6);
|
||||
|
@ -107,14 +428,14 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
reverseGeocode(lat, lng);
|
||||
},
|
||||
function () {
|
||||
userLocationEl.textContent = "Lokasi tidak diizinkan";
|
||||
userLocationEl.innerHTML = `<span>Lokasi tidak diizinkan</span>`;
|
||||
if (inputLat) inputLat.value = "";
|
||||
if (inputLng) inputLng.value = "";
|
||||
if (inputAlamat) inputAlamat.value = "Lokasi tidak diizinkan";
|
||||
}
|
||||
);
|
||||
} else {
|
||||
userLocationEl.textContent = "Browser tidak mendukung lokasi";
|
||||
userLocationEl.innerHTML = `<span>Browser tidak mendukung lokasi</span>`;
|
||||
if (inputLat) inputLat.value = "";
|
||||
if (inputLng) inputLng.value = "";
|
||||
if (inputAlamat) inputAlamat.value = "Browser tidak mendukung lokasi";
|
||||
|
@ -126,6 +447,60 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
userLocationEl.addEventListener("click", function () {
|
||||
getLocationUpdate();
|
||||
});
|
||||
|
||||
refreshLocationBtn.addEventListener("click", function() {
|
||||
getLocationUpdate();
|
||||
});
|
||||
|
||||
document.getElementById("upload-form").addEventListener("submit", function(e) {
|
||||
const originalContent = submitBtn.innerHTML;
|
||||
submitBtn.innerHTML = `
|
||||
<svg class="animate-spin w-5 h-5 mr-2" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="m4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
<span>Mengunggah...</span>
|
||||
`;
|
||||
submitBtn.disabled = true;
|
||||
|
||||
setTimeout(() => {
|
||||
submitBtn.innerHTML = originalContent;
|
||||
submitBtn.disabled = false;
|
||||
showAlert("Form berhasil dikirim!", "success");
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
function formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
const k = 1024;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
function showAlert(message, type) {
|
||||
const alertDiv = document.createElement('div');
|
||||
alertDiv.className = `fixed top-4 right-4 z-50 p-4 rounded-lg text-white font-medium transition-all duration-300 ${
|
||||
type === 'success' ? 'bg-green-500' : 'bg-red-500'
|
||||
}`;
|
||||
alertDiv.textContent = message;
|
||||
alertDiv.style.transform = 'translateX(100%)';
|
||||
|
||||
document.body.appendChild(alertDiv);
|
||||
|
||||
setTimeout(() => {
|
||||
alertDiv.style.transform = 'translateX(0)';
|
||||
}, 100);
|
||||
|
||||
setTimeout(() => {
|
||||
alertDiv.style.transform = 'translateX(100%)';
|
||||
setTimeout(() => {
|
||||
if (document.body.contains(alertDiv)) {
|
||||
document.body.removeChild(alertDiv);
|
||||
}
|
||||
}, 300);
|
||||
}, 3000);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</register-block>
|
|
@ -36,13 +36,11 @@
|
|||
--color-green-600: oklch(62.7% 0.194 149.214);
|
||||
--color-green-700: oklch(52.7% 0.154 150.069);
|
||||
--color-blue-100: oklch(93.2% 0.032 255.585);
|
||||
--color-blue-200: oklch(88.2% 0.059 254.128);
|
||||
--color-blue-500: oklch(62.3% 0.214 259.815);
|
||||
--color-blue-600: oklch(54.6% 0.245 262.881);
|
||||
--color-blue-700: oklch(48.8% 0.243 264.376);
|
||||
--color-indigo-50: oklch(96.2% 0.018 272.314);
|
||||
--color-indigo-200: oklch(87% 0.065 274.039);
|
||||
--color-indigo-300: oklch(78.5% 0.115 274.713);
|
||||
--color-indigo-500: oklch(58.5% 0.233 277.117);
|
||||
--color-indigo-600: oklch(51.1% 0.262 276.966);
|
||||
--color-purple-50: oklch(97.7% 0.014 308.299);
|
||||
--color-gray-50: oklch(98.5% 0.002 247.839);
|
||||
--color-gray-100: oklch(96.7% 0.003 264.542);
|
||||
|
@ -68,8 +66,6 @@
|
|||
--text-lg--line-height: calc(1.75 / 1.125);
|
||||
--text-xl: 1.25rem;
|
||||
--text-xl--line-height: calc(1.75 / 1.25);
|
||||
--text-2xl: 1.5rem;
|
||||
--text-2xl--line-height: calc(2 / 1.5);
|
||||
--font-weight-medium: 500;
|
||||
--font-weight-semibold: 600;
|
||||
--font-weight-bold: 700;
|
||||
|
@ -87,6 +83,7 @@
|
|||
--drop-shadow-lg: 0 4px 4px rgb(0 0 0 / 0.15);
|
||||
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
||||
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--animate-spin: spin 1s linear infinite;
|
||||
--animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
--blur-lg: 16px;
|
||||
--default-transition-duration: 150ms;
|
||||
|
@ -295,24 +292,15 @@
|
|||
.top-0 {
|
||||
top: calc(var(--spacing) * 0);
|
||||
}
|
||||
.top-1 {
|
||||
top: calc(var(--spacing) * 1);
|
||||
}
|
||||
.top-1\/2 {
|
||||
top: calc(1/2 * 100%);
|
||||
}
|
||||
.top-10 {
|
||||
top: calc(var(--spacing) * 10);
|
||||
.top-4 {
|
||||
top: calc(var(--spacing) * 4);
|
||||
}
|
||||
.top-12 {
|
||||
top: calc(var(--spacing) * 12);
|
||||
}
|
||||
.top-13 {
|
||||
top: calc(var(--spacing) * 13);
|
||||
}
|
||||
.top-16 {
|
||||
top: calc(var(--spacing) * 16);
|
||||
}
|
||||
.top-50 {
|
||||
top: calc(var(--spacing) * 50);
|
||||
}
|
||||
|
@ -331,9 +319,6 @@
|
|||
.right-full {
|
||||
right: 100%;
|
||||
}
|
||||
.-bottom-0 {
|
||||
bottom: calc(var(--spacing) * -0);
|
||||
}
|
||||
.-bottom-0\.5 {
|
||||
bottom: calc(var(--spacing) * -0.5);
|
||||
}
|
||||
|
@ -358,9 +343,6 @@
|
|||
.left-0 {
|
||||
left: calc(var(--spacing) * 0);
|
||||
}
|
||||
.left-1 {
|
||||
left: calc(var(--spacing) * 1);
|
||||
}
|
||||
.left-1\/2 {
|
||||
left: calc(1/2 * 100%);
|
||||
}
|
||||
|
@ -589,6 +571,9 @@
|
|||
.me-auto {
|
||||
margin-inline-end: auto;
|
||||
}
|
||||
.-mt-6 {
|
||||
margin-top: calc(var(--spacing) * -6);
|
||||
}
|
||||
.-mt-10 {
|
||||
margin-top: calc(var(--spacing) * -10);
|
||||
}
|
||||
|
@ -658,6 +643,9 @@
|
|||
.ml-4 {
|
||||
margin-left: calc(var(--spacing) * 4);
|
||||
}
|
||||
.ml-auto {
|
||||
margin-left: auto;
|
||||
}
|
||||
.\!hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
@ -700,9 +688,6 @@
|
|||
.table-row {
|
||||
display: table-row;
|
||||
}
|
||||
.h-0 {
|
||||
height: calc(var(--spacing) * 0);
|
||||
}
|
||||
.h-0\.5 {
|
||||
height: calc(var(--spacing) * 0.5);
|
||||
}
|
||||
|
@ -712,6 +697,9 @@
|
|||
.h-2 {
|
||||
height: calc(var(--spacing) * 2);
|
||||
}
|
||||
.h-3 {
|
||||
height: calc(var(--spacing) * 3);
|
||||
}
|
||||
.h-4 {
|
||||
height: calc(var(--spacing) * 4);
|
||||
}
|
||||
|
@ -748,6 +736,9 @@
|
|||
.h-30 {
|
||||
height: calc(var(--spacing) * 30);
|
||||
}
|
||||
.h-32 {
|
||||
height: calc(var(--spacing) * 32);
|
||||
}
|
||||
.h-50 {
|
||||
height: calc(var(--spacing) * 50);
|
||||
}
|
||||
|
@ -775,6 +766,9 @@
|
|||
.w-2 {
|
||||
width: calc(var(--spacing) * 2);
|
||||
}
|
||||
.w-3 {
|
||||
width: calc(var(--spacing) * 3);
|
||||
}
|
||||
.w-4 {
|
||||
width: calc(var(--spacing) * 4);
|
||||
}
|
||||
|
@ -874,18 +868,10 @@
|
|||
.border-collapse {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.-translate-x-1 {
|
||||
--tw-translate-x: calc(var(--spacing) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.-translate-x-1\/2 {
|
||||
--tw-translate-x: calc(calc(1/2 * 100%) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.-translate-y-1 {
|
||||
--tw-translate-y: calc(var(--spacing) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.-translate-y-1\/2 {
|
||||
--tw-translate-y: calc(calc(1/2 * 100%) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
|
@ -902,6 +888,9 @@
|
|||
.animate-pulse {
|
||||
animation: var(--animate-pulse);
|
||||
}
|
||||
.animate-spin {
|
||||
animation: var(--animate-spin);
|
||||
}
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -1220,15 +1209,9 @@
|
|||
.bg-red-100 {
|
||||
background-color: var(--color-red-100);
|
||||
}
|
||||
.bg-red-200 {
|
||||
background-color: var(--color-red-200);
|
||||
}
|
||||
.bg-red-500 {
|
||||
background-color: var(--color-red-500);
|
||||
}
|
||||
.bg-red-700 {
|
||||
background-color: var(--color-red-700);
|
||||
}
|
||||
.bg-transparent {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
@ -1252,6 +1235,10 @@
|
|||
--tw-gradient-position: to right in oklab;
|
||||
background-image: linear-gradient(var(--tw-gradient-stops));
|
||||
}
|
||||
.from-blue-100 {
|
||||
--tw-gradient-from: var(--color-blue-100);
|
||||
--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));
|
||||
}
|
||||
.from-green-500 {
|
||||
--tw-gradient-from: var(--color-green-500);
|
||||
--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));
|
||||
|
@ -1260,6 +1247,10 @@
|
|||
--tw-gradient-from: var(--color-indigo-50);
|
||||
--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));
|
||||
}
|
||||
.from-orange-100 {
|
||||
--tw-gradient-from: var(--color-orange-100);
|
||||
--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));
|
||||
}
|
||||
.from-orange-400 {
|
||||
--tw-gradient-from: var(--color-orange-400);
|
||||
--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));
|
||||
|
@ -1278,10 +1269,18 @@
|
|||
--tw-gradient-via-stops: var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);
|
||||
--tw-gradient-stops: var(--tw-gradient-via-stops);
|
||||
}
|
||||
.to-blue-200 {
|
||||
--tw-gradient-to: var(--color-blue-200);
|
||||
--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));
|
||||
}
|
||||
.to-green-400 {
|
||||
--tw-gradient-to: var(--color-green-400);
|
||||
--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));
|
||||
}
|
||||
.to-orange-200 {
|
||||
--tw-gradient-to: var(--color-orange-200);
|
||||
--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));
|
||||
}
|
||||
.to-orange-400 {
|
||||
--tw-gradient-to: var(--color-orange-400);
|
||||
--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));
|
||||
|
@ -1558,6 +1557,9 @@
|
|||
.text-black {
|
||||
color: var(--color-black);
|
||||
}
|
||||
.text-blue-600 {
|
||||
color: var(--color-blue-600);
|
||||
}
|
||||
.text-blue-700 {
|
||||
color: var(--color-blue-700);
|
||||
}
|
||||
|
@ -1832,10 +1834,10 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.hover\:border-red-400 {
|
||||
.hover\:border-orange-400 {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
border-color: var(--color-red-400);
|
||||
border-color: var(--color-orange-400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1874,6 +1876,13 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.hover\:bg-red-600 {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
background-color: var(--color-red-600);
|
||||
}
|
||||
}
|
||||
}
|
||||
.hover\:bg-white\/10 {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
|
@ -2250,6 +2259,11 @@
|
|||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes pulse {
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
|
|
Loading…
Reference in New Issue