diff --git a/Webshop.Api/Controllers/Public/ProductsController.cs b/Webshop.Api/Controllers/Public/ProductsController.cs
index bef694a..77316a9 100644
--- a/Webshop.Api/Controllers/Public/ProductsController.cs
+++ b/Webshop.Api/Controllers/Public/ProductsController.cs
@@ -49,5 +49,15 @@ namespace Webshop.Api.Controllers.Public
return Ok(product);
}
+ ///
+ /// Ruft eine Liste der Sonderangebote für die Startseite ab, sortiert nach Anzeigereihenfolge.
+ ///
+ [HttpGet("featured")]
+ [ProducesResponseType(typeof(IEnumerable), 200)]
+ public async Task>> GetFeaturedProducts()
+ {
+ var products = await _productService.GetFeaturedProductsAsync();
+ return Ok(products);
+ }
}
}
\ No newline at end of file
diff --git a/Webshop.Application/DTOs/Products/AdminProductDto.cs b/Webshop.Application/DTOs/Products/AdminProductDto.cs
index ee6b150..903db66 100644
--- a/Webshop.Application/DTOs/Products/AdminProductDto.cs
+++ b/Webshop.Application/DTOs/Products/AdminProductDto.cs
@@ -16,13 +16,16 @@ namespace Webshop.Application.DTOs.Products
public bool IsInStock { get; set; } = true;
public int StockQuantity { get; set; }
public decimal? Weight { get; set; }
- // << ENTFERNT: ImageUrl >>
public string Slug { get; set; } = string.Empty;
public DateTimeOffset CreatedDate { get; set; } = DateTimeOffset.UtcNow;
public DateTimeOffset? LastModifiedDate { get; set; }
public Guid? SupplierId { get; set; }
public decimal? PurchasePrice { get; set; }
public List categorieIds { get; set; } = new List();
- public List Images { get; set; } = new List(); // << NEU >>
+ public List Images { get; set; } = new List();
+
+ // << NEU >>
+ public bool IsFeatured { get; set; }
+ public int FeaturedDisplayOrder { get; set; }
}
}
\ No newline at end of file
diff --git a/Webshop.Application/DTOs/Products/CreateAdminProductDto.cs b/Webshop.Application/DTOs/Products/CreateAdminProductDto.cs
index 8949a8e..c2d92ae 100644
--- a/Webshop.Application/DTOs/Products/CreateAdminProductDto.cs
+++ b/Webshop.Application/DTOs/Products/CreateAdminProductDto.cs
@@ -30,5 +30,8 @@ namespace Webshop.Application.DTOs.Products
public decimal? OldPrice { get; set; }
public Guid? SupplierId { get; set; }
public decimal? PurchasePrice { get; set; }
+
+ public bool IsFeatured { get; set; } = false;
+ public int FeaturedDisplayOrder { get; set; } = 0;
}
}
\ No newline at end of file
diff --git a/Webshop.Application/DTOs/Products/UpdateAdminProductDto.cs b/Webshop.Application/DTOs/Products/UpdateAdminProductDto.cs
index 51c7cba..23c98a4 100644
--- a/Webshop.Application/DTOs/Products/UpdateAdminProductDto.cs
+++ b/Webshop.Application/DTOs/Products/UpdateAdminProductDto.cs
@@ -33,5 +33,7 @@ namespace Webshop.Application.DTOs.Products
public decimal? OldPrice { get; set; }
public Guid? SupplierId { get; set; }
public decimal? PurchasePrice { get; set; }
+ public bool IsFeatured { get; set; }
+ public int FeaturedDisplayOrder { get; set; }
}
}
\ No newline at end of file
diff --git a/Webshop.Application/Services/Admin/AdminProductService.cs b/Webshop.Application/Services/Admin/AdminProductService.cs
index 0764b89..503d6d8 100644
--- a/Webshop.Application/Services/Admin/AdminProductService.cs
+++ b/Webshop.Application/Services/Admin/AdminProductService.cs
@@ -137,6 +137,8 @@ namespace Webshop.Application.Services.Admin
OldPrice = productDto.OldPrice,
SupplierId = productDto.SupplierId,
PurchasePrice = productDto.PurchasePrice,
+ IsFeatured = productDto.IsFeatured, // << NEU >>
+ FeaturedDisplayOrder = productDto.FeaturedDisplayOrder, // << NEU >>
Images = images,
Productcategories = productDto.CategorieIds.Select(cId => new Productcategorie { categorieId = cId }).ToList()
};
@@ -196,6 +198,8 @@ namespace Webshop.Application.Services.Admin
existingProduct.SupplierId = productDto.SupplierId;
existingProduct.PurchasePrice = productDto.PurchasePrice;
existingProduct.LastModifiedDate = DateTimeOffset.UtcNow;
+ existingProduct.IsFeatured = productDto.IsFeatured; // << NEU >>
+ existingProduct.FeaturedDisplayOrder = productDto.FeaturedDisplayOrder; // << NEU >>
// Kategorien synchronisieren
existingProduct.Productcategories.Clear();
diff --git a/Webshop.Application/Services/Public/Interfaces/IProductService.cs b/Webshop.Application/Services/Public/Interfaces/IProductService.cs
index 4d55b7f..035509b 100644
--- a/Webshop.Application/Services/Public/Interfaces/IProductService.cs
+++ b/Webshop.Application/Services/Public/Interfaces/IProductService.cs
@@ -10,5 +10,6 @@ namespace Webshop.Application.Services.Public.Interfaces
Task> GetAllProductsAsync();
Task GetProductBySlugAsync(string slug);
+ Task> GetFeaturedProductsAsync(); // << NEU >>
}
}
\ No newline at end of file
diff --git a/Webshop.Application/Services/Public/ProductService.cs b/Webshop.Application/Services/Public/ProductService.cs
index 2a62d7e..cc0de72 100644
--- a/Webshop.Application/Services/Public/ProductService.cs
+++ b/Webshop.Application/Services/Public/ProductService.cs
@@ -89,5 +89,42 @@ namespace Webshop.Application.Services.Public
}).ToList()
};
}
+
+ public async Task> GetFeaturedProductsAsync()
+ {
+ var products = await _context.Products
+ .Where(p => p.IsActive && p.IsFeatured)
+ .OrderBy(p => p.FeaturedDisplayOrder)
+ .Include(p => p.Images)
+ .Include(p => p.Productcategories).ThenInclude(pc => pc.categorie)
+ .ToListAsync();
+
+ return products.Select(p => new ProductDto
+ {
+ Id = p.Id,
+ Name = p.Name,
+ Description = p.ShortDescription, // Für die Startseite ist die Kurzbeschreibung ideal
+ SKU = p.SKU,
+ Price = p.Price,
+ IsActive = p.IsActive,
+ IsInStock = p.IsInStock,
+ StockQuantity = p.StockQuantity,
+ Slug = p.Slug,
+ categories = p.Productcategories.Select(pc => new CategorieDto
+ {
+ Id = pc.categorie.Id,
+ Name = pc.categorie.Name,
+ Slug = pc.categorie.Slug
+ }).ToList(),
+ Images = p.Images.OrderBy(i => i.DisplayOrder).Select(img => new ProductImageDto
+ {
+ Id = img.Id,
+ Url = img.Url,
+ IsMainImage = img.IsMainImage,
+ DisplayOrder = img.DisplayOrder
+ }).ToList()
+ }).ToList();
+ }
+
}
}
\ No newline at end of file
diff --git a/Webshop.Domain/Entities/Product.cs b/Webshop.Domain/Entities/Product.cs
index 94f871e..82f2896 100644
--- a/Webshop.Domain/Entities/Product.cs
+++ b/Webshop.Domain/Entities/Product.cs
@@ -33,9 +33,6 @@ namespace Webshop.Domain.Entities
public decimal? Height { get; set; }
public decimal? Length { get; set; }
- // << ENTFERNT: ImageUrl wird durch Images ersetzt >>
- // public string? ImageUrl { get; set; }
-
[Required, MaxLength(255)]
public string Slug { get; set; } = string.Empty;
[Required]
@@ -45,13 +42,16 @@ namespace Webshop.Domain.Entities
public Guid? SupplierId { get; set; }
public decimal? PurchasePrice { get; set; }
+ // << NEUE EIGENSCHAFTEN FÜR SONDERANGEBOTE >>
+ public bool IsFeatured { get; set; } = false;
+ public int FeaturedDisplayOrder { get; set; } = 0;
+ // << ENDE NEUE EIGENSCHAFTEN >>
+
public virtual Supplier? Supplier { get; set; }
public virtual ICollection Variants { get; set; } = new List();
public virtual ICollection Reviews { get; set; } = new List();
public virtual ICollection ProductDiscounts { get; set; } = new List();
public virtual ICollection Productcategories { get; set; } = new List();
-
- // << NEU: Navigation Property zu Bildern >>
public virtual ICollection Images { get; set; } = new List();
}
}
\ No newline at end of file
diff --git a/Webshop.Infrastructure/Migrations/20250812113218_checkout.Designer.cs b/Webshop.Infrastructure/Migrations/20250812123244_featureartikel.Designer.cs
similarity index 99%
rename from Webshop.Infrastructure/Migrations/20250812113218_checkout.Designer.cs
rename to Webshop.Infrastructure/Migrations/20250812123244_featureartikel.Designer.cs
index 139313f..f2492b8 100644
--- a/Webshop.Infrastructure/Migrations/20250812113218_checkout.Designer.cs
+++ b/Webshop.Infrastructure/Migrations/20250812123244_featureartikel.Designer.cs
@@ -12,8 +12,8 @@ using Webshop.Infrastructure.Data;
namespace Webshop.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
- [Migration("20250812113218_checkout")]
- partial class checkout
+ [Migration("20250812123244_featureartikel")]
+ partial class featureartikel
{
///
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -576,6 +576,9 @@ namespace Webshop.Infrastructure.Migrations
.HasMaxLength(4000)
.HasColumnType("character varying(4000)");
+ b.Property("FeaturedDisplayOrder")
+ .HasColumnType("integer");
+
b.Property("Height")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
@@ -583,6 +586,9 @@ namespace Webshop.Infrastructure.Migrations
b.Property("IsActive")
.HasColumnType("boolean");
+ b.Property("IsFeatured")
+ .HasColumnType("boolean");
+
b.Property("IsInStock")
.HasColumnType("boolean");
diff --git a/Webshop.Infrastructure/Migrations/20250812113218_checkout.cs b/Webshop.Infrastructure/Migrations/20250812123244_featureartikel.cs
similarity index 99%
rename from Webshop.Infrastructure/Migrations/20250812113218_checkout.cs
rename to Webshop.Infrastructure/Migrations/20250812123244_featureartikel.cs
index 95a30b0..e0ca3f5 100644
--- a/Webshop.Infrastructure/Migrations/20250812113218_checkout.cs
+++ b/Webshop.Infrastructure/Migrations/20250812123244_featureartikel.cs
@@ -7,7 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Webshop.Infrastructure.Migrations
{
///
- public partial class checkout : Migration
+ public partial class featureartikel : Migration
{
///
protected override void Up(MigrationBuilder migrationBuilder)
@@ -460,7 +460,9 @@ namespace Webshop.Infrastructure.Migrations
CreatedDate = table.Column(type: "timestamp with time zone", nullable: false),
LastModifiedDate = table.Column(type: "timestamp with time zone", nullable: true),
SupplierId = table.Column(type: "uuid", nullable: true),
- PurchasePrice = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: true)
+ PurchasePrice = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: true),
+ IsFeatured = table.Column(type: "boolean", nullable: false),
+ FeaturedDisplayOrder = table.Column(type: "integer", nullable: false)
},
constraints: table =>
{
diff --git a/Webshop.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/Webshop.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs
index 0392333..42ffa62 100644
--- a/Webshop.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs
+++ b/Webshop.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs
@@ -573,6 +573,9 @@ namespace Webshop.Infrastructure.Migrations
.HasMaxLength(4000)
.HasColumnType("character varying(4000)");
+ b.Property("FeaturedDisplayOrder")
+ .HasColumnType("integer");
+
b.Property("Height")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
@@ -580,6 +583,9 @@ namespace Webshop.Infrastructure.Migrations
b.Property("IsActive")
.HasColumnType("boolean");
+ b.Property("IsFeatured")
+ .HasColumnType("boolean");
+
b.Property("IsInStock")
.HasColumnType("boolean");