update: jgc
parent
0d1d59cee5
commit
565ce93d4d
|
|
@ -14,19 +14,22 @@ namespace eSPJ.Controllers.SpjDriverUpstController
|
|||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly DetailPenjemputanService _detailService;
|
||||
private readonly DetailPenjemputanJGCService _jgcService;
|
||||
private readonly ILogger<DetailPenjemputanController> _logger;
|
||||
private readonly IWebHostEnvironment _env;
|
||||
|
||||
public DetailPenjemputanController(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IConfiguration configuration,
|
||||
DetailPenjemputanService detailService,
|
||||
DetailPenjemputanJGCService jgcService,
|
||||
ILogger<DetailPenjemputanController> logger,
|
||||
IWebHostEnvironment env)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_configuration = configuration;
|
||||
_detailService = detailService;
|
||||
_jgcService = jgcService;
|
||||
_logger = logger;
|
||||
_env = env;
|
||||
}
|
||||
|
|
@ -313,6 +316,11 @@ namespace eSPJ.Controllers.SpjDriverUpstController
|
|||
{
|
||||
return View("~/Views/Admin/Transport/SpjDriverUpst/DetailPenjemputan/TanpaTps.cshtml");
|
||||
}
|
||||
[HttpGet("jgc")]
|
||||
public IActionResult JGC()
|
||||
{
|
||||
return View("~/Views/Admin/Transport/SpjDriverUpst/DetailPenjemputan/JGC.cshtml");
|
||||
}
|
||||
|
||||
[HttpGet("batal")]
|
||||
public IActionResult Batal()
|
||||
|
|
@ -338,6 +346,12 @@ namespace eSPJ.Controllers.SpjDriverUpstController
|
|||
return View("~/Views/Admin/Transport/SpjDriverUpst/DetailPenjemputan/DetailSelesaiTanpaTps.cshtml");
|
||||
}
|
||||
|
||||
[HttpGet("detail-selesai-jgc")]
|
||||
public IActionResult DetailSelesaiJgc()
|
||||
{
|
||||
return View("~/Views/Admin/Transport/SpjDriverUpst/DetailPenjemputan/DetailSelesaiJGC.cshtml");
|
||||
}
|
||||
|
||||
[HttpGet("api/submitted")]
|
||||
[IgnoreAntiforgeryToken]
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
|
|
@ -436,7 +450,7 @@ namespace eSPJ.Controllers.SpjDriverUpstController
|
|||
{
|
||||
TempData["Error"] = result.Message;
|
||||
}
|
||||
|
||||
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -457,6 +471,53 @@ namespace eSPJ.Controllers.SpjDriverUpstController
|
|||
}
|
||||
}
|
||||
|
||||
[HttpPost("jgc-submit")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> SubmitJGC([FromForm] DetailPenjemputanRequest request)
|
||||
{
|
||||
var isAjaxRequest = string.Equals(Request.Headers["X-Requested-With"], "XMLHttpRequest", StringComparison.OrdinalIgnoreCase)
|
||||
|| Request.Headers.Accept.Any(value => value?.Contains("application/json", StringComparison.OrdinalIgnoreCase) == true);
|
||||
|
||||
try
|
||||
{
|
||||
var result = await _jgcService.SubmitPenjemputanAsync(request);
|
||||
|
||||
if (isAjaxRequest)
|
||||
{
|
||||
return result.Success
|
||||
? Ok(result)
|
||||
: BadRequest(result);
|
||||
}
|
||||
|
||||
if (result.Success)
|
||||
{
|
||||
TempData["Success"] = result.Message;
|
||||
}
|
||||
else
|
||||
{
|
||||
TempData["Error"] = result.Message;
|
||||
}
|
||||
|
||||
return RedirectToAction(nameof(JGC));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error submitting JGC penjemputan data");
|
||||
|
||||
if (isAjaxRequest)
|
||||
{
|
||||
return StatusCode(500, new DetailPenjemputanResponse
|
||||
{
|
||||
Success = false,
|
||||
Message = "Terjadi kesalahan saat menyimpan data."
|
||||
});
|
||||
}
|
||||
|
||||
TempData["Error"] = "Terjadi kesalahan saat menyimpan data.";
|
||||
return RedirectToAction(nameof(JGC));
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("save-record-non-tps")]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> SaveRecordNonTps()
|
||||
|
|
@ -470,6 +531,19 @@ namespace eSPJ.Controllers.SpjDriverUpstController
|
|||
return result.Success ? Ok(result) : StatusCode(500, result);
|
||||
}
|
||||
|
||||
[HttpPost("save-record-jgc")]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> SaveRecordJgc()
|
||||
{
|
||||
var request = await ResolveRecordSaveRequestAsync();
|
||||
|
||||
if (request == null)
|
||||
return BadRequest(new RecordSaveResponse { Success = false, Message = "Request tidak valid." });
|
||||
|
||||
var result = await _jgcService.SaveRecordJGCAsync(request);
|
||||
return result.Success ? Ok(result) : StatusCode(500, result);
|
||||
}
|
||||
|
||||
[HttpPost("save-record")]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> SaveRecord()
|
||||
|
|
@ -540,6 +614,62 @@ namespace eSPJ.Controllers.SpjDriverUpstController
|
|||
return Ok(new { success = true, fileNames, fileUrls, message = $"{fileNames.Count} foto kedatangan berhasil diupload." });
|
||||
}
|
||||
|
||||
[HttpPost("upload-foto-kedatangan-jgc")]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> UploadFotoKedatanganJgc(
|
||||
[FromForm] List<IFormFile>? FotoKedatangan,
|
||||
[FromForm] string? NomorSpj,
|
||||
[FromForm] string? NamaTps,
|
||||
[FromForm] string? SpjDetailId,
|
||||
[FromForm] string? LokasiAngkutId,
|
||||
[FromForm] string? WaktuKedatangan,
|
||||
[FromForm] string? Latitude,
|
||||
[FromForm] string? Longitude,
|
||||
[FromForm] string? AlamatJalan)
|
||||
{
|
||||
if (FotoKedatangan == null || FotoKedatangan.Count == 0)
|
||||
return BadRequest(new { success = false, message = "Tidak ada foto." });
|
||||
|
||||
var dateFolder = DateTime.Now.ToString("yyyy-MM-dd");
|
||||
var uploadDir = GetUploadDirectory(dateFolder, NomorSpj, NamaTps);
|
||||
|
||||
var fileNames = new List<string>();
|
||||
foreach (var file in FotoKedatangan)
|
||||
{
|
||||
if (file.Length == 0) continue;
|
||||
var ext = Path.GetExtension(file.FileName).ToLowerInvariant();
|
||||
var name = $"kedatangan_{Guid.NewGuid()}{ext}";
|
||||
var path = Path.Combine(uploadDir, name);
|
||||
await using var stream = new FileStream(path, FileMode.Create);
|
||||
await file.CopyToAsync(stream);
|
||||
fileNames.Add(name);
|
||||
}
|
||||
var fileUrls = fileNames.Select(n => BuildUploadUrl(dateFolder, n, NomorSpj, NamaTps)).ToList();
|
||||
|
||||
var saveResult = await SaveUploadedRecordAsync(
|
||||
isTps: false,
|
||||
nomorSpj: NomorSpj,
|
||||
namaTps: NamaTps,
|
||||
spjDetailId: SpjDetailId,
|
||||
lokasiAngkutId: LokasiAngkutId,
|
||||
applyChanges: request =>
|
||||
{
|
||||
request.WaktuKedatangan = string.IsNullOrWhiteSpace(WaktuKedatangan) ? request.WaktuKedatangan : WaktuKedatangan;
|
||||
request.Latitude = string.IsNullOrWhiteSpace(Latitude) ? request.Latitude : Latitude;
|
||||
request.Longitude = string.IsNullOrWhiteSpace(Longitude) ? request.Longitude : Longitude;
|
||||
request.AlamatJalan = string.IsNullOrWhiteSpace(AlamatJalan) ? request.AlamatJalan : AlamatJalan;
|
||||
request.FotoKedatanganFileNames = fileUrls;
|
||||
request.FotoKedatanganUploaded = true;
|
||||
});
|
||||
|
||||
if (!saveResult.Success)
|
||||
{
|
||||
return StatusCode(500, new { success = false, message = saveResult.Message });
|
||||
}
|
||||
|
||||
return Ok(new { success = true, fileNames, fileUrls, message = $"{fileNames.Count} foto kedatangan berhasil diupload." });
|
||||
}
|
||||
|
||||
[HttpPost("upload-foto-timbangan-non-tps")]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> UploadFotoTimbanganNonTps(
|
||||
|
|
@ -597,6 +727,56 @@ namespace eSPJ.Controllers.SpjDriverUpstController
|
|||
return Ok(new { success = true, fileName = name, fileUrl, message = $"Foto timbangan #{ItemIndex + 1} berhasil diupload." });
|
||||
}
|
||||
|
||||
[HttpPost("upload-foto-petugas-jgc")]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> UploadFotoPetugasJgc(
|
||||
[FromForm] List<IFormFile>? FotoPetugas,
|
||||
[FromForm] string? NomorSpj,
|
||||
[FromForm] string? NamaTps,
|
||||
[FromForm] string? SpjDetailId,
|
||||
[FromForm] string? LokasiAngkutId,
|
||||
[FromForm] string? NamaPetugas)
|
||||
{
|
||||
if (FotoPetugas == null || FotoPetugas.Count == 0)
|
||||
return BadRequest(new { success = false, message = "Tidak ada foto." });
|
||||
|
||||
var dateFolder = DateTime.Now.ToString("yyyy-MM-dd");
|
||||
var uploadDir = GetUploadDirectory(dateFolder, NomorSpj, NamaTps);
|
||||
|
||||
var fileNames = new List<string>();
|
||||
foreach (var file in FotoPetugas)
|
||||
{
|
||||
if (file.Length == 0) continue;
|
||||
var ext = Path.GetExtension(file.FileName).ToLowerInvariant();
|
||||
var name = $"petugas_{Guid.NewGuid()}{ext}";
|
||||
var path = Path.Combine(uploadDir, name);
|
||||
await using var stream = new FileStream(path, FileMode.Create);
|
||||
await file.CopyToAsync(stream);
|
||||
fileNames.Add(name);
|
||||
}
|
||||
var fileUrls = fileNames.Select(n => BuildUploadUrl(dateFolder, n, NomorSpj, NamaTps)).ToList();
|
||||
|
||||
var saveResult = await SaveUploadedRecordAsync(
|
||||
isTps: false,
|
||||
nomorSpj: NomorSpj,
|
||||
namaTps: NamaTps,
|
||||
spjDetailId: SpjDetailId,
|
||||
lokasiAngkutId: LokasiAngkutId,
|
||||
applyChanges: request =>
|
||||
{
|
||||
request.FotoPetugasFileNames = fileUrls;
|
||||
request.FotoPetugasUploaded = true;
|
||||
request.NamaPetugas = string.IsNullOrWhiteSpace(NamaPetugas) ? request.NamaPetugas : NamaPetugas;
|
||||
});
|
||||
|
||||
if (!saveResult.Success)
|
||||
{
|
||||
return StatusCode(500, new { success = false, message = saveResult.Message });
|
||||
}
|
||||
|
||||
return Ok(new { success = true, fileNames, fileUrls, message = $"{fileNames.Count} foto petugas berhasil diupload." });
|
||||
}
|
||||
|
||||
[HttpPost("upload-foto-petugas-non-tps")]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> UploadFotoPetugasNonTps(
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ builder.Services.AddHttpClient();
|
|||
// Register custom services
|
||||
builder.Services.AddScoped<IDetailPenjemputanStore, FileDetailPenjemputanStore>();
|
||||
builder.Services.AddScoped<DetailPenjemputanService>();
|
||||
builder.Services.AddScoped<DetailPenjemputanJGCService>();
|
||||
builder.Services.AddScoped<HistoryService>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,221 @@
|
|||
using eSPJ.Models;
|
||||
|
||||
namespace eSPJ.Services
|
||||
{
|
||||
public class DetailPenjemputanJGCService
|
||||
{
|
||||
private readonly IDetailPenjemputanStore _store;
|
||||
private readonly IWebHostEnvironment _env;
|
||||
private readonly ILogger<DetailPenjemputanJGCService> _logger;
|
||||
|
||||
public DetailPenjemputanJGCService(
|
||||
IWebHostEnvironment env,
|
||||
IDetailPenjemputanStore store,
|
||||
ILogger<DetailPenjemputanJGCService> logger)
|
||||
{
|
||||
_env = env;
|
||||
_store = store;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
private static string SanitizePathSegment(string? value, string fallback = "jgc")
|
||||
{
|
||||
var safe = string.Concat((value ?? string.Empty).Trim().Select(c =>
|
||||
char.IsLetterOrDigit(c) || c == '-' || c == '_'
|
||||
? c
|
||||
: '-'));
|
||||
|
||||
while (safe.Contains("--"))
|
||||
{
|
||||
safe = safe.Replace("--", "-");
|
||||
}
|
||||
|
||||
safe = safe.Trim('-');
|
||||
return string.IsNullOrWhiteSpace(safe) ? fallback : safe;
|
||||
}
|
||||
|
||||
public async Task<DetailPenjemputanResponse> SubmitPenjemputanAsync(DetailPenjemputanRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(request.TpsName))
|
||||
{
|
||||
return new DetailPenjemputanResponse
|
||||
{
|
||||
Success = false,
|
||||
Message = "Nama TPS harus diisi"
|
||||
};
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(request.NamaPetugas))
|
||||
{
|
||||
return new DetailPenjemputanResponse
|
||||
{
|
||||
Success = false,
|
||||
Message = "Nama petugas harus diisi"
|
||||
};
|
||||
}
|
||||
|
||||
var existingRecord = await GetRecordDetailAsync(request.NomorSpj, request.SpjDetailId, request.LokasiAngkutId, request.TpsName);
|
||||
|
||||
var now = DateTime.Now;
|
||||
var datePart = now.ToString("yyyy-MM-dd");
|
||||
var spjFolder = SanitizePathSegment(request.NomorSpj, "spj-jgc");
|
||||
var tpsFolder = SanitizePathSegment(request.TpsName, "tps-jgc");
|
||||
var uploadPath = Path.Combine(_env.ContentRootPath, "uploads", "penjemputan", datePart, spjFolder, tpsFolder);
|
||||
var uploadBaseUrl = $"/uploads/penjemputan/{datePart}/{spjFolder}/{tpsFolder}";
|
||||
if (!Directory.Exists(uploadPath))
|
||||
{
|
||||
Directory.CreateDirectory(uploadPath);
|
||||
}
|
||||
|
||||
var tpsData = existingRecord != null
|
||||
? CloneRecord(existingRecord)
|
||||
: new TpsData();
|
||||
|
||||
tpsData.NomorSpj = request.NomorSpj;
|
||||
tpsData.LokasiAngkutId = request.LokasiAngkutId;
|
||||
tpsData.SpjDetailId = request.SpjDetailId;
|
||||
tpsData.Name = request.TpsName;
|
||||
tpsData.Latitude = request.Latitude;
|
||||
tpsData.Longitude = request.Longitude;
|
||||
tpsData.AlamatJalan = request.AlamatJalan;
|
||||
tpsData.WaktuKedatangan = request.WaktuKedatangan;
|
||||
tpsData.NamaPetugas = request.NamaPetugas;
|
||||
tpsData.IsSubmit = true;
|
||||
tpsData.SubmittedAt ??= DateTime.Now;
|
||||
tpsData.UpdatedAt = DateTime.Now;
|
||||
|
||||
if (request.FotoKedatangan != null && request.FotoKedatangan.Any())
|
||||
{
|
||||
tpsData.FotoKedatangan = new List<string>();
|
||||
foreach (var file in request.FotoKedatangan)
|
||||
{
|
||||
var fileName = $"kedatangan_{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
|
||||
var filePath = Path.Combine(uploadPath, fileName);
|
||||
using (var stream = new FileStream(filePath, FileMode.Create))
|
||||
{
|
||||
await file.CopyToAsync(stream);
|
||||
}
|
||||
tpsData.FotoKedatangan.Add($"{uploadBaseUrl}/{fileName}");
|
||||
}
|
||||
tpsData.FotoKedatanganUploaded = tpsData.FotoKedatangan.Count > 0;
|
||||
}
|
||||
else if (existingRecord?.FotoKedatangan?.Any() == true)
|
||||
{
|
||||
tpsData.FotoKedatangan = new List<string>(existingRecord.FotoKedatangan);
|
||||
tpsData.FotoKedatanganUploaded = existingRecord.FotoKedatanganUploaded || tpsData.FotoKedatangan.Count > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DetailPenjemputanResponse
|
||||
{
|
||||
Success = false,
|
||||
Message = "Foto kedatangan harus diupload"
|
||||
};
|
||||
}
|
||||
|
||||
if (request.FotoPetugas != null && request.FotoPetugas.Any())
|
||||
{
|
||||
tpsData.FotoPetugas = new List<string>();
|
||||
foreach (var file in request.FotoPetugas)
|
||||
{
|
||||
var fileName = $"petugas_{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
|
||||
var filePath = Path.Combine(uploadPath, fileName);
|
||||
using (var stream = new FileStream(filePath, FileMode.Create))
|
||||
{
|
||||
await file.CopyToAsync(stream);
|
||||
}
|
||||
tpsData.FotoPetugas.Add($"{uploadBaseUrl}/{fileName}");
|
||||
}
|
||||
tpsData.FotoPetugasUploaded = tpsData.FotoPetugas.Count > 0;
|
||||
}
|
||||
else if (existingRecord?.FotoPetugas?.Any() == true)
|
||||
{
|
||||
tpsData.FotoPetugas = new List<string>(existingRecord.FotoPetugas);
|
||||
tpsData.FotoPetugasUploaded = existingRecord.FotoPetugasUploaded || tpsData.FotoPetugas.Count > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DetailPenjemputanResponse
|
||||
{
|
||||
Success = false,
|
||||
Message = "Foto petugas harus diupload"
|
||||
};
|
||||
}
|
||||
|
||||
await _store.SaveSubmittedAsync(tpsData);
|
||||
|
||||
return new DetailPenjemputanResponse
|
||||
{
|
||||
Success = true,
|
||||
Message = "Data penjemputan berhasil disimpan",
|
||||
Data = tpsData
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error submitting penjemputan data");
|
||||
return new DetailPenjemputanResponse
|
||||
{
|
||||
Success = false,
|
||||
Message = $"Terjadi kesalahan: {ex.Message}"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<TpsData?> GetRecordDetailAsync(string nomorSpj, string? spjDetailId = null, string? lokasiAngkutId = null, string? namaTps = null)
|
||||
{
|
||||
var normalizedNomorSpj = (nomorSpj ?? string.Empty).Trim();
|
||||
var normalizedSpjDetailId = (spjDetailId ?? string.Empty).Trim();
|
||||
var normalizedLokasiAngkutId = (lokasiAngkutId ?? string.Empty).Trim();
|
||||
var normalizedNamaTps = (namaTps ?? string.Empty).Trim();
|
||||
|
||||
var allData = await _store.GetByNomorSpjAsync(normalizedNomorSpj);
|
||||
return allData
|
||||
.OrderByDescending(item => item.UpdatedAt)
|
||||
.FirstOrDefault(item =>
|
||||
(string.IsNullOrWhiteSpace(normalizedSpjDetailId) || string.Equals((item.SpjDetailId ?? string.Empty).Trim(), normalizedSpjDetailId, StringComparison.OrdinalIgnoreCase)) &&
|
||||
(string.IsNullOrWhiteSpace(normalizedLokasiAngkutId) || string.Equals((item.LokasiAngkutId ?? string.Empty).Trim(), normalizedLokasiAngkutId, StringComparison.OrdinalIgnoreCase)) &&
|
||||
(string.IsNullOrWhiteSpace(normalizedNamaTps) || string.Equals((item.Name ?? string.Empty).Trim(), normalizedNamaTps, StringComparison.OrdinalIgnoreCase)));
|
||||
}
|
||||
|
||||
public async Task<RecordSaveResponse> SaveRecordJGCAsync(RecordSaveRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _store.SaveRecordAsync(request);
|
||||
return new RecordSaveResponse { Success = true, Message = "Data tersimpan." };
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error saving JGC penjemputan record");
|
||||
return new RecordSaveResponse { Success = false, Message = $"Gagal menyimpan data: {ex.Message}" };
|
||||
}
|
||||
}
|
||||
|
||||
private static TpsData CloneRecord(TpsData source)
|
||||
{
|
||||
return new TpsData
|
||||
{
|
||||
NomorSpj = source.NomorSpj,
|
||||
LokasiAngkutId = source.LokasiAngkutId,
|
||||
SpjDetailId = source.SpjDetailId,
|
||||
Name = source.Name,
|
||||
Index = source.Index,
|
||||
Latitude = source.Latitude,
|
||||
Longitude = source.Longitude,
|
||||
AlamatJalan = source.AlamatJalan,
|
||||
WaktuKedatangan = source.WaktuKedatangan,
|
||||
FotoKedatangan = new List<string>(source.FotoKedatangan ?? new List<string>()),
|
||||
FotoKedatanganUploaded = source.FotoKedatanganUploaded,
|
||||
FotoPetugas = new List<string>(source.FotoPetugas ?? new List<string>()),
|
||||
FotoPetugasUploaded = source.FotoPetugasUploaded,
|
||||
NamaPetugas = source.NamaPetugas,
|
||||
IsSubmit = source.IsSubmit,
|
||||
UpdatedAt = source.UpdatedAt,
|
||||
SubmittedAt = source.SubmittedAt,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
@{
|
||||
Layout = "~/Views/Admin/Transport/SpjDriverUpst/Shared/_Layout.cshtml";
|
||||
ViewData["Title"] = "Detail SPJ";
|
||||
}
|
||||
|
||||
<div class="w-full lg:max-w-sm mx-auto bg-gray-50 min-h-screen pb-20">
|
||||
<div class="bg-upst text-white px-6 pt-8 pb-16 rounded-b-[40px] shadow-lg relative">
|
||||
<div class="flex items-center justify-between relative z-10">
|
||||
<a href="@Url.Action("Index", "Home")" class="w-10 h-10 flex items-center justify-center bg-white/10 rounded-xl backdrop-blur-md hover:bg-white/20 transition-all">
|
||||
<i class="w-5 h-5" data-lucide="chevron-left"></i>
|
||||
</a>
|
||||
<h1 class="text-lg font-black uppercase tracking-tight">Detail SPJ</h1>
|
||||
<div class="w-10"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="px-4 pb-6 relative -mt-10 z-20 space-y-4">
|
||||
<div class="bg-white rounded-2xl p-5 shadow-sm border border-gray-100">
|
||||
<div class="flex items-start justify-between gap-3 border-b border-gray-100 pb-4 mb-4">
|
||||
<div>
|
||||
<div class="flex items-center gap-2 mb-2 flex-wrap">
|
||||
<div class="bg-green-100 text-green-600 px-3 py-1 rounded-full text-xs font-bold border border-green-200" id="status-badge">-</div>
|
||||
<div class="text-xs text-gray-500" id="tanggal-selesai">-</div>
|
||||
</div>
|
||||
<h3 class="font-bold text-gray-900 text-lg" id="nama-perusahaan">-</h3>
|
||||
<p class="text-sm text-gray-700 leading-relaxed mt-1" id="alamat-perusahaan">-</p>
|
||||
</div>
|
||||
<div class="w-12 h-12 rounded-2xl bg-green-50 flex items-center justify-center text-green-600 border border-green-100 shrink-0">
|
||||
<i class="w-6 h-6" data-lucide="badge-check"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<div class="rounded-xl bg-gray-50 border border-gray-100 p-3">
|
||||
<p class="text-[10px] font-black uppercase tracking-widest text-gray-400 mb-1">No. SPJ</p>
|
||||
<p class="text-sm font-bold text-gray-800 wrap-break-word" id="nomor-spj">-</p>
|
||||
</div>
|
||||
<div class="rounded-xl bg-gray-50 border border-gray-100 p-3">
|
||||
<p class="text-[10px] font-black uppercase tracking-widest text-gray-400 mb-1">Plat Nomor</p>
|
||||
<p class="text-sm font-bold text-gray-800" id="plat-nomor">-</p>
|
||||
</div>
|
||||
<div class="rounded-xl bg-gray-50 border border-gray-100 p-3">
|
||||
<p class="text-[10px] font-black uppercase tracking-widest text-gray-400 mb-1">No. Pintu</p>
|
||||
<p class="text-sm font-bold text-gray-800" id="nomor-pintu">-</p>
|
||||
</div>
|
||||
<div class="rounded-xl bg-gray-50 border border-gray-100 p-3">
|
||||
<p class="text-[10px] font-black uppercase tracking-widest text-gray-400 mb-1">Petugas</p>
|
||||
<p class="text-sm font-bold text-gray-800" id="nama-checker">-</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<partial name="~/Views/Admin/Transport/SpjDriverUpst/Shared/Components/_Navigation.cshtml" />
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', async function () {
|
||||
const formatWeight = (value) => new Intl.NumberFormat('id-ID', {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
}).format(Number(value || 0));
|
||||
const formatDateTime = (value) => {
|
||||
const date = new Date(value);
|
||||
return new Intl.DateTimeFormat('id-ID', {
|
||||
day: '2-digit',
|
||||
month: 'short',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
timeZone: 'Asia/Jakarta'
|
||||
}).format(date) + ' WIB';
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch('/driver/json/selesai-jgc.json');
|
||||
const data = await response.json();
|
||||
const selesai = data.selesai;
|
||||
|
||||
document.getElementById('status-badge').textContent = selesai.status;
|
||||
document.getElementById('tanggal-selesai').textContent = formatDateTime(selesai.tanggalSelesai);
|
||||
document.getElementById('nama-perusahaan').textContent = selesai.namaPerusahaan;
|
||||
document.getElementById('alamat-perusahaan').textContent = selesai.alamat;
|
||||
document.getElementById('nomor-spj').textContent = selesai.nomorSpj;
|
||||
document.getElementById('plat-nomor').textContent = selesai.platNomor;
|
||||
document.getElementById('nomor-pintu').textContent = selesai.nomorPintu;
|
||||
document.getElementById('nama-checker').textContent = selesai.petugas.checker;
|
||||
} catch (error) {
|
||||
console.error('Error loading selesai JGC data:', error);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
@{
|
||||
Layout = "~/Views/Admin/Transport/SpjDriverUpst/Shared/_Layout.cshtml";
|
||||
ViewData["Title"] = "Detail Penjemputan - JGC";
|
||||
}
|
||||
|
||||
<div class="w-full lg:max-w-sm mx-auto min-h-screen bg-gray-50 pb-24">
|
||||
<form id="upst-antiforgery" class="hidden" aria-hidden="true">
|
||||
@Html.AntiForgeryToken()
|
||||
</form>
|
||||
|
||||
<div class="bg-upst text-white px-6 pt-8 pb-16 rounded-b-[40px] shadow-lg relative">
|
||||
<div class="flex items-center justify-between relative z-10">
|
||||
<a href="@Url.Action("Index", "Home")" class="w-10 h-10 flex items-center justify-center bg-white/10 rounded-xl backdrop-blur-md">
|
||||
<i class="w-5 h-5" data-lucide="chevron-left"></i>
|
||||
</a>
|
||||
<h1 id="detail-page-title" class="text-lg font-black uppercase tracking-tight">JGC</h1>
|
||||
<div class="w-10"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center -mt-8 mb-6 px-6 relative z-20">
|
||||
<div class="bg-white border border-gray-100 px-6 py-3 rounded-2xl flex items-center gap-4 w-full justify-between">
|
||||
<div class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-gray-400 uppercase tracking-widest">Plat Nomor</span>
|
||||
<span id="plat-nomor" class="text-green-700 font-black text-xl leading-none">B 9632 TOR</span>
|
||||
</div>
|
||||
<div class="h-8 w-[1px] bg-gray-100"></div>
|
||||
<div class="text-right">
|
||||
<span class="text-[10px] font-black text-gray-400 uppercase tracking-widest">No. Pintu</span>
|
||||
<p id="detail-nomor-pintu" class="text-orange-500 font-bold text-sm">JGC 005</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="px-6 space-y-6">
|
||||
<div class="bg-white rounded-[32px] p-6 border border-gray-100 relative overflow-hidden">
|
||||
<div class="absolute top-0 right-0 p-4">
|
||||
<span id="detail-tps-badge" class="px-3 py-1 bg-gray-500 text-white rounded-full text-[10px] font-black tracking-tighter uppercase">
|
||||
JGC
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<p class="text-[10px] text-gray-400 uppercase tracking-widest mb-1">Perusahaan</p>
|
||||
<h2 id="detail-company-name" class="text-xl font-black text-gray-800 leading-tight">Jakarta Garden City</h2>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-center gap-2 bg-gray-50 p-2 rounded-xl">
|
||||
<p id="detail-spj-number" class="text-gray-600 font-mono text-xl font-bold uppercase tracking-tighter">SPJ/07-2025/PKM/000476</p>
|
||||
</div>
|
||||
|
||||
<div class="pt-2 border-t border-gray-50">
|
||||
<div class="flex gap-2 items-start">
|
||||
<p id="detail-address" class="text-gray-500 text-xs font-medium leading-relaxed">
|
||||
Jalan TB. Simatupang Kav. 7B Cilandak, Jakarta 12430
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tps-tabs-container" class="bg-white rounded-[32px] p-6 border border-gray-100">
|
||||
<div class="flex items-center gap-2 mb-4">
|
||||
<h3 class="font-black text-gray-800">Form Pengangkutan</h3>
|
||||
<span id="detail-form-badge" class="ml-auto text-[10px] font-bold text-gray-500 bg-gray-100 px-3 py-1 rounded-full">JGC</span>
|
||||
</div>
|
||||
<div id="tps-content">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (TempData["Success"] != null)
|
||||
{
|
||||
<div class="bg-green-50 border border-green-200 text-green-700 rounded-2xl p-3 text-sm font-medium">
|
||||
@TempData["Success"]
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (TempData["Error"] != null)
|
||||
{
|
||||
<div class="bg-red-50 border border-red-200 text-red-700 rounded-2xl p-3 text-sm font-medium">
|
||||
@TempData["Error"]
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<partial name="~/Views/Admin/Transport/SpjDriverUpst/Shared/Components/_Navigation.cshtml" />
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<script src="~/driver/js/detail-penjemputan-jgc.js"></script>
|
||||
}
|
||||
|
|
@ -192,6 +192,24 @@
|
|||
</div>
|
||||
</a>
|
||||
|
||||
<a href="@Url.Action("Jgc", "DetailPenjemputan")" class="block relative pl-12 group">
|
||||
<div class="absolute left-4 top-1 w-4 h-4 bg-white border-4 border-gray-400 rounded-full z-10"></div>
|
||||
<div class="bg-white p-4 rounded-3xl border border-gray-100 shadow-sm group-active:bg-gray-50 transition-colors">
|
||||
<div class="flex justify-between items-start mb-2">
|
||||
<span class="text-[9px] font-black text-gray-400 uppercase tracking-widest">Proses</span>
|
||||
<i class="w-4 h-4 text-gray-300" data-lucide="loader"></i>
|
||||
</div>
|
||||
<h4 class="font-bold text-gray-800 text-sm leading-tight">Jakarta Garden City</h4>
|
||||
<div class="flex items-center gap-1 mt-2 text-gray-500">
|
||||
<i class="w-3 h-3" data-lucide="map"></i>
|
||||
<p class="text-[10px] truncate italic">Jakarta Garden City, Jakarta</p>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<span class="text-[9px] font-bold text-gray-600 bg-gray-100 px-2 py-1 rounded-lg">1 TPS</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a href="@Url.Action("DetailSelesai", "DetailPenjemputan")" class="block relative pl-12 group">
|
||||
<div class="absolute left-4 top-1 w-4 h-4 bg-green-500 rounded-full z-10 ring-4 ring-green-100"></div>
|
||||
<div class="bg-green-50/50 p-4 rounded-3xl border border-green-100 shadow-sm group-active:bg-green-100 transition-colors">
|
||||
|
|
|
|||
|
|
@ -25,14 +25,12 @@
|
|||
--color-orange-700: oklch(55.3% 0.195 38.402);
|
||||
--color-orange-800: oklch(47% 0.157 37.304);
|
||||
--color-amber-50: oklch(98.7% 0.022 95.277);
|
||||
--color-amber-100: oklch(96.2% 0.059 95.617);
|
||||
--color-amber-200: oklch(92.4% 0.12 95.746);
|
||||
--color-amber-300: oklch(87.9% 0.169 91.605);
|
||||
--color-amber-400: oklch(82.8% 0.189 84.429);
|
||||
--color-amber-500: oklch(76.9% 0.188 70.08);
|
||||
--color-amber-600: oklch(66.6% 0.179 58.318);
|
||||
--color-amber-700: oklch(55.5% 0.163 48.998);
|
||||
--color-amber-800: oklch(47.3% 0.137 46.201);
|
||||
--color-yellow-50: oklch(98.7% 0.026 102.212);
|
||||
--color-yellow-100: oklch(97.3% 0.071 103.193);
|
||||
--color-yellow-200: oklch(94.5% 0.129 101.54);
|
||||
|
|
@ -434,9 +432,6 @@
|
|||
.right-full {
|
||||
right: 100%;
|
||||
}
|
||||
.-bottom-0 {
|
||||
bottom: calc(var(--spacing) * -0);
|
||||
}
|
||||
.-bottom-0\.5 {
|
||||
bottom: calc(var(--spacing) * -0.5);
|
||||
}
|
||||
|
|
@ -476,9 +471,6 @@
|
|||
.left-0 {
|
||||
left: calc(var(--spacing) * 0);
|
||||
}
|
||||
.left-1 {
|
||||
left: calc(var(--spacing) * 1);
|
||||
}
|
||||
.left-1\/2 {
|
||||
left: calc(1/2 * 100%);
|
||||
}
|
||||
|
|
@ -800,9 +792,6 @@
|
|||
.-mr-16 {
|
||||
margin-right: calc(var(--spacing) * -16);
|
||||
}
|
||||
.mr-1 {
|
||||
margin-right: calc(var(--spacing) * 1);
|
||||
}
|
||||
.mr-1\.5 {
|
||||
margin-right: calc(var(--spacing) * 1.5);
|
||||
}
|
||||
|
|
@ -896,9 +885,6 @@
|
|||
.aspect-square {
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
.h-0 {
|
||||
height: calc(var(--spacing) * 0);
|
||||
}
|
||||
.h-0\.5 {
|
||||
height: calc(var(--spacing) * 0.5);
|
||||
}
|
||||
|
|
@ -986,9 +972,6 @@
|
|||
.h-\[250px\] {
|
||||
height: 250px;
|
||||
}
|
||||
.h-\[340px\] {
|
||||
height: 340px;
|
||||
}
|
||||
.h-\[350px\] {
|
||||
height: 350px;
|
||||
}
|
||||
|
|
@ -1166,10 +1149,6 @@
|
|||
.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);
|
||||
|
|
@ -1182,10 +1161,6 @@
|
|||
--tw-translate-x: calc(var(--spacing) * 16);
|
||||
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);
|
||||
|
|
@ -1198,12 +1173,6 @@
|
|||
--tw-translate-y: calc(var(--spacing) * 12);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.scale-105 {
|
||||
--tw-scale-x: 105%;
|
||||
--tw-scale-y: 105%;
|
||||
--tw-scale-z: 105%;
|
||||
scale: var(--tw-scale-x) var(--tw-scale-y);
|
||||
}
|
||||
.scale-110 {
|
||||
--tw-scale-x: 110%;
|
||||
--tw-scale-y: 110%;
|
||||
|
|
@ -1318,13 +1287,6 @@
|
|||
.gap-6 {
|
||||
gap: calc(var(--spacing) * 6);
|
||||
}
|
||||
.space-y-0 {
|
||||
:where(& > :not(:last-child)) {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-block-start: calc(calc(var(--spacing) * 0) * var(--tw-space-y-reverse));
|
||||
margin-block-end: calc(calc(var(--spacing) * 0) * calc(1 - var(--tw-space-y-reverse)));
|
||||
}
|
||||
}
|
||||
.space-y-0\.5 {
|
||||
:where(& > :not(:last-child)) {
|
||||
--tw-space-y-reverse: 0;
|
||||
|
|
@ -1774,9 +1736,6 @@
|
|||
.bg-blue-800 {
|
||||
background-color: var(--color-blue-800);
|
||||
}
|
||||
.bg-cyan-400 {
|
||||
background-color: var(--color-cyan-400);
|
||||
}
|
||||
.bg-cyan-400\/10 {
|
||||
background-color: color-mix(in srgb, oklch(78.9% 0.154 211.53) 10%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
|
|
@ -1786,9 +1745,6 @@
|
|||
.bg-emerald-400 {
|
||||
background-color: var(--color-emerald-400);
|
||||
}
|
||||
.bg-emerald-600 {
|
||||
background-color: var(--color-emerald-600);
|
||||
}
|
||||
.bg-gray-50 {
|
||||
background-color: var(--color-gray-50);
|
||||
}
|
||||
|
|
@ -1846,9 +1802,6 @@
|
|||
.bg-indigo-300 {
|
||||
background-color: var(--color-indigo-300);
|
||||
}
|
||||
.bg-lime-500 {
|
||||
background-color: var(--color-lime-500);
|
||||
}
|
||||
.bg-lime-500\/15 {
|
||||
background-color: color-mix(in srgb, oklch(76.8% 0.233 130.85) 15%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
|
|
@ -1870,9 +1823,6 @@
|
|||
.bg-orange-500 {
|
||||
background-color: var(--color-orange-500);
|
||||
}
|
||||
.bg-orange-700 {
|
||||
background-color: var(--color-orange-700);
|
||||
}
|
||||
.bg-orange-700\/30 {
|
||||
background-color: color-mix(in srgb, oklch(55.3% 0.195 38.402) 30%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
|
|
@ -1903,12 +1853,6 @@
|
|||
.bg-slate-100 {
|
||||
background-color: var(--color-slate-100);
|
||||
}
|
||||
.bg-slate-100\/80 {
|
||||
background-color: color-mix(in srgb, oklch(96.8% 0.007 247.896) 80%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-slate-100) 80%, transparent);
|
||||
}
|
||||
}
|
||||
.bg-slate-200 {
|
||||
background-color: var(--color-slate-200);
|
||||
}
|
||||
|
|
@ -1921,9 +1865,6 @@
|
|||
.bg-slate-900 {
|
||||
background-color: var(--color-slate-900);
|
||||
}
|
||||
.bg-slate-950 {
|
||||
background-color: var(--color-slate-950);
|
||||
}
|
||||
.bg-slate-950\/60 {
|
||||
background-color: color-mix(in srgb, oklch(12.9% 0.042 264.695) 60%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
|
|
@ -1960,12 +1901,6 @@
|
|||
background-color: color-mix(in oklab, var(--color-white) 70%, transparent);
|
||||
}
|
||||
}
|
||||
.bg-white\/80 {
|
||||
background-color: color-mix(in srgb, #fff 80%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-white) 80%, transparent);
|
||||
}
|
||||
}
|
||||
.bg-white\/95 {
|
||||
background-color: color-mix(in srgb, #fff 95%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
|
|
@ -1981,12 +1916,6 @@
|
|||
.bg-yellow-400 {
|
||||
background-color: var(--color-yellow-400);
|
||||
}
|
||||
.bg-yellow-400\/20 {
|
||||
background-color: color-mix(in srgb, oklch(85.2% 0.199 91.936) 20%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-yellow-400) 20%, transparent);
|
||||
}
|
||||
}
|
||||
.bg-yellow-500 {
|
||||
background-color: var(--color-yellow-500);
|
||||
}
|
||||
|
|
@ -2078,13 +2007,6 @@
|
|||
--tw-gradient-from: var(--color-white);
|
||||
--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-white\/85 {
|
||||
--tw-gradient-from: color-mix(in srgb, #fff 85%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
--tw-gradient-from: color-mix(in oklab, var(--color-white) 85%, transparent);
|
||||
}
|
||||
--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-yellow-50 {
|
||||
--tw-gradient-from: var(--color-yellow-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));
|
||||
|
|
@ -2136,14 +2058,6 @@
|
|||
--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);
|
||||
}
|
||||
.via-white\/75 {
|
||||
--tw-gradient-via: color-mix(in srgb, #fff 75%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
--tw-gradient-via: color-mix(in oklab, var(--color-white) 75%, transparent);
|
||||
}
|
||||
--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-amber-500 {
|
||||
--tw-gradient-to: var(--color-amber-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));
|
||||
|
|
@ -2152,17 +2066,6 @@
|
|||
--tw-gradient-to: var(--color-amber-600);
|
||||
--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-blue-50 {
|
||||
--tw-gradient-to: var(--color-blue-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));
|
||||
}
|
||||
.to-blue-50\/70 {
|
||||
--tw-gradient-to: color-mix(in srgb, oklch(97% 0.014 254.604) 70%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
--tw-gradient-to: color-mix(in oklab, var(--color-blue-50) 70%, transparent);
|
||||
}
|
||||
--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-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));
|
||||
|
|
@ -2813,9 +2716,6 @@
|
|||
.text-yellow-200 {
|
||||
color: var(--color-yellow-200);
|
||||
}
|
||||
.text-yellow-300 {
|
||||
color: var(--color-yellow-300);
|
||||
}
|
||||
.text-yellow-500 {
|
||||
color: var(--color-yellow-500);
|
||||
}
|
||||
|
|
@ -2936,9 +2836,6 @@
|
|||
--tw-shadow-color: color-mix(in oklab, var(--color-gray-200) var(--tw-shadow-alpha), transparent);
|
||||
}
|
||||
}
|
||||
.ring-black {
|
||||
--tw-ring-color: var(--color-black);
|
||||
}
|
||||
.ring-black\/5 {
|
||||
--tw-ring-color: color-mix(in srgb, #000 5%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
|
|
@ -3268,14 +3165,6 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.hover\:-translate-y-1 {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
--tw-translate-y: calc(var(--spacing) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
}
|
||||
}
|
||||
.hover\:scale-105 {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
|
|
@ -3359,13 +3248,6 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.hover\:bg-emerald-700 {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
background-color: var(--color-emerald-700);
|
||||
}
|
||||
}
|
||||
}
|
||||
.hover\:bg-gray-50 {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"selesai": {
|
||||
"namaPerusahaan": "Jakarta Garden City",
|
||||
"alamat": "Jalan TB. Simatupang Kav. 7B Cilandak, Jakarta 12430 ",
|
||||
"tanggalSelesai": "2026-03-10T10:35:00",
|
||||
"status": "Selesai",
|
||||
"nomorSpj": "SPJ/07-2025/PKM/000477",
|
||||
"platNomor": "B 9041 UPT",
|
||||
"nomorPintu": "JGC 001",
|
||||
"petugas": {
|
||||
"driver": "Andri Saputra",
|
||||
"checker": "Nabila Putri"
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue