From f467862877c2bd4049b285fdfef881048107f415 Mon Sep 17 00:00:00 2001 From: Scott Pouliot Date: Thu, 14 May 2026 23:07:52 -0400 Subject: [PATCH] Add mobile card views to 12 high-priority list pages Pages were blank on phones because mobile-cards.css hides .table-responsive below 992px. Added .mobile-card-view sections to: GiftCertificates, PurchaseOrders, CreditMemos, VendorCredits, JournalEntries, Appointments, InAppNotifications, BankReconciliations, FixedAssets, RecurringTemplates, SmsAgreements, SmsConsentAudit. Co-Authored-By: Claude Sonnet 4.6 --- .../Views/Appointments/Index.cshtml | 54 +++++++++++ .../Views/BankReconciliations/Index.cshtml | 58 +++++++++++ .../Views/CreditMemos/Index.cshtml | 67 +++++++++++++ .../Views/FixedAssets/Index.cshtml | 57 +++++++++++ .../Views/GiftCertificates/Index.cshtml | 67 +++++++++++++ .../Views/InAppNotifications/Index.cshtml | 55 +++++++++++ .../Views/JournalEntries/Index.cshtml | 62 ++++++++++++ .../Views/PurchaseOrders/Index.cshtml | 50 ++++++++++ .../Views/RecurringTemplates/Index.cshtml | 90 ++++++++++++++++++ .../Views/SmsAgreements/Index.cshtml | 95 +++++++++++++++++++ .../Views/SmsConsentAudit/Index.cshtml | 58 +++++++++++ .../Views/VendorCredits/Index.cshtml | 58 +++++++++++ 12 files changed, 771 insertions(+) diff --git a/src/PowderCoating.Web/Views/Appointments/Index.cshtml b/src/PowderCoating.Web/Views/Appointments/Index.cshtml index b57848e..c32b942 100644 --- a/src/PowderCoating.Web/Views/Appointments/Index.cshtml +++ b/src/PowderCoating.Web/Views/Appointments/Index.cshtml @@ -176,6 +176,60 @@
@if (Model.Items.Any()) { +
+
+ @foreach (var appointment in Model.Items) + { +
+
+
+ +
+
+
@appointment.Title
+ @appointment.ScheduledStartTime.ToString("MMM dd, yyyy")
@(!appointment.IsAllDay ? $"{appointment.ScheduledStartTime:h:mm tt} – {appointment.ScheduledEndTime:h:mm tt}" : "All Day")
+
+
+
+
+ Status + + @appointment.StatusDisplayName + +
+
+ Type + + @appointment.TypeDisplayName + +
+ @if (!string.IsNullOrEmpty(appointment.CustomerName)) + { +
+ Customer + @appointment.CustomerName +
+ } + @if (!string.IsNullOrEmpty(appointment.AssignedWorkerName)) + { +
+ Worker + @appointment.AssignedWorkerName +
+ } +
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/BankReconciliations/Index.cshtml b/src/PowderCoating.Web/Views/BankReconciliations/Index.cshtml index b611e85..c191feb 100644 --- a/src/PowderCoating.Web/Views/BankReconciliations/Index.cshtml +++ b/src/PowderCoating.Web/Views/BankReconciliations/Index.cshtml @@ -21,6 +21,64 @@
+
+
+ @foreach (var br in Model) + { +
+
+
+ +
+
+
@br.Account?.Name
+ Statement: @br.StatementDate.ToString("MMM d, yyyy") +
+
+
+
+ Status + + @if (br.Status == BankReconciliationStatus.Completed) + { + Completed + } + else + { + In Progress + } + +
+
+ Ending Balance + @br.EndingBalance.ToString("C") +
+ @if (br.CompletedAt.HasValue) + { +
+ Completed By + @br.CompletedBy +
+ } +
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/CreditMemos/Index.cshtml b/src/PowderCoating.Web/Views/CreditMemos/Index.cshtml index f02007c..de0870c 100644 --- a/src/PowderCoating.Web/Views/CreditMemos/Index.cshtml +++ b/src/PowderCoating.Web/Views/CreditMemos/Index.cshtml @@ -101,6 +101,73 @@ else {
+
+
+ @foreach (var m in Model) + { + var expired2 = m.ExpiryDate.HasValue && m.ExpiryDate.Value < DateTime.UtcNow + && m.Status != CreditMemoStatus.FullyApplied + && m.Status != CreditMemoStatus.Voided; + var (cmBadge, cmLabel) = m.Status switch + { + CreditMemoStatus.Active => ("bg-success-subtle text-success", "Active"), + CreditMemoStatus.PartiallyApplied => ("bg-warning-subtle text-warning", "Partial"), + CreditMemoStatus.FullyApplied => ("bg-secondary-subtle text-secondary", "Applied"), + CreditMemoStatus.Voided => ("bg-danger-subtle text-danger", "Voided"), + _ => ("bg-secondary-subtle text-secondary", m.Status.ToString()) + }; + var cmCustomer = string.IsNullOrWhiteSpace(m.Customer?.CompanyName) + ? $"{m.Customer?.ContactFirstName} {m.Customer?.ContactLastName}".Trim() + : m.Customer!.CompanyName; +
+
+
+ +
+
+
@m.MemoNumber
+ @cmCustomer +
+
+
+
+ Status + @cmLabel +
+
+ Amount + @m.Amount.ToString("C") +
+
+ Remaining + + @m.RemainingBalance.ToString("C") + +
+
+ Issued + @m.IssueDate.ToLocalTime().ToString("MM/dd/yy") +
+ @if (m.ExpiryDate.HasValue) + { +
+ Expires + + @m.ExpiryDate.Value.ToLocalTime().ToString("MM/dd/yy") + @if (expired2) { (Expired) } + +
+ } +
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/FixedAssets/Index.cshtml b/src/PowderCoating.Web/Views/FixedAssets/Index.cshtml index 063a384..1001fa6 100644 --- a/src/PowderCoating.Web/Views/FixedAssets/Index.cshtml +++ b/src/PowderCoating.Web/Views/FixedAssets/Index.cshtml @@ -118,6 +118,63 @@ } else { +
+
+ @foreach (var a in Model) + { + var fd = a.AccumulatedDepreciation >= (a.PurchaseCost - a.SalvageValue); +
+
+
+ +
+
+
@a.Name
+ Purchased @a.PurchaseDate.ToLocalTime().ToString("MM/dd/yyyy") +
+
+
+
+ Status + + @if (a.IsDisposed) + { + Disposed + } + else if (fd) + { + Fully Depreciated + } + else + { + Active + } + +
+
+ Cost + @a.PurchaseCost.ToString("C") +
+
+ Book Value + + @a.BookValue.ToString("C") + +
+
+ Monthly Depr. + @a.MonthlyDepreciation.ToString("C") +
+
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/GiftCertificates/Index.cshtml b/src/PowderCoating.Web/Views/GiftCertificates/Index.cshtml index a68b771..ec79592 100644 --- a/src/PowderCoating.Web/Views/GiftCertificates/Index.cshtml +++ b/src/PowderCoating.Web/Views/GiftCertificates/Index.cshtml @@ -57,6 +57,73 @@ else {
+
+
+ @foreach (var cert in Model) + { + var (gcBadge, gcLabel) = cert.Status switch + { + GiftCertificateStatus.Active => ("bg-success", "Active"), + GiftCertificateStatus.PartiallyRedeemed => ("bg-info text-dark", "Partial"), + GiftCertificateStatus.FullyRedeemed => ("bg-secondary", "Used"), + GiftCertificateStatus.Expired => ("bg-warning text-dark", "Expired"), + GiftCertificateStatus.Voided => ("bg-danger", "Voided"), + _ => ("bg-secondary", cert.Status.ToString()) + }; +
+
+
+ +
+
+
@cert.CertificateCode
+ @(cert.RecipientName ?? cert.RecipientEmail ?? "No recipient") +
+
+
+
+ Status + @gcLabel +
+
+ Face Value + @cert.OriginalAmount.ToString("C") +
+
+ Remaining + + @cert.RemainingBalance.ToString("C") + +
+
+ Issued + @cert.IssueDate.Tz(ViewBag.CompanyTimeZone as string).ToString("MM/dd/yy") +
+ @if (cert.ExpiryDate.HasValue) + { +
+ Expires + + @cert.ExpiryDate.Value.ToString("MM/dd/yy") + +
+ } +
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/InAppNotifications/Index.cshtml b/src/PowderCoating.Web/Views/InAppNotifications/Index.cshtml index a4ed4ad..02bdc7a 100644 --- a/src/PowderCoating.Web/Views/InAppNotifications/Index.cshtml +++ b/src/PowderCoating.Web/Views/InAppNotifications/Index.cshtml @@ -29,6 +29,61 @@ else {
+
+
+ @foreach (var n in items) + { + bool mIsRead = (bool)n.IsRead; + string mTitle = (string)n.Title; + string mMessage = (string)n.Message; + string? mLink = (string?)n.Link; + string mType = (string)n.NotificationType; + DateTime mCreatedAt = ((DateTime)n.CreatedAt).Tz(ViewBag.CompanyTimeZone as string); +
+
+
+ +
+
+
+ @if (!mIsRead) + { + + } + @mTitle +
+ @mCreatedAt.ToString("MMM d, yyyy h:mm tt") +
+
+
+
+ Type + @mType +
+
+ Message + @mMessage +
+
+ @if (!string.IsNullOrEmpty(mLink)) + { + + } +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/JournalEntries/Index.cshtml b/src/PowderCoating.Web/Views/JournalEntries/Index.cshtml index 347683a..3e047b7 100644 --- a/src/PowderCoating.Web/Views/JournalEntries/Index.cshtml +++ b/src/PowderCoating.Web/Views/JournalEntries/Index.cshtml @@ -47,6 +47,68 @@
+
+
+ @foreach (var je in Model) + { +
+
+
+ +
+
+
+ @je.EntryNumber + @if (je.IsReversal) + { + REV + } +
+ @je.EntryDate.ToString("MMM d, yyyy") +
+
+
+
+ Status + + @if (je.Status == JournalEntryStatus.Draft) + { + Draft + } + else if (je.Status == JournalEntryStatus.Posted) + { + Posted + } + else + { + Reversed + } + +
+ @if (!string.IsNullOrWhiteSpace(je.Description)) + { +
+ Description + @je.Description +
+ } + @if (!string.IsNullOrWhiteSpace(je.Reference)) + { +
+ Reference + @je.Reference +
+ } +
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/PurchaseOrders/Index.cshtml b/src/PowderCoating.Web/Views/PurchaseOrders/Index.cshtml index ef4cc41..1c42c8e 100644 --- a/src/PowderCoating.Web/Views/PurchaseOrders/Index.cshtml +++ b/src/PowderCoating.Web/Views/PurchaseOrders/Index.cshtml @@ -164,6 +164,56 @@
+
+
+ @foreach (var po in Model.Items) + { +
+
+
+ +
+
+
@po.PoNumber @(po.IsOverdue ? " — Overdue" : "")
+ @po.VendorName +
+
+
+
+ Status + @po.Status +
+
+ Order Date + @po.OrderDate.ToString("MM/dd/yy") +
+ @if (po.ExpectedDeliveryDate.HasValue) + { +
+ Expected + + @po.ExpectedDeliveryDate.Value.ToString("MM/dd/yy") + +
+ } +
+ Items + @po.ItemCount +
+
+ Total + $@po.TotalAmount.ToString("N2") +
+
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/RecurringTemplates/Index.cshtml b/src/PowderCoating.Web/Views/RecurringTemplates/Index.cshtml index 81dd44a..fcc42e7 100644 --- a/src/PowderCoating.Web/Views/RecurringTemplates/Index.cshtml +++ b/src/PowderCoating.Web/Views/RecurringTemplates/Index.cshtml @@ -38,6 +38,96 @@ } else { +
+
+ @foreach (var t in Model) + { + var isOverdueRT = t.IsActive && t.NextFireDate.Date < DateTime.Today; +
+
+
+ +
+
+
@t.Name
+ + @if (t.TemplateType == RecurringTemplateType.Bill) + { + Bill + } + else + { + Expense + } + — + @(t.IntervalCount == 1 ? t.Frequency.ToString() : $"Every {t.IntervalCount} × {t.Frequency}") + +
+
+
+
+ Status + + @if (t.IsActive) + { + Active + } + else + { + Paused + } + +
+ @if (t.IsActive) + { +
+ Next Fire + + @t.NextFireDate.ToString("MM/dd/yyyy") + @if (isOverdueRT) { } + +
+ } +
+ Occurrences + + @t.OccurrenceCount + @if (t.MaxOccurrences.HasValue) { / @t.MaxOccurrences } + +
+ @if (!string.IsNullOrWhiteSpace(t.LastError)) + { +
+ Error + @t.LastError +
+ } +
+ +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/SmsAgreements/Index.cshtml b/src/PowderCoating.Web/Views/SmsAgreements/Index.cshtml index 25f0515..303e5ab 100644 --- a/src/PowderCoating.Web/Views/SmsAgreements/Index.cshtml +++ b/src/PowderCoating.Web/Views/SmsAgreements/Index.cshtml @@ -112,6 +112,101 @@ } else { +
+
+ @foreach (var row in Model) + { +
+
+
+ +
+
+
+ @row.CompanyName + @if (row.IsDeleted) { Deleted } +
+ + @if (row.SmsDisabledByAdmin) + { + Admin-Disabled + } + else if (row.SmsEnabled) + { + SMS Enabled + } + else + { + SMS Off + } + +
+
+
+
+ Terms + + @{ + var dispAgreement = row.CurrentAgreement ?? row.LatestAgreement; + } + @if (row.CurrentAgreement != null) + { + v@(row.CurrentAgreement.TermsVersion) + } + else if (row.LatestAgreement != null) + { + Stale (v@(row.LatestAgreement.TermsVersion)) + } + else + { + Never + } + +
+ @if (dispAgreement != null) + { +
+ Accepted By + + @dispAgreement.AgreedByUserName + +
+
+ Accepted At + + @dispAgreement.AgreedAt.ToString("MM/dd/yy") + +
+ } + @if (row.AllAgreements.Count > 0) + { +
+ History + + + +
+ } +
+
+ } +
+
diff --git a/src/PowderCoating.Web/Views/SmsConsentAudit/Index.cshtml b/src/PowderCoating.Web/Views/SmsConsentAudit/Index.cshtml index cfd84c2..3caef8c 100644 --- a/src/PowderCoating.Web/Views/SmsConsentAudit/Index.cshtml +++ b/src/PowderCoating.Web/Views/SmsConsentAudit/Index.cshtml @@ -110,6 +110,64 @@ +
+
+ @foreach (var row in Model.Rows) + { +
+
+
+ +
+
+
@row.CustomerName
+ @(row.MobilePhone ?? row.Phone ?? "No phone") +
+
+
+
+ SMS Status + @row.StatusLabel +
+ @if (row.ConsentedAt.HasValue) + { +
+ Consented + @row.ConsentedAt.Value.ToString("MMM d, yyyy") +
+ } + @if (!string.IsNullOrWhiteSpace(row.ConsentMethod)) + { +
+ Method + @row.ConsentMethod +
+ } + @if (row.OptedOutAt.HasValue) + { +
+ Opted Out + @row.OptedOutAt.Value.ToString("MMM d, yyyy") +
+ } +
+ +
+ } + @if (!Model.Rows.Any()) + { +
+ + No customers match the current filter. +
+ } +
+
diff --git a/src/PowderCoating.Web/Views/VendorCredits/Index.cshtml b/src/PowderCoating.Web/Views/VendorCredits/Index.cshtml index ae732bf..0979648 100644 --- a/src/PowderCoating.Web/Views/VendorCredits/Index.cshtml +++ b/src/PowderCoating.Web/Views/VendorCredits/Index.cshtml @@ -68,6 +68,64 @@
+
+
+ @foreach (var vc in Model) + { + var (vcBadge, vcLabel) = vc.Status switch + { + VendorCreditStatus.Open => ("bg-success", "Open"), + VendorCreditStatus.PartiallyApplied => ("bg-warning text-dark", "Partial"), + VendorCreditStatus.Applied => ("bg-secondary", "Applied"), + VendorCreditStatus.Voided => ("bg-danger", "Voided"), + _ => ("bg-secondary", vc.Status.ToString()) + }; +
+
+
+ +
+
+
@vc.CreditNumber
+ @vc.Vendor?.CompanyName +
+
+
+
+ Status + @vcLabel +
+
+ Date + @vc.CreditDate.ToString("MM/dd/yy") +
+
+ Total + @vc.Total.ToString("C") +
+
+ Remaining + + @(vc.RemainingAmount > 0 ? vc.RemainingAmount.ToString("C") : "—") + +
+ @if (!string.IsNullOrWhiteSpace(vc.Memo)) + { +
+ Memo + @vc.Memo +
+ } +
+ +
+ } +
+