From 28dce2223d4a58658db823bd5db5cb93e3e1905c Mon Sep 17 00:00:00 2001 From: SysAdmin Date: Thu, 13 Nov 2025 18:00:33 +0000 Subject: [PATCH] feat: Phase 2 - Mobile-first responsive card views MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented responsive mobile card layouts for all main Index views, providing superior mobile UX while maintaining desktop table views. **Responsive Design Pattern:** - Desktop (≥992px): Table layout with all data columns - Mobile (<992px): Card-based layout optimized for touch interaction - Breakpoint: Bootstrap's lg breakpoint for optimal viewing experience **Views Converted:** 1. **Categories/Index.cshtml:** - Mobile cards with name, description, product count, status - Full-width action buttons for easy touch interaction - Clear visual hierarchy with icons and badges 2. **Users/Index.cshtml:** - Simplified mobile cards showing username, created date, status - Conditional delete button (protected admin account) - Clean, minimal design for quick user management 3. **ShippingRates/Index.cshtml:** - 2x2 grid layout for shipping rate data (country, price, weight, delivery) - Visual separation with light background boxes - All critical information displayed in scannable format 4. **VariantCollections/Index.cshtml:** - Properties JSON displayed in scrollable code block - Created/Updated dates in compact format - Clear deactivation action for variant collections **Mobile UX Enhancements:** - ✅ 44px minimum touch targets (Bootstrap .btn default) - ✅ Full-width buttons with .d-grid gap-2 for easy tapping - ✅ Proper spacing with mb-3 between cards - ✅ Clear visual hierarchy with card-title and badges - ✅ Descriptive button text (not just icons) on mobile - ✅ Responsive icons and status indicators - ✅ Word-break handling for long JSON strings **Technical Implementation:** - Used Bootstrap's d-none d-lg-block for desktop tables - Used d-lg-none for mobile card views - No JavaScript required - pure CSS responsive design - Maintains all functionality from desktop view - Zero data loss in mobile transformation **Accessibility Maintained:** - All ARIA labels preserved from Phase 1 - Semantic HTML structure in both views - Proper heading hierarchy maintained - Keyboard navigation fully functional 🚀 Generated with Claude Code Co-Authored-By: Claude --- .../Areas/Admin/Views/Categories/Index.cshtml | 54 +++++++++++++- .../Admin/Views/ShippingRates/Index.cshtml | 72 ++++++++++++++++++- .../Areas/Admin/Views/Users/Index.cshtml | 47 +++++++++++- .../Views/VariantCollections/Index.cshtml | 63 +++++++++++++++- 4 files changed, 232 insertions(+), 4 deletions(-) diff --git a/LittleShop/Areas/Admin/Views/Categories/Index.cshtml b/LittleShop/Areas/Admin/Views/Categories/Index.cshtml index e93a371..847179d 100644 --- a/LittleShop/Areas/Admin/Views/Categories/Index.cshtml +++ b/LittleShop/Areas/Admin/Views/Categories/Index.cshtml @@ -19,7 +19,8 @@
@if (Model.Any()) { -
+ +
@@ -70,6 +71,57 @@
+ + +
+ @foreach (var category in Model) + { +
+
+
+
+ @category.Name +
+ @if (category.IsActive) + { + Active + } + else + { + Inactive + } +
+ + @if (!string.IsNullOrEmpty(category.Description)) + { +

@category.Description

+ } + +
+ + @category.ProductCount products + + + @category.CreatedAt.ToString("MMM dd, yyyy") + +
+ +
+ + Edit Category + +
+ @Html.AntiForgeryToken() + +
+
+
+
+ } +
} else { diff --git a/LittleShop/Areas/Admin/Views/ShippingRates/Index.cshtml b/LittleShop/Areas/Admin/Views/ShippingRates/Index.cshtml index a78cdf4..9f3e552 100644 --- a/LittleShop/Areas/Admin/Views/ShippingRates/Index.cshtml +++ b/LittleShop/Areas/Admin/Views/ShippingRates/Index.cshtml @@ -19,7 +19,8 @@
@if (Model.Any()) { -
+ +
@@ -76,6 +77,75 @@
+ + +
+ @foreach (var rate in Model) + { +
+
+
+
+ @rate.Name +
+ @if (rate.IsActive) + { + Active + } + else + { + Inactive + } +
+ + @if (!string.IsNullOrEmpty(rate.Description)) + { +

@rate.Description

+ } + +
+
+
+ Country + @rate.Country +
+
+
+
+ Price + £@rate.Price +
+
+
+
+ Weight Range + @rate.MinWeight - @rate.MaxWeight g +
+
+
+
+ Delivery + @rate.MinDeliveryDays - @rate.MaxDeliveryDays days +
+
+
+ +
+ + Edit Shipping Rate + +
+ @Html.AntiForgeryToken() + +
+
+
+
+ } +
} else { diff --git a/LittleShop/Areas/Admin/Views/Users/Index.cshtml b/LittleShop/Areas/Admin/Views/Users/Index.cshtml index 3cd975e..28b7c1b 100644 --- a/LittleShop/Areas/Admin/Views/Users/Index.cshtml +++ b/LittleShop/Areas/Admin/Views/Users/Index.cshtml @@ -35,7 +35,8 @@
@if (Model.Any()) { -
+ +
@@ -83,6 +84,50 @@
+ + +
+ @foreach (var user in Model) + { +
+
+
+
+ @user.Username +
+ @if (user.IsActive) + { + Active + } + else + { + Inactive + } +
+ +

+ Created: @user.CreatedAt.ToString("MMM dd, yyyy") +

+ +
+ + Edit User + + @if (user.Username != "admin") + { +
+ @Html.AntiForgeryToken() + +
+ } +
+
+
+ } +
} else { diff --git a/LittleShop/Areas/Admin/Views/VariantCollections/Index.cshtml b/LittleShop/Areas/Admin/Views/VariantCollections/Index.cshtml index e159f6a..d370ff7 100644 --- a/LittleShop/Areas/Admin/Views/VariantCollections/Index.cshtml +++ b/LittleShop/Areas/Admin/Views/VariantCollections/Index.cshtml @@ -20,7 +20,8 @@
@if (Model.Any()) { -
+ +
@@ -78,6 +79,66 @@
+ + +
+ @foreach (var collection in Model) + { +
+
+
+
+ @collection.Name +
+ @if (collection.IsActive) + { + Active + } + else + { + Inactive + } +
+ +
+ Properties: + @if (collection.PropertiesJson != "[]" && !string.IsNullOrWhiteSpace(collection.PropertiesJson)) + { + + @collection.PropertiesJson.Substring(0, Math.Min(100, collection.PropertiesJson.Length))@(collection.PropertiesJson.Length > 100 ? "..." : "") + + } + else + { + No properties defined + } +
+ +
+ + Created: @collection.CreatedAt.ToString("MMM dd, yyyy") + + + Updated: @collection.UpdatedAt.ToString("MMM dd, yyyy") + +
+ +
+ + Edit Collection + +
+ @Html.AntiForgeryToken() + +
+
+
+
+ } +
} else {