Replace literal Unicode special chars with HTML entities across all 233 views
Sweeps em dashes, en dashes, multiplication signs, ellipses, and curly quotes to their HTML entity equivalents (— – × … ‘ ’) in all .cshtml files, skipping <script> blocks. Prevents encoding corruption from AI tools and Windows encoding mismatches that caused recurring symbol bugs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,292 +0,0 @@
|
||||
@model PagedResult<PowderCoating.Application.DTOs.Equipment.EquipmentListDto>
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Equipment";
|
||||
ViewData["PageIcon"] = "bi-tools";
|
||||
ViewData["PageHelpTitle"] = "Equipment";
|
||||
ViewData["PageHelpContent"] = "Track all shop equipment — ovens, spray booths, compressors, and other machinery. Status shows whether each piece is Operational, Needs Maintenance, Under Maintenance, or Out of Service. Next Maintenance date is calculated from the last completed maintenance plus the equipment's maintenance interval. Click any row to view full details and maintenance history.";
|
||||
}
|
||||
|
||||
<div class="pcl-metric-strip">
|
||||
<div class="pcl-metric-strip-cell">
|
||||
@await Html.PartialAsync("_Metric", (Label: "TOTAL", Value: Model.TotalCount.ToString(), Delta: (string?)null, DeltaDir: (string?)null))
|
||||
</div>
|
||||
<div class="pcl-metric-strip-cell">
|
||||
@await Html.PartialAsync("_Metric", (Label: "OPERATIONAL", Value: Model.Items.Count(e => e.Status == "Operational").ToString(), Delta: (string?)null, DeltaDir: (string?)null))
|
||||
</div>
|
||||
<div class="pcl-metric-strip-cell">
|
||||
@await Html.PartialAsync("_Metric", (Label: "NEEDS SERVICE", Value: Model.Items.Count(e => e.Status == "NeedsMaintenance").ToString(), Delta: (string?)null, DeltaDir: (string?)null))
|
||||
</div>
|
||||
<div class="pcl-metric-strip-cell">
|
||||
@await Html.PartialAsync("_Metric", (Label: "IN MAINTENANCE", Value: Model.Items.Count(e => e.Status == "UnderMaintenance").ToString(), Delta: (string?)null, DeltaDir: (string?)null))
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Equipment Table Card -->
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-header bg-white border-0 py-3">
|
||||
<div class="d-flex flex-column flex-lg-row justify-content-between align-items-start align-items-lg-center gap-3">
|
||||
<div class="d-flex flex-column flex-sm-row gap-2 w-100 w-lg-auto">
|
||||
<form method="get" class="d-flex flex-column flex-sm-row gap-2 flex-grow-1 flex-lg-grow-0">
|
||||
<input type="hidden" name="sortColumn" value="@ViewBag.SortColumn" />
|
||||
<input type="hidden" name="sortDirection" value="@ViewBag.SortDirection" />
|
||||
<input type="hidden" name="pageSize" value="@Model.PageSize" />
|
||||
<select name="statusFilter" class="form-select" style="max-width: 250px; min-width: 150px;" onchange="this.form.submit()">
|
||||
<option value="">All Statuses</option>
|
||||
<option value="@((int)PowderCoating.Core.Enums.EquipmentStatus.Operational)" selected="@(ViewBag.StatusFilter == PowderCoating.Core.Enums.EquipmentStatus.Operational)">Operational</option>
|
||||
<option value="@((int)PowderCoating.Core.Enums.EquipmentStatus.NeedsMaintenance)" selected="@(ViewBag.StatusFilter == PowderCoating.Core.Enums.EquipmentStatus.NeedsMaintenance)">Needs Maintenance</option>
|
||||
<option value="@((int)PowderCoating.Core.Enums.EquipmentStatus.UnderMaintenance)" selected="@(ViewBag.StatusFilter == PowderCoating.Core.Enums.EquipmentStatus.UnderMaintenance)">Under Maintenance</option>
|
||||
<option value="@((int)PowderCoating.Core.Enums.EquipmentStatus.OutOfService)" selected="@(ViewBag.StatusFilter == PowderCoating.Core.Enums.EquipmentStatus.OutOfService)">Out of Service</option>
|
||||
<option value="@((int)PowderCoating.Core.Enums.EquipmentStatus.Retired)" selected="@(ViewBag.StatusFilter == PowderCoating.Core.Enums.EquipmentStatus.Retired)">Retired</option>
|
||||
</select>
|
||||
<div class="input-group" style="max-width: 350px; min-width: 200px;">
|
||||
<span class="input-group-text bg-white border-end-0">
|
||||
<i class="bi bi-search text-muted"></i>
|
||||
</span>
|
||||
<input type="text" name="searchTerm" class="form-control border-start-0"
|
||||
placeholder="Search equipment..." value="@ViewBag.SearchTerm">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="bi bi-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<a asp-action="Create" class="btn btn-primary text-nowrap">
|
||||
<i class="bi bi-plus-circle me-2"></i>
|
||||
<span class="d-none d-sm-inline">Add Equipment</span>
|
||||
<span class="d-inline d-sm-none">Add</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
@if (!Model.Items.Any())
|
||||
{
|
||||
<div class="text-center py-5">
|
||||
<i class="bi bi-inbox" style="font-size: 4rem; color: #d1d5db;"></i>
|
||||
<h5 class="mt-3 text-muted">No equipment found</h5>
|
||||
<p class="text-muted mb-4">Get started by adding your first equipment</p>
|
||||
<a asp-action="Create" class="btn btn-primary">
|
||||
<i class="bi bi-plus-circle me-2"></i>Add Your First Equipment
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th sortable="Name" current-sort="@ViewBag.SortColumn" current-direction="@ViewBag.SortDirection" class="ps-4">Equipment</th>
|
||||
<th sortable="EquipmentCode" current-sort="@ViewBag.SortColumn" current-direction="@ViewBag.SortDirection">Code</th>
|
||||
<th>Type</th>
|
||||
<th sortable="Status" current-sort="@ViewBag.SortColumn" current-direction="@ViewBag.SortDirection">Status</th>
|
||||
<th>Location</th>
|
||||
<th sortable="NextMaintenanceDate" current-sort="@ViewBag.SortColumn" current-direction="@ViewBag.SortDirection">Next Maintenance</th>
|
||||
<th class="text-end pe-4">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="equipmentTable">
|
||||
@foreach (var equipment in Model.Items.Where(e => e.IsActive))
|
||||
{
|
||||
<tr class="equipment-row" data-equipment-id="@equipment.Id" style="cursor: pointer;">
|
||||
<td class="ps-4">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<div class="rounded-circle d-flex align-items-center justify-content-center"
|
||||
style="width: 40px; height: 40px; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; font-weight: 600;">
|
||||
@if (!string.IsNullOrEmpty(equipment.EquipmentType))
|
||||
{
|
||||
@equipment.EquipmentType.Substring(0, 1).ToUpper()
|
||||
}
|
||||
else
|
||||
{
|
||||
@equipment.EquipmentName.Substring(0, 1).ToUpper()
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
<div class="fw-semibold">@equipment.EquipmentName</div>
|
||||
@if (!string.IsNullOrEmpty(equipment.EquipmentNumber))
|
||||
{
|
||||
<small class="text-muted">@equipment.EquipmentNumber</small>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>@equipment.EquipmentType</td>
|
||||
<td>
|
||||
@await Html.PartialAsync("_StatusChip", (Kind: StatusChipHelper.EquipmentStatus(equipment.Status), Text: equipment.StatusDisplay))
|
||||
</td>
|
||||
<td>
|
||||
@if (!string.IsNullOrEmpty(equipment.Location))
|
||||
{
|
||||
<span><i class="bi bi-geo-alt me-1"></i>@equipment.Location</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-muted">—</span>
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@if (equipment.NextScheduledMaintenance.HasValue)
|
||||
{
|
||||
<span>@equipment.NextScheduledMaintenance.Value.ToString("MMM dd, yyyy")</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-muted">Not scheduled</span>
|
||||
}
|
||||
</td>
|
||||
<td class="text-end pe-4">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<a asp-action="Details" asp-route-id="@equipment.Id" class="btn btn-outline-primary" title="View Details">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
<a asp-action="Edit" asp-route-id="@equipment.Id" class="btn btn-outline-warning" title="Edit">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
<a asp-action="Delete" asp-route-id="@equipment.Id" class="btn btn-outline-danger" title="Delete">
|
||||
<i class="bi bi-trash"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Card View -->
|
||||
<div class="mobile-card-view">
|
||||
<div class="mobile-card-list">
|
||||
@foreach (var equipment in Model.Items.Where(e => e.IsActive))
|
||||
{
|
||||
<div class="mobile-data-card"
|
||||
data-id="@equipment.Id"
|
||||
onclick="window.location.href='@Url.Action("Details", new { id = equipment.Id })'">
|
||||
|
||||
<div class="mobile-card-header">
|
||||
<div class="mobile-card-icon" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
|
||||
<i class="bi bi-tools"></i>
|
||||
</div>
|
||||
<div class="mobile-card-title">
|
||||
<h6>@equipment.EquipmentName</h6>
|
||||
<small>@equipment.EquipmentType</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-card-body">
|
||||
@if (!string.IsNullOrEmpty(equipment.EquipmentNumber))
|
||||
{
|
||||
<div class="mobile-card-row">
|
||||
<span class="mobile-card-label">Code</span>
|
||||
<span class="mobile-card-value">@equipment.EquipmentNumber</span>
|
||||
</div>
|
||||
}
|
||||
<div class="mobile-card-row">
|
||||
<span class="mobile-card-label">Status</span>
|
||||
<span class="mobile-card-value">
|
||||
@switch (equipment.Status)
|
||||
{
|
||||
case "Operational":
|
||||
<span class="badge bg-success bg-opacity-10 text-success">
|
||||
<i class="bi bi-check-circle me-1"></i>@equipment.StatusDisplay
|
||||
</span>
|
||||
break;
|
||||
case "NeedsMaintenance":
|
||||
<span class="badge bg-warning bg-opacity-10 text-warning">
|
||||
<i class="bi bi-exclamation-triangle me-1"></i>@equipment.StatusDisplay
|
||||
</span>
|
||||
break;
|
||||
case "UnderMaintenance":
|
||||
<span class="badge bg-info bg-opacity-10 text-info">
|
||||
<i class="bi bi-wrench me-1"></i>@equipment.StatusDisplay
|
||||
</span>
|
||||
break;
|
||||
case "OutOfService":
|
||||
<span class="badge bg-danger bg-opacity-10 text-danger">
|
||||
<i class="bi bi-x-circle me-1"></i>@equipment.StatusDisplay
|
||||
</span>
|
||||
break;
|
||||
default:
|
||||
<span class="badge bg-secondary bg-opacity-10 text-secondary">
|
||||
@equipment.StatusDisplay
|
||||
</span>
|
||||
break;
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(equipment.Location))
|
||||
{
|
||||
<div class="mobile-card-row">
|
||||
<span class="mobile-card-label">Location</span>
|
||||
<span class="mobile-card-value"><i class="bi bi-geo-alt me-1"></i>@equipment.Location</span>
|
||||
</div>
|
||||
}
|
||||
@if (equipment.NextScheduledMaintenance.HasValue)
|
||||
{
|
||||
<div class="mobile-card-row">
|
||||
<span class="mobile-card-label">Next Maintenance</span>
|
||||
<span class="mobile-card-value">@equipment.NextScheduledMaintenance.Value.ToString("MMM dd, yyyy")</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="mobile-card-footer">
|
||||
<a href="@Url.Action("Details", new { id = equipment.Id })"
|
||||
class="btn btn-sm btn-outline-primary"
|
||||
onclick="event.stopPropagation();">
|
||||
<i class="bi bi-eye me-1"></i>View
|
||||
</a>
|
||||
<a href="@Url.Action("Edit", new { id = equipment.Id })"
|
||||
class="btn btn-sm btn-outline-secondary"
|
||||
onclick="event.stopPropagation();">
|
||||
<i class="bi bi-pencil me-1"></i>Edit
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@if (Model.TotalCount > 0)
|
||||
{
|
||||
@await Html.PartialAsync("_Pagination", Model)
|
||||
}
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<script>
|
||||
// Simple search functionality
|
||||
document.getElementById('searchInput')?.addEventListener('input', function(e) {
|
||||
const searchTerm = e.target.value.toLowerCase();
|
||||
const rows = document.querySelectorAll('#equipmentTable tr');
|
||||
|
||||
rows.forEach(row => {
|
||||
const text = row.textContent.toLowerCase();
|
||||
row.style.display = text.includes(searchTerm) ? '' : 'none';
|
||||
});
|
||||
});
|
||||
|
||||
// Make table rows clickable
|
||||
document.querySelectorAll('.equipment-row').forEach(row => {
|
||||
row.addEventListener('click', function(e) {
|
||||
// Don't navigate if clicking on action buttons or links
|
||||
if (e.target.closest('.btn-group') || e.target.closest('a') || e.target.closest('button')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const equipmentId = this.getAttribute('data-equipment-id');
|
||||
window.location.href = '@Url.Action("Details", "Equipment")/' + equipmentId;
|
||||
});
|
||||
|
||||
// Add hover effect
|
||||
row.addEventListener('mouseenter', function() {
|
||||
this.style.backgroundColor = '#f8f9fa';
|
||||
});
|
||||
|
||||
row.addEventListener('mouseleave', function() {
|
||||
this.style.backgroundColor = '';
|
||||
});
|
||||
});
|
||||
</script>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user