diff --git a/src/PowderCoating.Web/Views/AiUsageReport/Index.cshtml b/src/PowderCoating.Web/Views/AiUsageReport/Index.cshtml index b9bcdd9..6419bda 100644 --- a/src/PowderCoating.Web/Views/AiUsageReport/Index.cshtml +++ b/src/PowderCoating.Web/Views/AiUsageReport/Index.cshtml @@ -109,6 +109,69 @@ Per-Company Breakdown @Model.Rows.Count companies total +
+
+ @foreach (var row in Model.Rows) + { +
+
+
+ +
+
+
@row.CompanyName @if (!row.IsActive) { Inactive }
+ @row.Plan +
+
+
+
+ Today + + @if (row.Today > 0) { @row.Today.ToString("N0") } else { } + +
+
+ 30 Days + + @if (row.Last30Days > 0) { @row.Last30Days.ToString("N0") } else { } + +
+
+ All Time + + @if (row.AllTime > 0) { @row.AllTime.ToString("N0") } else { } + +
+ @if (row.TopFeature != null) + { +
+ Top Feature + + @row.FeatureDisplayName(row.TopFeature) + +
+ } +
+ Tier + @row.UsageTier +
+
+ +
+ } + @if (!Model.Rows.Any()) + { +
+ + No AI usage logged yet. +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/BannedIps/Index.cshtml b/src/PowderCoating.Web/Views/BannedIps/Index.cshtml index 5f0a2d5..c354d99 100644 --- a/src/PowderCoating.Web/Views/BannedIps/Index.cshtml +++ b/src/PowderCoating.Web/Views/BannedIps/Index.cshtml @@ -60,6 +60,59 @@
@if (active.Any()) { +
+
+ @foreach (var ban in active) + { +
+
+
+ +
+
+
@ban.IpAddress
+ @(ban.Reason ?? "No reason given") +
+
+
+
+ Banned + @ban.BannedAt.ToString("MMM d, yyyy HH:mm") +
+
+ Expires + + @if (ban.ExpiresAt.HasValue) + { + @ban.ExpiresAt.Value.ToString("MMM d, yyyy") + } + else + { + Permanent + } + +
+
+ +
+ } +
+
@@ -130,6 +183,55 @@
Lifted / Expired Bans
+
+
+ @foreach (var ban in inactive) + { +
+
+
+ +
+
+
@ban.IpAddress
+ + @if (!ban.IsActive) + { + Lifted + } + else + { + Expired + } + +
+
+
+ @if (!string.IsNullOrEmpty(ban.Reason)) + { +
+ Reason + @ban.Reason +
+ } +
+ Banned + @ban.BannedAt.ToString("MMM d, yyyy") +
+
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/GiftCertificates/BulkResult.cshtml b/src/PowderCoating.Web/Views/GiftCertificates/BulkResult.cshtml index 0bbc6a7..b3a6087 100644 --- a/src/PowderCoating.Web/Views/GiftCertificates/BulkResult.cshtml +++ b/src/PowderCoating.Web/Views/GiftCertificates/BulkResult.cshtml @@ -26,6 +26,48 @@
+
+
+ @foreach (var cert in Model) + { +
+
+
+ +
+
+
@cert.CertificateCode
+ @cert.OriginalAmount.ToString("C") +
+
+
+
+ Issued + @cert.IssueDate.ToLocalTime().ToString("MMM d, yyyy") +
+
+ Expiry + + @if (cert.ExpiryDate.HasValue) { @cert.ExpiryDate.Value.ToLocalTime().ToString("MMM d, yyyy") } else { } + +
+
+ Status + Active +
+
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/Inventory/SamplePanels.cshtml b/src/PowderCoating.Web/Views/Inventory/SamplePanels.cshtml index f27e83b..1fa5e0f 100644 --- a/src/PowderCoating.Web/Views/Inventory/SamplePanels.cshtml +++ b/src/PowderCoating.Web/Views/Inventory/SamplePanels.cshtml @@ -126,6 +126,77 @@ } else { +
+
+ @{ lastMfr = null; } + @foreach (var item in needOrder) + { + if (string.IsNullOrWhiteSpace(selectedMfr) && item.Manufacturer != lastMfr) + { + lastMfr = item.Manufacturer; +
+ @(string.IsNullOrWhiteSpace(item.Manufacturer) ? "No Manufacturer" : item.Manufacturer) +
+ } +
+
+ @if (!string.IsNullOrWhiteSpace(item.ColorCode)) + { +
+ } + else + { +
+ +
+ } +
+
@(item.ColorName ?? item.Name)
+ @(item.Manufacturer ?? "No Manufacturer") +
+
+
+ @if (!string.IsNullOrWhiteSpace(item.ManufacturerPartNumber)) + { +
+ Part # + @item.ManufacturerPartNumber +
+ } + @if (!string.IsNullOrWhiteSpace(item.Finish)) + { +
+ Finish + @item.Finish +
+ } +
+ In Stock + + @if (item.QuantityOnHand > 0) + { + @item.QuantityOnHand.ToString("N2") @item.UnitOfMeasure + } + else + { + None + } + +
+
+ +
+ } +
+
@@ -220,6 +291,68 @@ } else { +
+
+ @{ lastMfr = null; } + @foreach (var item in onHand) + { + if (string.IsNullOrWhiteSpace(selectedMfr) && item.Manufacturer != lastMfr) + { + lastMfr = item.Manufacturer; +
+ @(string.IsNullOrWhiteSpace(item.Manufacturer) ? "No Manufacturer" : item.Manufacturer) +
+ } +
+
+ @if (!string.IsNullOrWhiteSpace(item.ColorCode)) + { +
+ } + else + { +
+ +
+ } +
+
@(item.ColorName ?? item.Name)
+ @(item.Manufacturer ?? "No Manufacturer") +
+
+
+ @if (!string.IsNullOrWhiteSpace(item.ManufacturerPartNumber)) + { +
+ Part # + @item.ManufacturerPartNumber +
+ } + @if (!string.IsNullOrWhiteSpace(item.Finish)) + { +
+ Finish + @item.Finish +
+ } +
+ Status + On Wall +
+
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/JobsPriority/Index.cshtml b/src/PowderCoating.Web/Views/JobsPriority/Index.cshtml index 8e2e808..533a643 100644 --- a/src/PowderCoating.Web/Views/JobsPriority/Index.cshtml +++ b/src/PowderCoating.Web/Views/JobsPriority/Index.cshtml @@ -71,6 +71,59 @@
+
+
+ @foreach (var job in overdueJobs) + { +
+
+
+ +
+
+
@job.JobNumber
+ @job.CustomerName +
+
+
+
+ Status + @job.StatusDisplayName +
+
+ Priority + @job.PriorityDisplayName +
+ @if (job.ScheduledDate.HasValue) + { +
+ Scheduled + @job.ScheduledDate.Value.ToString("MMM d, yyyy") +
+ } + @if (job.DueDate.HasValue) + { +
+ Due + @job.DueDate.Value.ToString("MMM d, yyyy") +
+ } +
+ +
+ } +
+
@@ -191,6 +244,74 @@
+
+
+ @foreach (var job in Model) + { +
+
+
+ +
+
+
@job.JobNumber
+ @job.CustomerName +
+
+
+
+ Status + @job.StatusDisplayName +
+
+ Priority + @job.PriorityDisplayName +
+ @if (!string.IsNullOrEmpty(job.AssignedWorkerName)) + { +
+ Worker + @job.AssignedWorkerName +
+ } + @if (job.ScheduledDate.HasValue) + { +
+ Scheduled + @job.ScheduledDate.Value.ToString("MMM d, yyyy") +
+ } + @if (job.DueDate.HasValue) + { + var mJobOverdue = job.DueDate.Value.Date < DateTime.Today; +
+ Due + @job.DueDate.Value.ToString("MMM d, yyyy") +
+ } +
+ +
+ } + @if (!Model.Any()) + { +
+ + No jobs scheduled for @scheduledDate.ToString("MMMM dd, yyyy"). +
+ } +
+
@@ -352,6 +473,65 @@ } else { +
+
+ @foreach (var item in maintenanceItems) + { + var mPriorityBg = item.Priority switch + { + MaintenancePriority.Critical => "danger", + MaintenancePriority.High => "warning", + MaintenancePriority.Normal => "info", + _ => "secondary" + }; + var mStatusBgM = item.Status == MaintenanceStatus.InProgress ? "success" : "primary"; + var mStatusLbl = item.Status == MaintenanceStatus.InProgress ? "In Progress" : "Scheduled"; +
+
+
+ +
+
+
@(item.Equipment?.EquipmentName ?? "Maintenance")
+ @item.MaintenanceType +
+
+
+
+ Priority + @item.Priority +
+
+ Status + @mStatusLbl +
+ @if (item.AssignedUser != null) + { +
+ Worker + @item.AssignedUser.FullName +
+ } + @if (!string.IsNullOrEmpty(item.Description)) + { +
+ Desc. + @item.Description +
+ } +
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/NotificationLogs/Index.cshtml b/src/PowderCoating.Web/Views/NotificationLogs/Index.cshtml index a396c19..3f99c5a 100644 --- a/src/PowderCoating.Web/Views/NotificationLogs/Index.cshtml +++ b/src/PowderCoating.Web/Views/NotificationLogs/Index.cshtml @@ -134,6 +134,67 @@ } else { +
+
+ @foreach (var item in Model.Items) + { +
+
+
+ +
+
+
@item.RecipientName
+ @item.Recipient +
+
+
+
+ Type + @item.NotificationTypeDisplay +
+
+ Sent + @item.SentAt.Tz(ViewBag.CompanyTimeZone as string).ToString("MM/dd HH:mm") +
+ @if (item.JobId.HasValue) + { +
+ Job + @item.JobNumber +
+ } + else if (item.QuoteId.HasValue) + { +
+ Quote + @item.QuoteNumber +
+ } +
+ Status + + @{ + var (mStatusBadge, mStatusIcon) = item.Status switch + { + PowderCoating.Core.Enums.NotificationStatus.Sent => ("bg-success", "bi-check-circle"), + PowderCoating.Core.Enums.NotificationStatus.Failed => ("bg-danger", "bi-x-circle"), + _ => ("bg-secondary", "bi-dash-circle") + }; + } + @item.StatusDisplay + +
+
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/OnboardingProgress/Index.cshtml b/src/PowderCoating.Web/Views/OnboardingProgress/Index.cshtml index 8c2ccd5..e2308cd 100644 --- a/src/PowderCoating.Web/Views/OnboardingProgress/Index.cshtml +++ b/src/PowderCoating.Web/Views/OnboardingProgress/Index.cshtml @@ -44,6 +44,91 @@
+
+
+ @foreach (var row in Model.Rows) + { + var oPct = row.TotalSteps == 0 ? 0 : row.StepsCompleted * 100 / row.TotalSteps; +
+
+
+ +
+
+
@row.CompanyName
+ + @switch (row.Status) + { + case OnboardingStatus.Complete: + Complete + break; + case OnboardingStatus.InProgress: + In Progress + break; + case OnboardingStatus.Dismissed: + Dismissed + break; + default: + Not Started + break; + } + +
+
+
+
+ Wizard + + @if (row.WizardCompleted) + { + + Done + } + else + { + + Pending + } + +
+
+ Milestones + +
+
+
+
+ @row.StepsCompleted/@row.TotalSteps +
+
+
+ @{ + var oFirstActivity = row.FirstJobCreatedAt ?? row.FirstQuoteCreatedAt; + } + @if (oFirstActivity.HasValue) + { +
+ First Activity + @oFirstActivity.Value.ToString("MMM d, yyyy") +
+ } +
+ +
+ } + @if (!Model.Rows.Any()) + { +
+ + No companies found. +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/ReleaseNotes/Manage.cshtml b/src/PowderCoating.Web/Views/ReleaseNotes/Manage.cshtml index 776aafc..08f4cf6 100644 --- a/src/PowderCoating.Web/Views/ReleaseNotes/Manage.cshtml +++ b/src/PowderCoating.Web/Views/ReleaseNotes/Manage.cshtml @@ -65,6 +65,77 @@
+
+
+ @foreach (var note in Model) + { +
+
+
+ +
+
+
v@(note.Version) — @note.Title
+ + @note.Tag +   + @if (note.IsPublished) + { + Published + } + else + { + Draft + } + +
+
+
+
+ Released + @note.ReleasedAt.ToString("MM/dd/yyyy") +
+
+ Created By + @note.CreatedByUserName +
+ @if (note.Body.Length > 0) + { +
+ Preview + @(note.Body.Length > 60 ? note.Body[..60] + "…" : note.Body) +
+ } +
+ +
+ } + @if (!Model.Any()) + { +
+ + No release notes yet. Create the first one. +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/StorageMigration/Results.cshtml b/src/PowderCoating.Web/Views/StorageMigration/Results.cshtml index e69b28c..35e9267 100644 --- a/src/PowderCoating.Web/Views/StorageMigration/Results.cshtml +++ b/src/PowderCoating.Web/Views/StorageMigration/Results.cshtml @@ -84,6 +84,46 @@ } +
+
+ @foreach (var file in Model.Files.OrderBy(f => f.Status).ThenBy(f => f.RelativePath)) + { + var fStatusBadge = file.Status switch + { + MigrationFileStatus.Migrated => "bg-success", + MigrationFileStatus.Skipped => "bg-secondary", + _ => "bg-danger" + }; + var fStatusLabel = file.Status switch + { + MigrationFileStatus.Migrated => "Migrated", + MigrationFileStatus.Skipped => "Already in Azure", + _ => "Failed" + }; +
+
+
+ +
+
+
@file.RelativePath
+ @file.Container +
+
+
+
+ Size + @FormatBytes(file.FileSize) +
+
+ Status + @fStatusLabel +
+
+
+ } +
+
diff --git a/src/PowderCoating.Web/wwwroot/css/mobile-cards.css b/src/PowderCoating.Web/wwwroot/css/mobile-cards.css index 5891463..232e19b 100644 --- a/src/PowderCoating.Web/wwwroot/css/mobile-cards.css +++ b/src/PowderCoating.Web/wwwroot/css/mobile-cards.css @@ -9,8 +9,9 @@ } @media (max-width: 991px) { - /* Hide desktop table view on mobile */ - .table-responsive { + /* Hide desktop table only when a mobile card view sibling is present */ + .mobile-card-view ~ .table-responsive, + .table-responsive:has(~ .mobile-card-view) { display: none !important; }