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,160 +0,0 @@
@{
ViewData["Title"] = "Notification History";
ViewData["PageIcon"] = "bi-bell";
var items = Model as IEnumerable<dynamic> ?? Enumerable.Empty<dynamic>();
var pageNumber = (int)(ViewBag.PageNumber ?? 1);
var pageSize = (int)(ViewBag.PageSize ?? 25);
var totalCount = (int)(ViewBag.TotalCount ?? 0);
var totalPages = (int)(ViewBag.TotalPages ?? 1);
}
@section Styles {
<style>
tr.notif-unread { background: rgba(99, 102, 241, 0.08) !important; }
tr.notif-unread:hover { background: rgba(99, 102, 241, 0.14) !important; }
</style>
}
<div class="mb-4"></div>
@if (!items.Any())
{
<div class="card border-0 shadow-sm">
<div class="card-body text-center py-5 text-muted">
<i class="bi bi-bell-slash fs-1 d-block mb-3 opacity-25"></i>
<p class="mb-0">No notifications yet.</p>
</div>
</div>
}
else
{
<div class="card border-0 shadow-sm">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr>
<th style="width:20px;"></th>
<th>Title</th>
<th>Message</th>
<th>Type</th>
<th>Received</th>
<th>Read</th>
</tr>
</thead>
<tbody>
@foreach (var n in items)
{
bool isRead = (bool)n.IsRead;
string title = (string)n.Title;
string message = (string)n.Message;
string? link = (string?)n.Link;
string notifType = (string)n.NotificationType;
DateTime createdAt = ((DateTime)n.CreatedAt).Tz(ViewBag.CompanyTimeZone as string);
DateTime? readAt = n.ReadAt == null ? (DateTime?)null : ((DateTime)n.ReadAt).Tz(ViewBag.CompanyTimeZone as string);
<tr class="@(!isRead ? "notif-unread" : "") notif-history-row" style="cursor:pointer;"
data-id="@n.Id"
data-title="@title"
data-message="@message"
data-link="@(link ?? "")"
data-type="@notifType"
data-is-read="@(isRead ? "1" : "0")"
data-created-at="@createdAt.ToString("MMM d, yyyy h:mm tt")">
<td>
@if (!isRead)
{
<span title="Unread" style="display:inline-block;width:10px;height:10px;background:#6366f1;border-radius:50%;"></span>
}
</td>
<td class="@(!isRead ? "fw-semibold" : "text-muted")">
@if (!string.IsNullOrEmpty(link))
{
<a href="@link" class="text-decoration-none">@title</a>
}
else
{
@title
}
</td>
<td class="text-muted small" style="max-width:320px;">@message</td>
<td><span class="badge bg-secondary bg-opacity-25 text-body small">@notifType</span></td>
<td class="text-nowrap small text-muted">@createdAt.ToString("MMM d, yyyy h:mm tt")</td>
<td class="text-nowrap small text-muted">
@if (readAt.HasValue)
{
@readAt.Value.ToString("MMM d, h:mm tt")
}
else
{
<span class="badge bg-primary bg-opacity-10 text-primary">Unread</span>
}
</td>
</tr>
}
</tbody>
</table>
</div>
@if (totalPages > 1)
{
<div class="card-footer d-flex justify-content-between align-items-center">
<small class="text-muted">
Showing @((pageNumber - 1) * pageSize + 1)@(Math.Min(pageNumber * pageSize, totalCount)) of @totalCount
</small>
<nav>
<ul class="pagination pagination-sm mb-0">
<li class="page-item @(pageNumber <= 1 ? "disabled" : "")">
<a class="page-link" href="?pageNumber=@(pageNumber - 1)&pageSize=@pageSize"></a>
</li>
@for (var p = Math.Max(1, pageNumber - 2); p <= Math.Min(totalPages, pageNumber + 2); p++)
{
<li class="page-item @(p == pageNumber ? "active" : "")">
<a class="page-link" href="?pageNumber=@p&pageSize=@pageSize">@p</a>
</li>
}
<li class="page-item @(pageNumber >= totalPages ? "disabled" : "")">
<a class="page-link" href="?pageNumber=@(pageNumber + 1)&pageSize=@pageSize"></a>
</li>
</ul>
</nav>
</div>
}
</div>
}
@section Scripts {
<script>
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.notif-history-row').forEach(row => {
row.addEventListener('click', () => {
const n = {
id: parseInt(row.dataset.id),
title: row.dataset.title,
message: row.dataset.message,
link: row.dataset.link || null,
notificationType: row.dataset.type,
isRead: row.dataset.isRead === '1',
createdAt: row.dataset.createdAt
};
// Open the shared detail modal
notifBell.openDetail(n, null);
// Update this row's visual state if it was unread
if (!n.isRead) {
row.classList.remove('notif-unread');
row.dataset.isRead = '1';
const dot = row.querySelector('[title="Unread"]');
if (dot) dot.remove();
const badge = row.querySelector('.badge.text-primary');
if (badge) badge.remove();
const titleCell = row.querySelector('td:nth-child(2)');
if (titleCell) {
titleCell.classList.remove('fw-semibold');
titleCell.classList.add('text-muted');
}
}
});
});
});
</script>
}