From b3ef79e495bff178ea6c1e44a2484c548f9bdbcf Mon Sep 17 00:00:00 2001 From: Peter Foster Date: Wed, 15 Apr 2026 03:00:36 +0100 Subject: [PATCH] Add dyscalculia-friendly UI: card preview, verbal prices, relative dates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - NumberWords helper: decimal → "about seventeen pounds", DateTime → "3 days ago" - PhotoAnalysisView: after analysis shows a card preview with large verbal price, photo dots, "Looks good ✓" to save instantly, "Change something ▼" to reveal a price slider (snaps to 50p, updates verbally as you drag) and title bar - Card preview updates when live eBay price lookup completes - SavedListingsView cards: verbal price as primary, £x.xx small beneath, relative date ("yesterday", "3 days ago") instead of raw timestamp - Detail panel also shows relative date Co-Authored-By: Claude Sonnet 4.6 --- EbayListingTool/Helpers/NumberWords.cs | 79 +++++++++ EbayListingTool/Models/SavedListing.cs | 6 + EbayListingTool/Views/PhotoAnalysisView.xaml | 160 ++++++++++++++++++ .../Views/PhotoAnalysisView.xaml.cs | 139 ++++++++++++++- .../Views/SavedListingsView.xaml.cs | 31 ++-- 5 files changed, 396 insertions(+), 19 deletions(-) create mode 100644 EbayListingTool/Helpers/NumberWords.cs diff --git a/EbayListingTool/Helpers/NumberWords.cs b/EbayListingTool/Helpers/NumberWords.cs new file mode 100644 index 0000000..bf50e69 --- /dev/null +++ b/EbayListingTool/Helpers/NumberWords.cs @@ -0,0 +1,79 @@ +namespace EbayListingTool.Helpers; + +public static class NumberWords +{ + private static readonly string[] Ones = + [ + "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", + "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", + "seventeen", "eighteen", "nineteen" + ]; + + private static readonly string[] Tens = + [ + "", "", "twenty", "thirty", "forty", "fifty", + "sixty", "seventy", "eighty", "ninety" + ]; + + /// + /// Converts a price to a friendly verbal string. + /// £17.49 → "about seventeen pounds" + /// £17.50 → "about seventeen pounds fifty" + /// £0.50 → "fifty pence" + /// + public static string ToVerbalPrice(decimal price) + { + if (price <= 0) return "no price set"; + + // Snap to nearest 50p + var rounded = Math.Round(price * 2) / 2m; + int pounds = (int)rounded; + bool hasFifty = (rounded - pounds) >= 0.5m; + + if (pounds == 0) + return "fifty pence"; + + var poundsWord = IntToWords(pounds); + var poundsLabel = pounds == 1 ? "pound" : "pounds"; + var suffix = hasFifty ? " fifty" : ""; + + return $"about {poundsWord} {poundsLabel}{suffix}"; + } + + /// + /// Converts a UTC DateTime to a human-friendly relative string. + /// + public static string ToRelativeDate(DateTime utcTime) + { + var diff = DateTime.UtcNow - utcTime; + + if (diff.TotalSeconds < 60) return "just now"; + if (diff.TotalMinutes < 60) return $"{(int)diff.TotalMinutes} minutes ago"; + if (diff.TotalHours < 2) return "about an hour ago"; + if (diff.TotalHours < 24) return $"{(int)diff.TotalHours} hours ago"; + if (diff.TotalDays < 2) return "yesterday"; + if (diff.TotalDays < 7) return $"{(int)diff.TotalDays} days ago"; + if (diff.TotalDays < 14) return "last week"; + if (diff.TotalDays < 30) return $"{(int)(diff.TotalDays / 7)} weeks ago"; + if (diff.TotalDays < 60) return "last month"; + return $"{(int)(diff.TotalDays / 30)} months ago"; + } + + private static string IntToWords(int n) + { + if (n < 20) return Ones[n]; + if (n < 100) + { + var t = Tens[n / 10]; + var o = n % 10; + return o == 0 ? t : $"{t}-{Ones[o]}"; + } + if (n < 1000) + { + var h = Ones[n / 100]; + var rest = n % 100; + return rest == 0 ? $"{h} hundred" : $"{h} hundred and {IntToWords(rest)}"; + } + return n.ToString(); // fallback for very large prices + } +} diff --git a/EbayListingTool/Models/SavedListing.cs b/EbayListingTool/Models/SavedListing.cs index a269c09..fff9b2b 100644 --- a/EbayListingTool/Models/SavedListing.cs +++ b/EbayListingTool/Models/SavedListing.cs @@ -1,3 +1,5 @@ +using EbayListingTool.Helpers; + namespace EbayListingTool.Models; public class SavedListing @@ -18,5 +20,9 @@ public class SavedListing public string PriceDisplay => Price > 0 ? $"£{Price:F2}" : "—"; + public string PriceWords => NumberWords.ToVerbalPrice(Price); + public string SavedAtDisplay => SavedAt.ToLocalTime().ToString("d MMM yyyy, HH:mm"); + + public string SavedAtRelative => NumberWords.ToRelativeDate(SavedAt); } diff --git a/EbayListingTool/Views/PhotoAnalysisView.xaml b/EbayListingTool/Views/PhotoAnalysisView.xaml index 7da77e3..d45b1ea 100644 --- a/EbayListingTool/Views/PhotoAnalysisView.xaml +++ b/EbayListingTool/Views/PhotoAnalysisView.xaml @@ -325,6 +325,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +