update terakhir nih

main
marszayn 2025-07-29 16:03:11 +07:00
parent e4ce7912ff
commit e9f34b1f3c
19 changed files with 1433 additions and 761 deletions

View File

@ -12,6 +12,11 @@ namespace eSPJ.Controllers
return View(); return View();
} }
[HttpGet("batal")]
public IActionResult Batal()
{
return View("~/Views/DetailPenjemputan/Batal.cshtml");
}
} }
} }

View File

@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Mvc;
namespace eSPJ.Controllers
{
[Route("history")]
public class HistoryController : Controller
{
[HttpGet("")]
public IActionResult Index()
{
return View();
}
[HttpGet("details/{id}")]
public IActionResult Details(int id)
{
ViewData["Id"] = id;
return View();
}
}
}

View File

@ -6,6 +6,7 @@ namespace eSPJ.Controllers;
public class HomeController : Controller public class HomeController : Controller
{ {
private readonly ILogger<HomeController> _logger; private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger) public HomeController(ILogger<HomeController> logger)
@ -18,6 +19,11 @@ public class HomeController : Controller
return View(); return View();
} }
public IActionResult Batal()
{
return View();
}
public IActionResult Privacy() public IActionResult Privacy()
{ {
return View(); return View();

View File

@ -0,0 +1,23 @@
using Microsoft.AspNetCore.Mvc;
namespace eSPJ.Controllers
{
[Route("login")]
public class LoginController : Controller
{
private readonly IConfiguration _configuration;
public LoginController(IConfiguration configuration)
{
_configuration = configuration;
}
[HttpGet("")]
public IActionResult Index()
{
ViewBag.SSOLoginUrl = _configuration["SSO:LoginUrl"];
return View();
}
}
}

View File

@ -11,7 +11,5 @@ namespace eSPJ.Controllers
{ {
return View(); return View();
} }
} }
} }

View File

@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Mvc;
namespace eSPJ.Controllers
{
[Route("submit")]
public class SubmitController : Controller
{
[HttpGet("")]
public IActionResult Index()
{
return View();
}
[HttpGet("struk")]
public IActionResult Struk()
{
return View();
}
}
}

View File

@ -0,0 +1,104 @@
@{
ViewData["Title"] = "Detail Batal Penjemputan";
}
<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">Pembatalan Penjemputan</h1>
<div class="w-9"></div>
</div>
</div>
<div class="px-4 pt-4">
<div class="bg-white rounded-2xl p-4 shadow-sm border border-gray-100 mb-4">
<div class="flex items-center gap-3 mb-3">
<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="map-pin"></i>
</div>
<div>
<h3 class="font-bold text-gray-900">CV Tri Berkah Sejahtera</h3>
<p class="text-xs text-gray-500">Lokasi yang dibatalkan</p>
</div>
</div>
<p class="text-sm text-gray-700 leading-relaxed">
Kp. Pertanian II Rt.004 Rw.001 Kel. Klender Kec, Duren Sawit, Kota Adm. Jakarta Timur 13470
</p>
</div>
</div>
<div class="px-4 pb-6">
<div class="bg-white rounded-2xl p-5 shadow-sm 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>
<div>
<h2 class="text-lg font-bold text-gray-900">Form Pembatalan</h2>
<p class="text-xs text-gray-500">Berikan keterangan</p>
</div>
</div>
<form asp-action="Batal" method="post" class="space-y-5">
<!-- Alasan Pembatalan -->
<div>
<label class="block text-sm font-semibold text-gray-700 mb-3">Alasan Pembatalan</label>
<textarea name="AlasanPembatalan"
class="w-full rounded-xl text-sm border border-gray-300 focus:border-red-500 focus:ring-2 focus:ring-red-200 p-4 text-gray-700 resize-none transition-all duration-200"
rows="5"
placeholder="Jelaskan alasan pembatalan penjemputan..."
required></textarea>
<div class="text-red-500 text-sm mt-2" id="validation-message" style="display: none;">
Harap isi alasan pembatalan
</div>
</div>
<div class="flex gap-3 pt-4">
<a href="@Url.Action("Index", "Home")"
class="flex-1 bg-gray-200 text-gray-700 font-semibold py-3 rounded-xl text-center hover:bg-gray-300 transition-colors">
Batal
</a>
<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">
Konfirmasi
</button>
</div>
</form>
</div>
</div>
<!-- Bottom Navigation -->
<partial name="~/Views/Shared/Components/_Navigation.cshtml" />
</div>
<register-block dynamic-section="scripts" key="jsDetailBatal">
<script>
document.addEventListener('DOMContentLoaded', function() {
const alasanTextarea = document.querySelector('textarea[name="AlasanPembatalan"]');
const form = document.querySelector('form');
const validationMessage = document.getElementById('validation-message');
form.addEventListener('submit', function(e) {
if (!alasanTextarea.value.trim()) {
e.preventDefault();
validationMessage.style.display = 'block';
alasanTextarea.focus();
alasanTextarea.style.borderColor = '#ef4444';
return false;
}
validationMessage.style.display = 'none';
return true;
});
alasanTextarea.addEventListener('input', function() {
if (this.value.trim()) {
validationMessage.style.display = 'none';
this.style.borderColor = '';
}
});
});
</script>
</register-block>

View File

