Fix: Populate existing variant panels with imported ProductVariant data
**Previous Approach (WRONG):**
- Created a separate table section to display ProductVariants
- User wanted data in the EXISTING collapsible panels, not a new section
**Proper Fix:**
- ProductImportService creates records in ProductVariants table
- Edit page's collapsible panels read from VariantsJson field (different system)
- Solution: Convert ProductVariants → VariantsJson format on page load
**Changes:**
1. **ProductsController.cs (Lines 105-115):**
- Load ProductVariants from database
- If VariantsJson empty but ProductVariants exist, convert them
- Format: `[{Weight: "28g", Price: 700, StockQty: 100}, ...]`
- JavaScript reads Price and StockQty to populate collapsible panel fields
2. **Edit.cshtml:**
- Removed the extra table section
- Existing collapsible panels now display imported data automatically
**Result:**
When you open Edit page, expand "Product Variants" → "Price, Stock & Weight Details",
the fields will be PRE-FILLED with your imported values (700, 100, etc.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
2c5815510d
commit
9f7b2840af
@ -98,10 +98,22 @@ public class ProductsController : Controller
|
|||||||
var productMultiBuys = await _productService.GetProductMultiBuysAsync(id);
|
var productMultiBuys = await _productService.GetProductMultiBuysAsync(id);
|
||||||
ViewData["ProductMultiBuys"] = productMultiBuys;
|
ViewData["ProductMultiBuys"] = productMultiBuys;
|
||||||
|
|
||||||
// Load product variants
|
// Load product variants and convert to VariantsJson format for UI
|
||||||
var productVariants = await _productService.GetProductVariantsAsync(id);
|
var productVariants = await _productService.GetProductVariantsAsync(id);
|
||||||
ViewData["ProductVariants"] = productVariants;
|
ViewData["ProductVariants"] = productVariants;
|
||||||
|
|
||||||
|
// If product has no VariantsJson but has ProductVariant records, convert them
|
||||||
|
if ((string.IsNullOrEmpty(product.VariantsJson) || product.VariantsJson == "[]") && productVariants.Any())
|
||||||
|
{
|
||||||
|
var variantsForJson = productVariants.Select(v => new
|
||||||
|
{
|
||||||
|
Weight = v.Name, // Use variant name as the "Weight" property
|
||||||
|
Price = v.Price,
|
||||||
|
StockQty = v.StockLevel
|
||||||
|
}).ToList();
|
||||||
|
product.VariantsJson = System.Text.Json.JsonSerializer.Serialize(variantsForJson);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Add ReviewService injection and retrieve actual reviews
|
// TODO: Add ReviewService injection and retrieve actual reviews
|
||||||
// For now, providing mock review data for demonstration
|
// For now, providing mock review data for demonstration
|
||||||
ViewData["ProductReviews"] = new[]
|
ViewData["ProductReviews"] = new[]
|
||||||
@ -139,7 +151,7 @@ public class ProductsController : Controller
|
|||||||
StockQuantity = product.StockQuantity,
|
StockQuantity = product.StockQuantity,
|
||||||
CategoryId = product.CategoryId,
|
CategoryId = product.CategoryId,
|
||||||
VariantCollectionId = product.VariantCollectionId,
|
VariantCollectionId = product.VariantCollectionId,
|
||||||
VariantsJson = product.VariantsJson,
|
VariantsJson = product.VariantsJson, // Now contains converted ProductVariants data
|
||||||
IsActive = product.IsActive
|
IsActive = product.IsActive
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -317,101 +317,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Product Variants (from Text Import) Display Section -->
|
|
||||||
@{
|
|
||||||
var productVariants = ViewData["ProductVariants"] as IEnumerable<LittleShop.DTOs.ProductVariantDto>;
|
|
||||||
}
|
|
||||||
@if (productVariants != null && productVariants.Any())
|
|
||||||
{
|
|
||||||
<hr class="my-4">
|
|
||||||
<div class="card mb-3">
|
|
||||||
<div class="card-header p-0">
|
|
||||||
<button class="btn btn-link w-100 text-start d-flex justify-content-between align-items-center"
|
|
||||||
type="button" data-bs-toggle="collapse" data-bs-target="#productVariantsCollapse"
|
|
||||||
aria-expanded="true" aria-controls="productVariantsCollapse">
|
|
||||||
<span>
|
|
||||||
<i class="fas fa-list me-2"></i>Product Variants
|
|
||||||
<small class="text-muted ms-2">@productVariants.Count() variant(s) configured</small>
|
|
||||||
</span>
|
|
||||||
<i class="fas fa-chevron-down transition-transform"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="collapse show" id="productVariantsCollapse">
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="text-muted">
|
|
||||||
<i class="fas fa-info-circle"></i> These variants were imported via text import format.
|
|
||||||
To manage them, use the <a href="@Url.Action("ProductVariants", new { id = productId })" class="alert-link">Product Variants page</a>
|
|
||||||
or re-import via <a href="@Url.Action("ImportText", "Products")" class="alert-link">Text Import</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-sm table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Type</th>
|
|
||||||
<th>Price</th>
|
|
||||||
<th>Stock Level</th>
|
|
||||||
<th>Sort Order</th>
|
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach (var variant in productVariants.OrderBy(v => v.SortOrder))
|
|
||||||
{
|
|
||||||
<tr>
|
|
||||||
<td><strong>@variant.Name</strong></td>
|
|
||||||
<td>
|
|
||||||
<span class="badge bg-secondary">@variant.VariantType</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
@if (variant.Price.HasValue)
|
|
||||||
{
|
|
||||||
<strong class="text-success">£@variant.Price.Value.ToString("F2")</strong>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<span class="text-muted">£@Model?.Price.ToString("F2") (base)</span>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
@if (variant.StockLevel > 0)
|
|
||||||
{
|
|
||||||
<span class="badge bg-success">@variant.StockLevel in stock</span>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<span class="badge bg-danger">Out of stock</span>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
<td>@variant.SortOrder</td>
|
|
||||||
<td>
|
|
||||||
@if (variant.IsActive)
|
|
||||||
{
|
|
||||||
<span class="badge bg-success">Active</span>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<span class="badge bg-secondary">Inactive</span>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert alert-info mt-3 mb-0">
|
|
||||||
<i class="fas fa-lightbulb"></i> <strong>Quick Summary:</strong>
|
|
||||||
Total variants: @productVariants.Count() |
|
|
||||||
Total stock: @productVariants.Sum(v => v.StockLevel) units |
|
|
||||||
Price range: £@productVariants.Where(v => v.Price.HasValue).Min(v => v.Price ?? 0).ToString("F2") - £@productVariants.Where(v => v.Price.HasValue).Max(v => v.Price ?? 0).ToString("F2")
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input name="IsActive" type="checkbox" class="form-check-input" checked="@(Model?.IsActive == true)" value="true" />
|
<input name="IsActive" type="checkbox" class="form-check-input" checked="@(Model?.IsActive == true)" value="true" />
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user