107 lines
4.2 KiB
Plaintext
107 lines
4.2 KiB
Plaintext
@model PowderCoating.Web.ViewModels.Reports.JobCycleTimeViewModel
|
|
@{ ViewData["Title"] = "Job Cycle Time"; }
|
|
|
|
<partial name="_ReportHeader" model="Model" />
|
|
|
|
<div class="row g-3 mb-3">
|
|
<div class="col-sm-4">
|
|
<div class="card text-bg-primary">
|
|
<div class="card-body py-2">
|
|
<div class="small">Overall Avg Cycle Time</div>
|
|
<div class="fs-5 fw-bold">@Model.OverallAvgCycleDays.ToString("N1") days</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm-4">
|
|
<div class="card border-secondary">
|
|
<div class="card-body py-2 text-center">
|
|
<div class="small text-muted">Stages Tracked</div>
|
|
<div class="fs-5 fw-bold">@Model.Items.Count</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm-4">
|
|
<div class="card border-secondary">
|
|
<div class="card-body py-2 text-center">
|
|
<div class="small text-muted">Slowest Stage</div>
|
|
@if (Model.Items.Any())
|
|
{
|
|
var slowest = Model.Items.OrderByDescending(i => i.AvgDays).First();
|
|
<div class="fs-6 fw-bold text-warning">@slowest.StatusName (@slowest.AvgDays.ToString("N1") d)</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-3">
|
|
<div class="col-lg-6">
|
|
<div class="card h-100">
|
|
<div class="card-header fw-semibold">Average Days per Stage</div>
|
|
<div class="card-body">
|
|
<canvas id="cycleChart" height="300"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-6">
|
|
<div class="card h-100">
|
|
<div class="card-header fw-semibold">Stage Detail</div>
|
|
<div class="card-body p-0">
|
|
<table class="table table-sm table-hover mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>Stage</th>
|
|
<th class="text-end">Avg Days</th>
|
|
<th class="text-end">Min</th>
|
|
<th class="text-end">Max</th>
|
|
<th class="text-end">Jobs</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var item in Model.Items)
|
|
{
|
|
<tr>
|
|
<td>@item.StatusName</td>
|
|
<td class="text-end fw-semibold">@item.AvgDays.ToString("N1")</td>
|
|
<td class="text-end text-success">@item.MinDays.ToString("N1")</td>
|
|
<td class="text-end text-danger">@item.MaxDays.ToString("N1")</td>
|
|
<td class="text-end text-muted">@item.JobCount</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@section Scripts {
|
|
<script src="~/lib/chartjs/chart.umd.min.js"></script>
|
|
<script>
|
|
(function () {
|
|
const labels = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.Items.Select(i => i.StatusName)));
|
|
const avgDays = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.Items.Select(i => i.AvgDays)));
|
|
const minDays = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.Items.Select(i => i.MinDays)));
|
|
const maxDays = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.Items.Select(i => i.MaxDays)));
|
|
|
|
new Chart(document.getElementById('cycleChart'), {
|
|
type: 'bar',
|
|
data: {
|
|
labels,
|
|
datasets: [
|
|
{ label: 'Avg Days', data: avgDays, backgroundColor: 'rgba(13,110,253,0.7)' },
|
|
{ label: 'Min Days', data: minDays, backgroundColor: 'rgba(25,135,84,0.5)' },
|
|
{ label: 'Max Days', data: maxDays, backgroundColor: 'rgba(220,53,69,0.4)' }
|
|
]
|
|
},
|
|
options: {
|
|
indexAxis: 'y',
|
|
responsive: true,
|
|
plugins: { legend: { position: 'top' } },
|
|
scales: { x: { beginAtZero: true, title: { display: true, text: 'Days' } } }
|
|
}
|
|
});
|
|
})();
|
|
</script>
|
|
}
|