@ -52,7 +52,7 @@
<img src="@Url.Content("~/odo_simple.svg")" class="overflow-visible drop-shadow-lg scale-110" alt=""> <img src="@Url.Content("~/odo_simple.svg")" class="overflow-visible drop-shadow-lg scale-110" alt="">
<!-- Digital display --> <!-- Digital display -->
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2"> <div class="absolute bottom-8 left-1/2 transform -translate-x-1/2">
<input type="text" maxlength="6" 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" /> <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" />
</div> </div>
</div> </div>
</div> </div>
@ -66,7 +66,8 @@
</button> </button>
</div> </div>
</div> </div>
<partial name="~/Views/Shared/Components/_Navigation.cshtml" /> <!-- Bottom Navigation -->
<partial name="~/Views/Shared/Components/_Navigation.cshtml" />
</div> </div>
<register-block dynamic-section="scripts" key="jsDetailPenjemputan"> <register-block dynamic-section="scripts" key="jsDetailPenjemputan">
@ -77,7 +78,7 @@
odoInput.addEventListener('focus', function() { odoInput.addEventListener('focus', function() {
setTimeout(function() { setTimeout(function() {
odoInput.scrollIntoView({ behavior: 'smooth', block: 'center' }); odoInput.scrollIntoView({ behavior: 'smooth', block: 'center' });
}, 300); // delay agar keyboard muncul dulu }, 300);
}); });
} }
}); });

View File

@ -0,0 +1,162 @@
@{
ViewData["Title"] = "Detail Perjalanan - DLH";
}
<div class="max-w-sm mx-auto bg-gray-50 min-h-screen">
<!-- 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="flex items-center justify-between">
<a href="@Url.Action("Index", "History")" 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">Detail Perjalanan</h1>
<div class="w-9"></div>
</div>
</div>
<div class="px-4 py-4 space-y-4">
<!-- SPJ Information Card -->
<div class="bg-white rounded-2xl p-5 shadow-sm 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>
<div>
<h2 class="text-lg font-bold text-gray-900">Data SPJ</h2>
<p class="text-xs text-gray-500">Surat Perintah Jalan</p>
</div>
</div>
<div class="space-y-3">
<div class="flex justify-between items-center py-2 border-b border-gray-50">
<span class="text-sm text-gray-600">No. SPJ</span>
<span class="font-semibold text-gray-900 text-sm">SPJ/07-2025/PKM/000476</span>
</div>
<div class="flex justify-between items-center py-2 border-b border-gray-50">
<span class="text-sm text-gray-600">Plat Nomor</span>
<span class="bg-orange-50 text-orange-700 px-3 py-1 rounded-full text-sm font-medium">B 9632 TOR</span>
</div>
<div class="flex justify-between items-center py-2 border-b border-gray-50">
<span class="text-sm text-gray-600">Nomer Pintu</span>
<span class="font-mono text-sm text-gray-700">JRC 005</span>
</div>
<div class="flex justify-between items-center py-2">
<span class="text-sm text-gray-600">Tujuan Pembuangan</span>
<span class="font-semibold text-gray-900 text-sm">Taman Barito</span>
</div>
</div>
</div>
<!-- Summary Card -->
<div class="bg-white rounded-2xl p-5 shadow-sm 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="bar-chart-3"></i>
</div>
<div>
<h2 class="text-lg font-bold text-gray-900">Ringkasan</h2>
<p class="text-xs text-gray-500">Informasi perjalanan</p>
</div>
</div>
<div class="grid grid-cols-4 gap-3">
<div class="text-center p-3 bg-gray-50 rounded-xl">
<div class="text-xl font-bold text-gray-900">3</div>
<div class="text-xs text-gray-600">Total</div>
</div>
<div class="text-center p-3 bg-green-50 rounded-xl">
<div class="text-xl font-bold text-green-600">1</div>
<div class="text-xs text-gray-600">Selesai</div>
</div>
<div class="text-center p-3 bg-yellow-50 rounded-xl">
<div class="text-xl font-bold text-yellow-600">1</div>
<div class="text-xs text-gray-600">Proses</div>
</div>
<div class="text-center p-3 bg-red-50 rounded-xl">
<div class="text-xl font-bold text-red-600">1</div>
<div class="text-xs text-gray-600">Batal</div>
</div>
</div>
</div>
<!-- Pickup Locations -->
<div class="bg-white rounded-2xl p-5 shadow-sm 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="map-pin"></i>
</div>
<div>
<h2 class="text-lg font-bold text-gray-900">Lokasi Pengangkutan</h2>
<p class="text-xs text-gray-500">Daftar lokasi yang dikunjungi</p>
</div>
</div>
<div class="space-y-4">
<!-- Location 1 - In Progress -->
<div class="border border-yellow-200 bg-yellow-50 rounded-xl p-4">
<div class="flex items-start gap-3">
<div class="w-8 h-8 bg-yellow-500 rounded-full flex items-center justify-center flex-shrink-0 mt-1">
<i class="w-4 h-4 text-white" data-lucide="clock"></i>
</div>
<div class="flex-1">
<div class="flex items-center gap-2 mb-2">
<span class="bg-yellow-400 text-white text-xs font-semibold px-2 py-1 rounded-full">Pengangkutan</span>
<span class="text-xs text-gray-500">Lokasi 1</span>
</div>
<h4 class="font-bold text-gray-900 mb-1">CV Tri Mitra Utama</h4>
<p class="text-sm text-gray-600 mb-1">Shell Radio Dalam</p>
<p class="text-sm text-gray-600 mb-2">Alamat:</p>
<p class="text-sm text-gray-700 leading-relaxed">
Jl. Radio Dalam Raya No.6C Gandaria Utara, Kecamatan Kebayoran Baru, Kota Jakarta Selatan 12140
</p>
</div>
</div>
</div>
<!-- Location 2 - Completed -->
<div class="border border-green-200 bg-green-100 rounded-xl p-4">
<div class="flex items-start gap-3">
<div class="w-8 h-8 bg-green-500 rounded-full flex items-center justify-center flex-shrink-0 mt-1">
<i class="w-4 h-4 text-white" data-lucide="check"></i>
</div>
<div class="flex-1">
<div class="flex items-center gap-2 mb-2">
<span class="bg-green-500 text-white text-xs font-semibold px-2 py-1 rounded-full">Sudah Diangkut</span>
<span class="text-xs text-gray-500">Lokasi 2</span>
</div>
<h4 class="font-bold text-gray-900 mb-1">CV Tri Berkah Sejahtera</h4>
<p class="text-sm text-gray-600 mb-2">Alamat:</p>
<p class="text-sm text-gray-700 leading-relaxed">
Kp. Pertanian II Rt.004 Rw.001 Kel. Klender Kec, Duren Sawit, Kota Adm. Jakarta Timur 13470
</p>
</div>
</div>
</div>
<!-- Location 3 - Cancelled -->
<div class="border border-red-200 bg-red-100 rounded-xl p-4">
<div class="flex items-start gap-3">
<div class="w-8 h-8 bg-red-500 rounded-full flex items-center justify-center flex-shrink-0 mt-1">
<i class="w-4 h-4 text-white" data-lucide="x"></i>
</div>
<div class="flex-1">
<div class="flex items-center gap-2 mb-2">
<span class="bg-red-500 text-white text-xs font-semibold px-2 py-1 rounded-full">Batal Angkut</span>
<span class="text-xs text-gray-500">Lokasi 3</span>
</div>
<h4 class="font-bold text-gray-900 mb-1">CV Tri Berkah Sejahtera</h4>
<p class="text-sm text-gray-600 mb-2">Alamat:</p>
<p class="text-sm text-gray-700 leading-relaxed">
Kp. Pertanian II Rt.004 Rw.001 Kel. Klender Kec, Duren Sawit, Kota Adm. Jakarta Timur 13470
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Bottom Navigation -->
<partial name="~/Views/Shared/Components/_Navigation.cshtml" />
</div>

View File

@ -0,0 +1,153 @@
@{
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/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>

View File

@ -14,7 +14,7 @@
<i class="w-4 h-4 text-white" data-lucide="map-pin"></i> <i class="w-4 h-4 text-white" data-lucide="map-pin"></i>
<span class="text-sm opacity-90">Lokasi Anda:</span> <span class="text-sm opacity-90">Lokasi Anda:</span>
</div> </div>
<p id="userLocation" class="font-semibold text-sm tracking-wide cursor-pointer underline text-white hover:text-orange-200 transition"> <p id="userLocation" class="font-semibold text-xs tracking-wide cursor-pointer underline text-white hover:text-orange-200 transition">
Mendeteksi lokasi... Mendeteksi lokasi...
</p> </p>
</div> </div>
@ -27,7 +27,6 @@
<!-- SPJ Data Card --> <!-- SPJ Data Card -->
<div class="bg-green-500 text-white mx-4 px-6 py-6 mt-40 rounded-2xl relative overflow-hidden shadow-lg z-21"> <div class="bg-green-500 text-white mx-4 px-6 py-6 mt-40 rounded-2xl relative overflow-hidden shadow-lg z-21">
<!-- Background pattern -->
<div class="absolute right-0 bottom-0 opacity-30 pointer-events-none select-none" style="width: 160px; height: 160px;"> <div class="absolute right-0 bottom-0 opacity-30 pointer-events-none select-none" style="width: 160px; height: 160px;">
<img src="@Url.Content("~/tree.svg")" alt="tree" class="w-full h-full object-contain"> <img src="@Url.Content("~/tree.svg")" alt="tree" class="w-full h-full object-contain">
</div> </div>
@ -54,56 +53,82 @@
</div> </div>
</div> </div>
<!-- Pickup Locations --> <!-- Lokasi Pengangkutan -->
<div class="px-4 mt-8"> <div class="px-4 mt-8">
<div class="flex justify-between items-center mb-4"> <div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold text-gray-800">Lokasi Pengangkutan</h3> <h3 class="text-lg font-semibold text-gray-800">Lokasi Pengangkutan</h3>
<button class="bg-gray-400 text-white px-4 py-1 rounded-full text-sm"> <div class="relative group">
Selesai <i class="w-5 h-5 cursor-pointer text-gray-500" data-lucide="info"></i>
</button> <div class="absolute right-full top-1/2 -translate-y-1/2 mr-2 w-max px-3 py-2 bg-gray-800 text-white text-xs rounded shadow-lg opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none z-30">
Selesaikan semua lokasi <br> penjemputan untuk mengakhiri SPJ
</div>
</div>
</div> </div>
<div class="flex flex-col gap-2">
<!-- Location 1 - Completed --> <!-- Location 1 - Berlangsung -->
<a href="@Url.Action("Index", "DetailPenjemputan")" class="hover:cursor-pointer"> <a href="@Url.Action("Index", "DetailPenjemputan")" class="hover:cursor-pointer">
<div class="bg-green-100 border border-green-200 rounded-lg p-4 mb-3 relative"> <div class="bg-white border border-gray-200 rounded-lg p-4 mb-3 relative">
<div class="flex justify-between items-start"> <div class="flex justify-between items-start">
<div class="flex-1"> <div class="flex-1">
<span class="inline-block bg-green-500 text-white text-xs font-semibold px-3 py-1 rounded-full mb-1">Sudah Diangkut</span> <span class="inline-block bg-yellow-400 text-white text-xs font-semibold px-3 py-1 rounded-full mb-1">Pengangkutan</span>
<h4 class="font-semibold text-gray-800 mb-2">CV Tri Berkah Sejahtera</h4> <h4 class="font-semibold text-gray-800 mb-2">CV Tri Mitra Utama - Shell Radio Dalam</h4>
<p class="text-sm text-gray-600 mb-1">Alamat</p> <p class="text-sm text-gray-600 mb-1">Alamat</p>
<p class="text-sm text-gray-700"> <p class="text-sm text-gray-700">
Kp. Pertanian II Rt.004 Rw.001 Kel. Klender Kec, Duren Sawit, Kota Adm. Jakarta Timur 13470 Kp. Pertanian II Rt.004 Rw.001 Kel. Klender Kec, Duren Sawit, Kota Adm. Jakarta Timur 13470
</p> </p>
</div> </div>
<div class="ml-4"> <div class="ml-4">
<div class="w-8 h-8 bg-green-500 rounded-full flex items-center justify-center"> <div class="w-8 h-8 border-2 border-gray-300 rounded-full flex items-center justify-center">
<i class="w-5 h-5 text-white" data-lucide="circle-check"></i> <i class="w-5 h-5 text-gray-400" data-lucide="circle-ellipsis"></i>
</div>
</div>
</div> </div>
</div> </div>
</div> </a>
</div> <!-- Location 2 - Selesai -->
</a> <a href="@Url.Action("Index", "DetailPenjemputan")" class="hover:cursor-pointer">
<div class="bg-green-100 border border-green-200 rounded-lg p-4 mb-3 relative">
<!-- Location 2 - Pending --> <div class="flex justify-between items-start">
<div class="bg-white border border-gray-200 rounded-lg p-4 mb-6 relative"> <div class="flex-1">
<div class="flex justify-between items-start"> <span class="inline-block bg-green-500 text-white text-xs font-semibold px-3 py-1 rounded-full mb-1">Sudah Diangkut</span>
<div class="flex-1"> <h4 class="font-semibold text-gray-800 mb-2">CV Tri Berkah Sejahtera</h4>
<span class="inline-block bg-yellow-400 text-white text-xs font-semibold px-3 py-1 rounded-full mb-1">Pengangkutan</span> <p class="text-sm text-gray-600 mb-1">Alamat</p>
<h4 class="font-semibold text-gray-800 mb-2">CV Tri Mitra Utama</h4> <p class="text-sm text-gray-700">
<p class="text-sm text-gray-600 mb-1">Shell Radio Dalam</p> Kp. Pertanian II Rt.004 Rw.001 Kel. Klender Kec, Duren Sawit, Kota Adm. Jakarta Timur 13470
<p class="text-sm text-gray-600 mb-1">Alamat</p> </p>
<p class="text-sm text-gray-700"> </div>
Jl. Radio Dalam Raya No.6C Gandaria Utara, Kecamatan Kebayoran Baru, Kota Jakarta Selatan 12140 <div class="ml-4">
</p> <div class="w-8 h-8 bg-green-500 rounded-full flex items-center justify-center">
</div> <i class="w-5 h-5 text-white" data-lucide="circle-check"></i>
<div class="ml-4"> </div>
<div class="w-8 h-8 border-2 border-gray-300 rounded-full flex items-center justify-center"> </div>
<i class="w-5 h-5 text-gray-400" data-lucide="circle-ellipsis"></i>
</div> </div>
</div> </div>
</div> </a>
<!-- Location 3 - Batal -->
<a href="@Url.Action("Batal", "DetailPenjemputan")" class="hover:cursor-pointer">
<div class="bg-red-100 border border-red-200 rounded-lg p-4 mb-3 relative">
<div class="flex justify-between items-start">
<div class="flex-1">
<span class="inline-block bg-red-500 text-white text-xs font-semibold px-3 py-1 rounded-full mb-1">Batal Angkut</span>
<h4 class="font-semibold text-gray-800 mb-2">CV Tri Berkah Sejahtera</h4>
<p class="text-sm text-gray-600 mb-1">Alamat</p>
<p class="text-sm text-gray-700">
Kp. Pertanian II Rt.004 Rw.001 Kel. Klender Kec, Duren Sawit, Kota Adm. Jakarta Timur 13470
</p>
</div>
<div class="ml-4">
<div class="w-8 h-8 bg-red-500 rounded-full flex items-center justify-center">
<i class="w-5 h-5 text-white" data-lucide="circle-x"></i>
</div>
</div>
</div>
</div>
</a>
</div> </div>
</div> </div>
<!-- Bottom Navigation --> <!-- Bottom Navigation -->
<partial name="~/Views/Shared/Components/_Navigation.cshtml" /> <partial name="~/Views/Shared/Components/_Navigation.cshtml" />
@ -149,12 +174,11 @@ document.addEventListener("DOMContentLoaded", function () {
} }
} }
// Ambil dari localStorage kalo ada
const savedAddress = localStorage.getItem("user_address"); const savedAddress = localStorage.getItem("user_address");
if (savedAddress) { if (savedAddress) {
userLocationEl.textContent = savedAddress; userLocationEl.textContent = savedAddress;
} else { } else {
getLocationUpdate(); // Pertama kali ambil lokasi getLocationUpdate();
} }
// Update Lokasi cuy // Update Lokasi cuy

