From ee4a5c3578fb862542bb77f9311e786a36b63ab3 Mon Sep 17 00:00:00 2001 From: sysadmin Date: Mon, 1 Sep 2025 08:03:00 +0100 Subject: [PATCH] Product-enhancements-and-validation-fixes --- .../Admin/Controllers/ProductsController.cs | 24 ++- .../Areas/Admin/Views/Products/Create.cshtml | 188 +++++++++++++++--- .../Areas/Admin/Views/Products/Edit.cshtml | 10 +- .../Areas/Admin/Views/Products/Index.cshtml | 11 + LittleShop/DTOs/ProductDto.cs | 18 +- LittleShop/Models/Product.cs | 3 +- LittleShop/Program.cs | 4 +- LittleShop/Services/DataSeederService.cs | 5 + LittleShop/Services/ProductService.cs | 7 +- LittleShop/wwwroot/css/modern-admin.css | 86 ++++---- LittleShop/wwwroot/js/pwa.js | 171 ++++------------ LittleShop/wwwroot/sw.js | 24 ++- 12 files changed, 340 insertions(+), 211 deletions(-) diff --git a/LittleShop/Areas/Admin/Controllers/ProductsController.cs b/LittleShop/Areas/Admin/Controllers/ProductsController.cs index 6661ea8..8629218 100644 --- a/LittleShop/Areas/Admin/Controllers/ProductsController.cs +++ b/LittleShop/Areas/Admin/Controllers/ProductsController.cs @@ -20,6 +20,11 @@ public class ProductsController : Controller public async Task Index() { + // Prevent caching of products list to show real-time data + Response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate"); + Response.Headers.Add("Pragma", "no-cache"); + Response.Headers.Add("Expires", "0"); + var products = await _productService.GetAllProductsAsync(); return View(products); } @@ -34,17 +39,31 @@ public class ProductsController : Controller [HttpPost] public async Task Create(CreateProductDto model) { - Console.WriteLine($"Received Product: Name='{model?.Name}', Description='{model?.Description}', Price={model?.Price}"); + Console.WriteLine($"Received Product: Name='{model?.Name}', Description='{model?.Description}', Price={model?.Price}, Stock={model?.StockQuantity}"); + Console.WriteLine($"CategoryId: {model?.CategoryId}"); + Console.WriteLine($"Weight: {model?.Weight}, WeightUnit: {model?.WeightUnit}"); Console.WriteLine($"ModelState.IsValid: {ModelState.IsValid}"); + // Remove Description validation errors since it's optional + ModelState.Remove("Description"); + if (!ModelState.IsValid) { + Console.WriteLine("Validation errors:"); + foreach (var error in ModelState) + { + if (error.Value?.Errors.Count > 0) + { + Console.WriteLine($" {error.Key}: {string.Join(", ", error.Value.Errors.Select(e => e.ErrorMessage))}"); + } + } + var categories = await _categoryService.GetAllCategoriesAsync(); ViewData["Categories"] = categories.Where(c => c.IsActive); return View(model); } - await _productService.CreateProductAsync(model); + var createdProduct = await _productService.CreateProductAsync(model); return RedirectToAction(nameof(Index)); } @@ -68,6 +87,7 @@ public class ProductsController : Controller WeightUnit = product.WeightUnit, Weight = product.Weight, Price = product.Price, + StockQuantity = product.StockQuantity, CategoryId = product.CategoryId, IsActive = product.IsActive }; diff --git a/LittleShop/Areas/Admin/Views/Products/Create.cshtml b/LittleShop/Areas/Admin/Views/Products/Create.cshtml index 8b9ce62..c66f790 100644 --- a/LittleShop/Areas/Admin/Views/Products/Create.cshtml +++ b/LittleShop/Areas/Admin/Views/Products/Create.cshtml @@ -17,46 +17,86 @@
@Html.AntiForgeryToken() - @if (ViewData.ModelState[""] != null && ViewData.ModelState[""].Errors.Count > 0) + + @if (!ViewData.ModelState.IsValid) { }
- + 0 ? "is-invalid" : "")" required /> + @if(ViewData.ModelState["Name"]?.Errors.Count > 0) + { +
+ @ViewData.ModelState["Name"]?.Errors.FirstOrDefault()?.ErrorMessage +
+ }
- - + + + @if(ViewData.ModelState["Description"]?.Errors.Count > 0) + { +
+ @ViewData.ModelState["Description"]?.Errors.FirstOrDefault()?.ErrorMessage +
+ }
-
+
- + 0 ? "is-invalid" : "")" required /> + @if(ViewData.ModelState["Price"]?.Errors.Count > 0) + { +
+ @ViewData.ModelState["Price"]?.Errors.FirstOrDefault()?.ErrorMessage +
+ }
-
+
+
+ + 0 ? "is-invalid" : "")" required /> + @if(ViewData.ModelState["StockQuantity"]?.Errors.Count > 0) + { +
+ @ViewData.ModelState["StockQuantity"]?.Errors.FirstOrDefault()?.ErrorMessage +
+ } +
+
+
- 0 ? "is-invalid" : "")" required> @if (categories != null) { @foreach (var category in categories) { - + } } + @if(ViewData.ModelState["CategoryId"]?.Errors.Count > 0) + { +
+ @ViewData.ModelState["CategoryId"]?.Errors.FirstOrDefault()?.ErrorMessage +
+ }
@@ -65,21 +105,33 @@
- + 0 ? "is-invalid" : "")" required /> + @if(ViewData.ModelState["Weight"]?.Errors.Count > 0) + { +
+ @ViewData.ModelState["Weight"]?.Errors.FirstOrDefault()?.ErrorMessage +
+ }
- 0 ? "is-invalid" : "")"> + + + + + + + + @if(ViewData.ModelState["WeightUnit"]?.Errors.Count > 0) + { +
+ @ViewData.ModelState["WeightUnit"]?.Errors.FirstOrDefault()?.ErrorMessage +
+ }
@@ -105,13 +157,99 @@
  • Name: Unique product identifier
  • -
  • Description: Supports Unicode and emojis
  • +
  • Description: Optional, supports Unicode and emojis
  • Price: Base price in GBP
  • +
  • Stock: Current inventory quantity
  • Weight/Volume: Used for shipping calculations
  • Category: Product organization
  • +
  • Photos: Can be added after creating the product
- You can add photos after creating the product. + The form remembers your last used category and weight unit. Add photos after creation.
- \ No newline at end of file + + +@section Scripts { + +} \ No newline at end of file diff --git a/LittleShop/Areas/Admin/Views/Products/Edit.cshtml b/LittleShop/Areas/Admin/Views/Products/Edit.cshtml index 6960c74..4bf6c3c 100644 --- a/LittleShop/Areas/Admin/Views/Products/Edit.cshtml +++ b/LittleShop/Areas/Admin/Views/Products/Edit.cshtml @@ -40,13 +40,19 @@
-
+
-
+
+
+ + +
+
+