Initial commit
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
@{
|
||||
ViewData["Title"] = "Update Job Status";
|
||||
Layout = null;
|
||||
var job = ViewBag.Job as PowderCoating.Core.Entities.Job;
|
||||
var allStatuses = ViewBag.AllStatuses as List<PowderCoating.Core.Entities.JobStatusLookup>;
|
||||
var token = (Guid)ViewBag.Token;
|
||||
|
||||
// Determine next/previous status options
|
||||
var currentOrder = job!.JobStatus.DisplayOrder;
|
||||
var nextStatus = allStatuses!
|
||||
.Where(s => s.DisplayOrder > currentOrder && s.StatusCode != "ONHOLD" && s.StatusCode != "CANCELLED")
|
||||
.OrderBy(s => s.DisplayOrder)
|
||||
.FirstOrDefault();
|
||||
var onHoldStatus = allStatuses!.FirstOrDefault(s => s.StatusCode == "ONHOLD");
|
||||
var isOnHold = job.JobStatus.StatusCode == "ONHOLD";
|
||||
var isTerminal = job.JobStatus.IsTerminalStatus;
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<title>@ViewData["Title"]</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
background: #f0f2f5;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20px 16px;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.10);
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
background: #1a56db;
|
||||
color: white;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.card-header .job-number {
|
||||
font-size: 28px;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
.card-header .customer-name {
|
||||
font-size: 14px;
|
||||
opacity: 0.85;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: 24px 20px;
|
||||
}
|
||||
|
||||
.status-section {
|
||||
text-align: center;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.status-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
color: #6b7280;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.current-status-badge {
|
||||
display: inline-block;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
padding: 10px 24px;
|
||||
border-radius: 50px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.action-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.btn-advance {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 18px 20px;
|
||||
background: #059669;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.btn-advance:active { opacity: 0.85; transform: scale(0.98); }
|
||||
|
||||
.btn-hold {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 14px 20px;
|
||||
background: white;
|
||||
color: #d97706;
|
||||
border: 2px solid #d97706;
|
||||
border-radius: 12px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-hold:active { background: #fef3c7; }
|
||||
|
||||
.btn-resume {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 18px 20px;
|
||||
background: #2563eb;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-resume:active { opacity: 0.85; }
|
||||
|
||||
.terminal-msg {
|
||||
text-align: center;
|
||||
padding: 16px;
|
||||
color: #6b7280;
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.success-banner {
|
||||
background: #d1fae5;
|
||||
border: 2px solid #059669;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
color: #065f46;
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
height: 1px;
|
||||
background: #e5e7eb;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.meta-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
/* Bootstrap color helpers inline for the badge */
|
||||
.bg-primary { background-color: #0d6efd !important; }
|
||||
.bg-secondary { background-color: #6c757d !important; }
|
||||
.bg-success { background-color: #198754 !important; }
|
||||
.bg-danger { background-color: #dc3545 !important; }
|
||||
.bg-warning { background-color: #ffc107 !important; color: #212529 !important; }
|
||||
.bg-info { background-color: #0dcaf0 !important; color: #212529 !important; }
|
||||
.bg-dark { background-color: #212529 !important; }
|
||||
.bg-purple { background-color: #6f42c1 !important; }
|
||||
.bg-orange { background-color: #fd7e14 !important; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="job-number">@job.JobNumber</div>
|
||||
<div class="customer-name">
|
||||
@if (!string.IsNullOrWhiteSpace(job.Customer?.CompanyName))
|
||||
{ @job.Customer.CompanyName }
|
||||
else
|
||||
{ @($"{job.Customer?.ContactFirstName} {job.Customer?.ContactLastName}".Trim()) }
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
@if (TempData["StatusUpdated"] != null)
|
||||
{
|
||||
<div class="success-banner">
|
||||
✓ Status updated successfully!
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="status-section">
|
||||
<div class="status-label">Current Status</div>
|
||||
<span class="current-status-badge bg-@job.JobStatus.ColorClass">
|
||||
@job.JobStatus.DisplayName
|
||||
</span>
|
||||
@if (job.DueDate.HasValue)
|
||||
{
|
||||
<div style="margin-top: 10px; font-size: 13px; color: @(job.DueDate < DateTime.Today ? "#dc2626" : "#6b7280");">
|
||||
Due: @job.DueDate.Value.ToString("MMM d, yyyy")
|
||||
@if (job.DueDate < DateTime.Today && !isTerminal)
|
||||
{
|
||||
<strong style="color: #dc2626;"> — OVERDUE</strong>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="action-section">
|
||||
@if (isTerminal)
|
||||
{
|
||||
<div class="terminal-msg">
|
||||
This job is <strong>@job.JobStatus.DisplayName</strong> and requires no further updates.
|
||||
</div>
|
||||
}
|
||||
else if (isOnHold)
|
||||
{
|
||||
@* On hold — offer resume (next logical status after resume by advancing) *@
|
||||
@if (nextStatus != null)
|
||||
{
|
||||
<form method="post" asp-action="StatusBump" asp-route-token="@token">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="newStatusId" value="@nextStatus.Id" />
|
||||
<button type="submit" class="btn-resume">
|
||||
▶ Resume — Move to @nextStatus.DisplayName
|
||||
</button>
|
||||
</form>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@* Advance to next step *@
|
||||
@if (nextStatus != null)
|
||||
{
|
||||
<form method="post" asp-action="StatusBump" asp-route-token="@token">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="newStatusId" value="@nextStatus.Id" />
|
||||
<button type="submit" class="btn-advance">
|
||||
✓ Mark as @nextStatus.DisplayName
|
||||
</button>
|
||||
</form>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="terminal-msg">No further stages available.</div>
|
||||
}
|
||||
|
||||
@* On Hold option *@
|
||||
@if (onHoldStatus != null)
|
||||
{
|
||||
<form method="post" asp-action="StatusBump" asp-route-token="@token">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="newStatusId" value="@onHoldStatus.Id" />
|
||||
<button type="submit" class="btn-hold">
|
||||
⏸ Put on Hold
|
||||
</button>
|
||||
</form>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
<div class="meta-row">
|
||||
<span>Job created @job.CreatedAt.ToString("MMM d, yyyy")</span>
|
||||
<span>@job.JobPriority?.DisplayName Priority</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user