View File

@ -0,0 +1,277 @@
@{
ViewData["Title"] = "Login eSPJ";
}
<div class="bg-gradient-to-br from-indigo-50 via-white to-purple-50">
<div class="max-w-sm mx-auto bg-white min-h-screen shadow-xl relative overflow-hidden">
<!-- Background Pattern -->
<div class="absolute inset-0 opacity-5">
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse">
<path d="M 20 0 L 0 0 0 20" fill="none" stroke="#667eea" stroke-width="1"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#grid)" />
</svg>
</div>
<!-- Splash Screens Container -->
<div id="splashContainer" class="splash-container" style="width: 400%; display: flex;">
<!-- Splash Screen 1 -->
<div class="w-1/4 flex flex-col items-center justify-center h-screen px-6 relative">
<div class="fade-in flex flex-col items-center">
<div class="icon-bg w-24 h-24 rounded-3xl flex items-center justify-center mb-6 shadow-lg">
<svg class="w-12 h-12 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
</svg>
</div>
<h2 class="text-2xl font-bold mb-3 text-gray-800 text-center">Selamat Datang di eSPJ</h2>
<p class="text-gray-600 text-center leading-relaxed">Aplikasi pengelolaan Surat Perjalanan Dinas yang modern dan efisien</p>
</div>
</div>
<!-- Splash Screen 2 -->
<div class="w-1/4 flex flex-col items-center justify-center h-screen px-6 relative">
<div class="fade-in flex flex-col items-center">
<div class="icon-bg w-24 h-24 rounded-3xl flex items-center justify-center mb-6 shadow-lg">
<svg class="w-12 h-12 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<h2 class="text-2xl font-bold mb-3 text-gray-800 text-center">Mudah & Cepat</h2>
<p class="text-gray-600 text-center leading-relaxed">Proses pengajuan SPJ lebih efisien dan terintegrasi dengan sistem terbaru</p>
</div>
</div>
<!-- Splash Screen 3 -->
<div class="w-1/4 flex flex-col items-center justify-center h-screen px-6 relative">
<div class="fade-in flex flex-col items-center">
<div class="icon-bg w-24 h-24 rounded-3xl flex items-center justify-center mb-6 shadow-lg">
<svg class="w-12 h-12 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path>
</svg>
</div>
<h2 class="text-2xl font-bold mb-3 text-gray-800 text-center">Keamanan Data Terjamin</h2>
<p class="text-gray-600 text-center leading-relaxed">Data perjalanan dinas Anda aman dengan enkripsi tingkat enterprise</p>
</div>
</div>
<!-- Login Form -->
<div class="w-1/4 flex flex-col items-center justify-center h-screen px-6 relative">
<div class="w-full max-w-sm slide-up">
<div class="glass-effect rounded-3xl p-8 ">
<div class="text-center mb-8">
<div class="icon-bg w-16 h-16 rounded-2xl flex items-center justify-center mx-auto mb-4 shadow-lg">
<svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
</svg>
</div>
<h2 class="text-2xl font-bold text-gray-800 mb-2">Masuk ke eSPJ</h2>
<p class="text-gray-600">Silakan masukkan kredensial Anda</p>
</div>
<div class="space-y-4">
<button class="btn-gradient w-full py-3 px-4 rounded-xl text-white font-semibold flex items-center justify-center" type="button" onclick="showSSOModal()">
<i class="w-5 h-5 mr-3" data-lucide="key"></i>
Masuk dengan SSO
</button>
<div class="flex items-center justify-center">
</div>
</div>
</div>
</div>
</div>
</div>
<div id="navigationControls" class="absolute bottom-8 left-0 right-0 px-6">
<!-- Dot Navigation -->
<div class="flex justify-center space-x-2 mb-6">
<div class="dot w-3 h-3 rounded-full transition-all duration-300 dot-active" data-slide="0"></div>
<div class="dot w-3 h-3 rounded-full transition-all duration-300 dot-inactive" data-slide="1"></div>
<div class="dot w-3 h-3 rounded-full transition-all duration-300 dot-inactive" data-slide="2"></div>
<div class="dot w-3 h-3 rounded-full transition-all duration-300 dot-inactive" data-slide="3"></div>
</div>
<!-- Next Button -->
<div class="flex justify-between items-center">
<button id="skipBtn" class="text-gray-500 hover:text-gray-700 transition-colors duration-300">Lewati</button>
<button id="nextBtn" class="btn-gradient px-8 py-3 rounded-xl text-white font-semibold transition-all duration-300">
Selanjutnya
</button>
</div>
</div>
<!-- Modal SSO -->
<div id="ssoModal" style="display:none; position:fixed; z-index:9999; top:0; left:0; width:100vw; height:100vh; background:rgba(0,0,0,0.5);">
<div style="position:relative; width:100%; height:100%;">
<iframe id="ssoIframe" src="" style="width:90vw; max-width:400px; height:70vh; max-height:600px; border-radius:16px; border:none; position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); background:#fff;"></iframe>
<button onclick="closeSSOModal()" style="position:absolute; top:20px; right:20px; z-index:10000;">Tutup</button>
</div>
</div>
</div>
</div>
@section Styles {
<style>
.splash-container {
transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.fade-in {
animation: fadeIn 0.8s ease-out;
}
.slide-up {
animation: slideUp 0.6s ease-out;
}
@@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@@keyframes slideUp {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}
.dot-active {
background: linear-gradient(135deg, #fb923c 0%, #f59e42 100%);
transform: scale(1.2);
}
.dot-inactive {
background: #fde68a;
}
.btn-gradient {
background: linear-gradient(135deg, #fb923c 0%, #f59e42 100%);
box-shadow: 0 4px 15px rgba(251, 146, 60, 0.4);
}
.btn-gradient:hover {
box-shadow: 0 8px 25px rgba(251, 146, 60, 0.6);
transform: translateY(-2px);
}
.glass-effect {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.icon-bg {
background: linear-gradient(135deg, #fb923c 0%, #f59e42 100%);
}
.form-input {
transition: all 0.3s ease;
}
.form-input:focus {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(251, 146, 60, 0.15);
}
</style>
}
@section Scripts {
<script>
let currentSlide = 0;
const totalSlides = 4;
const container = document.getElementById('splashContainer');
const dots = document.querySelectorAll('.dot');
const nextBtn = document.getElementById('nextBtn');
const skipBtn = document.getElementById('skipBtn');
const navigationControls = document.getElementById('navigationControls');
function updateSlide(slideIndex) {
container.style.transform = `translateX(-${slideIndex * 25}%)`;
dots.forEach((dot, index) => {
if (index === slideIndex) {
dot.classList.remove('dot-inactive');
dot.classList.add('dot-active');
} else {
dot.classList.remove('dot-active');
dot.classList.add('dot-inactive');
}
});
if (slideIndex === totalSlides - 1) {
navigationControls.style.display = 'none';
} else {
navigationControls.style.display = 'block';
nextBtn.textContent = slideIndex === totalSlides - 2 ? 'Masuk' : 'Selanjutnya';
}
}
function nextSlide() {
if (currentSlide < totalSlides - 1) {
currentSlide++;
updateSlide(currentSlide);
}
}
function skipToLogin() {
currentSlide = totalSlides - 1;
updateSlide(currentSlide);
}
nextBtn.addEventListener('click', nextSlide);
skipBtn.addEventListener('click', skipToLogin);
dots.forEach((dot, index) => {
dot.addEventListener('click', () => {
currentSlide = index;
updateSlide(currentSlide);
});
});
let startX = 0;
let endX = 0;
container.addEventListener('touchstart', (e) => {
startX = e.touches[0].clientX;
});
container.addEventListener('touchend', (e) => {
endX = e.changedTouches[0].clientX;
handleSwipe();
});
function handleSwipe() {
const swipeThreshold = 50;
const diff = startX - endX;
if (Math.abs(diff) > swipeThreshold) {
if (diff > 0 && currentSlide < totalSlides - 1) {
nextSlide();
} else if (diff < 0 && currentSlide > 0) {
currentSlide--;
updateSlide(currentSlide);
}
}
}
</script>
<script>
function showSSOModal() {
document.getElementById('ssoIframe').src = '@ViewBag.SSOLoginUrl';
document.getElementById('ssoModal').style.display = 'block';
}
function closeSSOModal() {
document.getElementById('ssoModal').style.display = 'none';
document.getElementById('ssoIframe').src = '';
}
// biar bisa nerima pesan dari iframe SSO ( endpoint callback harus mengirim window.parent.postMessage)
window.addEventListener('message', function(event) {
if (event.data === 'sso-success') {
closeSSOModal();
window.location.href = '/';
}
});
</script>
}

View File

@ -99,5 +99,7 @@
</button> </button>
</div> </div>
<partial name="~/Views/Shared/Components/_Navigation.cshtml" /> <!-- Bottom Navigation -->
<partial name="~/Views/Shared/Components/_Navigation.cshtml" />
</div> </div>

View File

@ -1,12 +1,8 @@
<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 max-w-sm z-99">
<!-- Navigation Bar with Curved Inward Notch -->
<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">
<!-- Curved Notch using CSS -->
<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">
<!-- Left curve -->
<div class="absolute left-0 top-0 w-10 h-10 backdrop-blur-lg rounded-br-full"></div> <div class="absolute left-0 top-0 w-10 h-10 backdrop-blur-lg rounded-br-full"></div>
<!-- Right curve -->
<div class="absolute right-0 top-0 w-10 h-10 backdrop-blur-lg rounded-bl-full"></div> <div class="absolute right-0 top-0 w-10 h-10 backdrop-blur-lg rounded-bl-full"></div>
</div> </div>
</div> </div>
@ -22,108 +18,31 @@
<span class="text-xs text-gray-600 group-hover:text-orange-500 font-medium transition-colors duration-300">Home</span> <span class="text-xs text-gray-600 group-hover:text-orange-500 font-medium transition-colors duration-300">Home</span>
</a> </a>
<!-- Spacer for center FAB -->
<div class="w-12"></div> <div class="w-12"></div>
<!-- Profile Button --> <!-- Profile Button -->
<a href="@Url.Action("Index", "Profil")" class="flex flex-col items-center gap-1 px-4 py-2 transition-all duration-300 hover:scale-105 group"> <a href="@Url.Action("Index", "History")" class="flex flex-col items-center gap-1 px-4 py-2 transition-all duration-300 hover:scale-105 group">
<div class="relative"> <div class="relative">
<i class="w-6 h-6 text-gray-400 group-hover:text-orange-500 transition-colors duration-300" data-lucide="user"></i> <i class="w-6 h-6 text-gray-400 group-hover:text-orange-500 transition-colors duration-300" data-lucide="clipboard-check"></i>
<div class="absolute -bottom-0.5 left-1/2 transform -translate-x-1/2 w-0 h-0.5 bg-orange-500 group-hover:w-full transition-all duration-300"></div> <div class="absolute -bottom-0.5 left-1/2 transform -translate-x-1/2 w-0 h-0.5 bg-orange-500 group-hover:w-full transition-all duration-300"></div>
</div> </div>
<span class="text-xs text-gray-600 group-hover:text-orange-500 font-medium transition-colors duration-300">Profile</span> <span class="text-xs text-gray-600 group-hover:text-orange-500 font-medium transition-colors duration-300">History</span>
</a> </a>
</div> </div>
</div> </div>
<!-- Center Floating Action Button in Curved Notch --> <!-- Center Submit -->
<div class="absolute -top-4 left-1/2 transform -translate-x-1/2"> <div class="absolute -top-4 left-1/2 transform -translate-x-1/2">
<button id="truckBtn" class="w-14 h-14 bg-gradient-to-br from-orange-500 via-orange-400 to-orange-600 rounded-full shadow-xl flex items-center justify-center transition-all duration-300 hover:scale-110 hover:rotate-6 border-4 border-white ring-2 ring-orange-200"> <a href="@Url.Action("Index", "Submit")" id="truckBtn" class="hover:cursor-pointer w-14 h-14 bg-gradient-to-br from-orange-500 via-orange-400 to-orange-600 rounded-full shadow-xl flex items-center justify-center transition-all duration-300 hover:scale-110 hover:rotate-6 border-4 border-white ring-2 ring-orange-200">
<i class="w-6 h-6 text-white" data-lucide="truck"></i> <i class="w-6 h-6 text-white" data-lucide="truck"></i>
</button> </a>
</div>
</div>
<div class="h-40"></div>
<!-- Modal Overlay -->
<div id="modalOverlay" class="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 opacity-0 invisible transition-all duration-300 flex items-center justify-center">
<!-- Modal Content -->
<div id="modalContent" class="transform scale-95 opacity-0 transition-all duration-300 ease-out max-w-sm w-full mx-4">
<div class="bg-green-500 text-white px-6 py-6 rounded-2xl relative overflow-hidden shadow-2xl">
<!-- Background pattern -->
<div class="absolute right-0 bottom-0 opacity-30 pointer-events-none select-none" style="width: 160px; height: 160px;">
<!-- Tree SVG placeholder -->
<div class="w-full h-full bg-green-400/20 rounded-full flex items-center justify-center">
<img src="@Url.Content("~/tree.svg")" alt="tree" class="w-full h-full object-contain">
</div>
</div>
<div class="relative z-10">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">Data SPJ</h2>
<div class="flex flex-col items-end mt-8">
<div class="bg-white text-green-600 px-4 py-2 rounded-full text-base font-bold shadow-md flex items-center gap-2">
<span>B 9632 TOR</span>
</div>
<div class="text-xs text-white mt-1 font-semibold tracking-wide opacity-80">(JRC 005)</div>
</div>
</div>
<div class="space-y-1 mt-2">
<p class="text-sm opacity-90">No. SPJ</p>
<p class="font-bold text-lg tracking-wide">SPJ/07-2025/PKM/000476</p>
<p class="text-sm opacity-90 mt-3">Tujuan Pembuangan</p>
<p class="font-bold text-lg tracking-wide">Taman Barito</p>
</div>
<!-- DLH logo -->
<div class="absolute bottom-2 right-4 opacity-80" style="width: 48px; height: 48px;">
<!-- DLH Logo placeholder -->
<div class="w-full h-full flex items-center justify-center">
<img src="@Url.Content("~/dlh_type.svg")" alt="DLH Logo" class="w-full h-full object-contain">
</div>
</div>
</div>
<!-- Close button -->
<button id="closeModal" class="absolute top-4 right-4 w-8 h-8 bg-white/20 hover:bg-white/30 rounded-full flex items-center justify-center transition-colors duration-200 hover:cursor-pointer">
<i class="w-4 h-4 text-white" data-lucide="x"></i>
</button>
</div>
</div> </div>
</div> </div>
<div class="h-30"></div>
<register-block dynamic-section="scripts" key="jsNav"> <register-block dynamic-section="scripts" key="jsNav">
<script>
// Modal functionality
const truckBtn = document.getElementById('truckBtn');
const modalOverlay = document.getElementById('modalOverlay');
const modalContent = document.getElementById('modalContent');
const closeModal = document.getElementById('closeModal');
// Show modal
truckBtn.addEventListener('click', () => {
modalOverlay.classList.remove('opacity-0', 'invisible');
modalOverlay.classList.add('opacity-100', 'visible');
modalContent.classList.remove('scale-95', 'opacity-0');
modalContent.classList.add('scale-100', 'opacity-100');
});
// Hide modal
function hideModal() {
modalOverlay.classList.remove('opacity-100', 'visible');
modalOverlay.classList.add('opacity-0', 'invisible');
modalContent.classList.remove('scale-100', 'opacity-100');
modalContent.classList.add('scale-95', 'opacity-0');
}
// Close modal events
closeModal.addEventListener('click', hideModal);
modalOverlay.addEventListener('click', (e) => {
if (e.target === modalOverlay) {
hideModal();
}
});
</script>
</register-block> </register-block>

View File

@ -40,6 +40,9 @@
@RenderBody() @RenderBody()
<script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script> <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script> <script src="~/js/site.js" asp-append-version="true"></script>

View File

@ -0,0 +1,125 @@
@{
ViewData["Title"] = "Submit Foto Muatan";
}
<div class="max-w-sm mx-auto bg-white min-h-screen">
<!-- Header with Orange Background -->
<div class="bg-orange-500 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>
</a>
<h1 class="text-lg font-bold">Unggah Foto Muatan</h1>
<div class="w-8"></div>
</div>
</div>
<!-- Upload -->
<div class="px-4 py-6">
<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>
<div>
<h2 class="text-lg font-bold text-gray-900">Foto Muatan Kendaraan</h2>
<p class="text-xs text-gray-500">Optional</p>
</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>
<!-- Lokasi User -->
<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" class="mt-6">
<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>
<!-- Bottom Navigation -->
<partial name="~/Views/Shared/Components/_Navigation.cshtml" />
</div>
<register-block dynamic-section="scripts" key="jsSubmit">
<script>
</script>
<script>
document.addEventListener("DOMContentLoaded", function () {
const userLocationEl = document.getElementById("userLocationSubmit");
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;
localStorage.setItem("user_latitude", lat);
localStorage.setItem("user_longitude", lng);
localStorage.setItem("user_address", address);
})
.catch(() => {
userLocationEl.textContent = `${lat}, ${lng}`;
});
}
function getLocationUpdate() {
if ("geolocation" in navigator) {
userLocationEl.textContent = "Mendeteksi lokasi baru...";
navigator.geolocation.getCurrentPosition(
function (position) {
const lat = position.coords.latitude.toFixed(6);
const lng = position.coords.longitude.toFixed(6);
reverseGeocode(lat, lng);
},
function () {
userLocationEl.textContent = "Lokasi tidak diizinkan";
}
);
} else {
userLocationEl.textContent = "Browser tidak mendukung lokasi";
}
}
const savedAddress = localStorage.getItem("user_address");
if (savedAddress) {
userLocationEl.textContent = savedAddress;
} else {
getLocationUpdate();
}
// Update Lokasi
userLocationEl.addEventListener("click", function () {
getLocationUpdate();
});
});
</script>
</register-block>

View File

@ -0,0 +1,81 @@
@{
ViewData["Title"] = "Submit Struk";
}
<div class="max-w-sm mx-auto bg-white min-h-screen">
<!-- Header with Orange Background -->
<div class="bg-orange-500 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>
</a>
<h1 class="text-lg font-bold">Unggah Struk</h1>
<div class="w-8"></div>
</div>
</div>
<form action="/submit-struk" method="post" class="px-8 py-8 space-y-6 bg-white rounded-xl mt-2">
<div class="flex flex-col items-center space-y-2">
<div class="bg-orange-100 rounded-full p-3">
<i data-lucide="file-text" class="w-7 h-7 text-orange-500"></i>
</div>
<h2 class="text-xl font-bold text-orange-500">Isi Data Struk</h2>
<p class="text-sm text-gray-500 text-center">Masukkan nomor struk dan berat muatan dengan benar.</p>
</div>
<div>
<label for="NomorStruk" class="block text-sm font-medium text-gray-700 mb-1">Nomor Struk</label>
<input
type="text"
id="NomorStruk"
name="NomorStruk"
inputmode="numeric"
pattern="[0-9]*"
class="mt-1 block w-full rounded-lg border border-orange-300 shadow-sm focus:border-orange-500 focus:ring-2 focus:ring-orange-200 transition-all duration-150 px-4 py-2"
required
placeholder="1234567890"
/>
</div>
<div>
<label for="BeratMuatan" class="block text-sm font-medium text-gray-700 mb-1">Berat Muatan (kg)</label>
<input
type="text"
id="BeratMuatan"
name="BeratMuatan"
inputmode="decimal"
pattern="[0-9]*\.?[0-9]*"
class="mt-1 block w-full rounded-lg border border-orange-300 shadow-sm focus:border-orange-500 focus:ring-2 focus:ring-orange-200 transition-all duration-150 px-4 py-2"
required
placeholder="1500"
/>
</div>
<button type="submit" class="w-full bg-gradient-to-r from-orange-500 to-orange-400 text-white py-3 rounded-lg font-semibold shadow hover:from-orange-600 hover:to-orange-500 transition-all duration-150 flex items-center justify-center gap-2">
<i data-lucide="send" class="w-5 h-5"></i>
Submit
</button>
</form>
<!-- Bottom Navigation -->
<partial name="~/Views/Shared/Components/_Navigation.cshtml" />
</div>
<register-block dynamic-section="scripts" key="jsSubmitStruk">
<script>
document.addEventListener('DOMContentLoaded', function() {
const nomorStrukInput = document.getElementById('NomorStruk');
const beratMuatanInput = document.getElementById('BeratMuatan');
nomorStrukInput.addEventListener('input', function() {
this.value = this.value.replace(/[^0-9]/g, '');
});
beratMuatanInput.addEventListener('input', function() {
this.value = this.value.replace(/[^0-9.]/g, '');
});
});
</script>
</register-block>

View File

@ -5,5 +5,8 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"SSO": {
"LoginUrl": "https://akun.dinaslhdki.id/Identity/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%3Fclient_id%3Dwebdinas%26redirect_uri%3Dhttps%253A%252F%252Flingkunganhidup.jakarta.go.id%252Fsignin-oidc%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520email%2520roles%26code_challenge%3Df9YuMeOzpB-egjQlGp4Pqrthdewj6YeINPhz7wgbL-k%26code_challenge_method%3DS256%26response_mode%3Dform_post%26nonce%3D638893657991954291.YTQ5OGU1NWEtOGU0Yi00NjI2LWFkOGEtZjI0YzliMWE5ZGJmYzk1NWFmM2QtOTA3YS00YmU4LWIwYmYtMjBhODc3M2Q1Mjll%26state%3DCfDJ8MtdNDKU3ypIhY_fd6D9SIg-h4wZ5PTm8sXsF0Qt60PKRgGw0d3i7fDi1lkDFBBsDPqzCl_2wM0_cfa16rr1BLmzplWuTtyIwTeTQKD6L-hhysUTyV94E2A1nocB5y-bM1hor2UaCtT9qs7LbdkFPGgUjV6ijoL0HcjilJtVzWYIo6aSsmiEUti9Q8n7XNEEGaZIVLDUH_qfykx51FMn5RCO2j-FkuSA98WBt8KyiN4-jimbr_LTkJVFClnKy_ClAfTS1vlC2a2hu-dDOdCYqlnf6QfuSCvZBf_2D4geBWnlRIHM5m8PfmtYm_WgYyQMuqYf9zkxn2_FTcrMFl4dC5ypMX5yWm0GaeMJlpUt_QYGRyMX6blGcqw5VW9YIexCX9FDuD3xSIjCqnVn6digGLBkDZ8TghO6_KJ5Jkyg8hws%26x-client-SKU%3DID_NET9_0%26x-client-ver%3D8.0.1.0%26prompt%3D"
},
"AllowedHosts": "*" "AllowedHosts": "*"
} }

File diff suppressed because it is too large Load Diff