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:
2026-05-14 19:16:17 -04:00
parent cefdf3e35c
commit 3eda91f170
233 changed files with 0 additions and 72627 deletions
@@ -1,196 +0,0 @@
@using PowderCoating.Application.DTOs.Common
@using PowderCoating.Application.DTOs.Invoice
@using PowderCoating.Core.Enums
@using PowderCoating.Web.Controllers
@model PagedResult<InvoiceListDto>
@{
ViewData["Title"] = "Invoices";
ViewData["PageIcon"] = "bi-receipt";
ViewData["PageHelpTitle"] = "Invoices";
ViewData["PageHelpContent"] = "Invoices are created from completed jobs and sent to the customer for payment. Lifecycle: Draft (editable) → Sent (locked, awaiting payment) → Partially Paid / Paid. Overdue = past due date with a balance still owed. Outstanding shows the total A/R balance across all unpaid invoices currently on screen. Use Void to cancel without deleting history.";
var searchTerm = ViewBag.SearchTerm as string;
var statusFilter = ViewBag.StatusFilter as InvoiceStatus?;
var outstandingOnly = (bool)(ViewBag.OutstandingOnly ?? false);
var thisMonthOnly = (bool)(ViewBag.ThisMonthOnly ?? false);
}
@{
var _outstanding = Model.Items.Where(i => i.Status != InvoiceStatus.Paid && i.Status != InvoiceStatus.Voided && i.Status != InvoiceStatus.WrittenOff).Sum(i => i.BalanceDue);
var _collected = Model.Items.Sum(i => i.AmountPaid);
var _overdue = Model.Items.Count(i => i.IsOverdue);
}
<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: "OUTSTANDING", Value: _outstanding.ToString("C0"), Delta: (string?)null, DeltaDir: (string?)null))
</div>
<div class="pcl-metric-strip-cell">
@await Html.PartialAsync("_Metric", (Label: "OVERDUE", Value: _overdue.ToString(), Delta: (string?)null, DeltaDir: (string?)null))
</div>
<div class="pcl-metric-strip-cell">
@await Html.PartialAsync("_Metric", (Label: "COLLECTED", Value: _collected.ToString("C0"), Delta: (string?)null, DeltaDir: (string?)null))
</div>
</div>
@if (TempData["Success"] != null)
{
<div class="alert alert-success alert-dismissible fade show" role="alert">
<i class="bi bi-check-circle me-2"></i>@TempData["Success"]
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
}
@if (TempData["Error"] != null)
{
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<i class="bi bi-exclamation-triangle me-2"></i>@TempData["Error"]
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
}
<div class="card border-0 shadow-sm">
<div class="card-header 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">
<form asp-action="Index" method="get" class="d-flex flex-nowrap gap-2 align-items-center">
<input type="hidden" name="sortColumn" value="@ViewBag.SortColumn" />
<input type="hidden" name="sortDirection" value="@ViewBag.SortDirection" />
<input type="hidden" name="pageSize" value="@Model.PageSize" />
@if (outstandingOnly) { <input type="hidden" name="outstandingOnly" value="true" /> }
@if (thisMonthOnly) { <input type="hidden" name="thisMonthOnly" value="true" /> }
<div class="input-group" style="max-width:280px; min-width:180px;">
<span class="input-group-text 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 invoices..." value="@searchTerm">
</div>
<select class="form-select" name="statusFilter" style="width:auto;">
<option value="">All Statuses</option>
@foreach (InvoiceStatus s in Enum.GetValues(typeof(InvoiceStatus)))
{
<option value="@((int)s)" selected="@(statusFilter == s)">@InvoicesController.GetStatusDisplay(s)</option>
}
</select>
<button type="submit" class="btn btn-primary"><i class="bi bi-search"></i></button>
@if (!string.IsNullOrEmpty(searchTerm) || statusFilter.HasValue || outstandingOnly || thisMonthOnly)
{
<a asp-action="Index" class="btn btn-outline-secondary">Clear</a>
}
@if (outstandingOnly)
{
<span class="badge bg-info text-dark fs-6 fw-normal">
<i class="bi bi-funnel-fill me-1"></i>Outstanding A/R
</span>
}
@if (thisMonthOnly && statusFilter == InvoiceStatus.Paid)
{
<span class="badge bg-success fs-6 fw-normal">
<i class="bi bi-funnel-fill me-1"></i>Paid — @DateTime.Now.ToString("MMMM yyyy")
</span>
}
else if (thisMonthOnly)
{
<span class="badge bg-info text-dark fs-6 fw-normal">
<i class="bi bi-funnel-fill me-1"></i>@DateTime.Now.ToString("MMMM yyyy")
</span>
}
</form>
<a asp-action="Create" class="btn btn-primary text-nowrap">
<i class="bi bi-plus-circle me-2"></i>New Invoice
</a>
</div>
</div>
<div class="card-body p-0">
@if (Model != null && Model.Items.Any())
{
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr>
<th sortable="InvoiceNumber" current-sort="@ViewBag.SortColumn" current-direction="@ViewBag.SortDirection">Invoice #</th>
<th>Customer</th>
<th>Job #</th>
<th sortable="Status" current-sort="@ViewBag.SortColumn" current-direction="@ViewBag.SortDirection">Status</th>
<th sortable="InvoiceDate" current-sort="@ViewBag.SortColumn" current-direction="@ViewBag.SortDirection">Date</th>
<th sortable="DueDate" current-sort="@ViewBag.SortColumn" current-direction="@ViewBag.SortDirection">Due</th>
<th sortable="Total" current-sort="@ViewBag.SortColumn" current-direction="@ViewBag.SortDirection" class="text-end">Total</th>
<th sortable="BalanceDue" current-sort="@ViewBag.SortColumn" current-direction="@ViewBag.SortDirection" class="text-end">Balance Due</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach (var inv in Model.Items)
{
var rowClass = inv.IsOverdue ? "table-danger" : "";
<tr class="@rowClass" style="cursor:pointer;"
onclick="window.location='@Url.Action("Details", "Invoices", new { id = inv.Id })'">
<td><strong>@inv.InvoiceNumber</strong></td>
<td>@inv.CustomerName</td>
<td>
@if (inv.JobId.HasValue)
{
<a asp-controller="Jobs" asp-action="Details" asp-route-id="@inv.JobId"
class="text-decoration-none" onclick="event.stopPropagation()">
@inv.JobNumber
</a>
}
else
{
<span class="badge bg-success-subtle text-success">Merch</span>
}
</td>
<td>
@await Html.PartialAsync("_StatusChip", (Kind: StatusChipHelper.InvoiceStatus(inv.Status), Text: InvoicesController.GetStatusDisplay(inv.Status)))
</td>
<td>@inv.InvoiceDate.ToString("MM/dd/yyyy")</td>
<td class="@(inv.IsOverdue ? "fw-bold text-danger" : "")">
@(inv.DueDate.HasValue ? inv.DueDate.Value.ToString("MM/dd/yyyy") : "—")
</td>
<td class="text-end">@inv.Total.ToString("C")</td>
<td class="text-end @(inv.BalanceDue > 0 ? "fw-semibold" : "text-muted")">
@inv.BalanceDue.ToString("C")
</td>
<td onclick="event.stopPropagation()">
<div class="d-flex gap-1">
<a asp-action="Details" asp-route-id="@inv.Id"
class="btn btn-sm btn-outline-primary" title="View">
<i class="bi bi-eye"></i>
</a>
<a asp-action="DownloadPdf" asp-route-id="@inv.Id"
class="btn btn-sm btn-outline-secondary" title="Download PDF">
<i class="bi bi-file-pdf"></i>
</a>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
<div class="px-3">
@await Html.PartialAsync("_Pagination", Model)
</div>
}
else
{
<div class="text-center py-5">
<i class="bi bi-receipt" style="font-size:3rem; color:#94a3b8;"></i>
<p class="mt-3 text-muted">No invoices found.</p>
<a asp-action="Create" class="btn btn-primary mt-2">
<i class="bi bi-plus-circle me-2"></i>Create First Invoice
</a>
</div>
}
</div>
</div>
@section Scripts {
<script>
function changePageSize(size) {
const url = new URL(window.location.href);
url.searchParams.set('pageSize', size);
url.searchParams.set('pageNumber', '1');
window.location.href = url.toString();
}
</script>
}