diff --git a/Webshop.Api/Controllers/Customers/CartController.cs b/Webshop.Api/Controllers/Customers/CartController.cs new file mode 100644 index 0000000..cdd045b --- /dev/null +++ b/Webshop.Api/Controllers/Customers/CartController.cs @@ -0,0 +1,50 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Security.Claims; +using System.Threading.Tasks; +using Webshop.Application; +using Webshop.Application.DTOs.Customers; +using Webshop.Application.DTOs.Shipping; +using Webshop.Application.Services.Customers.Interfaces; + +namespace Webshop.Api.Controllers.Customer +{ + [ApiController] + [Route("api/v1/customer/[controller]")] + [Authorize(Roles = "Customer")] + public class CartController : ControllerBase + { + private readonly ICartService _cartService; + + public CartController(ICartService cartService) + { + _cartService = cartService; + } + + [HttpGet] + public async Task GetCart() + { + var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); + var result = await _cartService.GetCartAsync(userId!); + return Ok(result.Value); + } + + [HttpPost("items")] + public async Task AddToCart([FromBody] CartItemDto item) + { + var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); + var result = await _cartService.AddToCartAsync(userId!, item); + return result.Type == ServiceResultType.Success ? Ok() : BadRequest(result.ErrorMessage); + } + + [HttpDelete("items/{productId}")] + public async Task RemoveItem(Guid productId) + { + var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); + await _cartService.RemoveFromCartAsync(userId!, productId); + return NoContent(); + } + } +} \ No newline at end of file diff --git a/Webshop.Application/DTOs/Customers/CartDto.cs b/Webshop.Application/DTOs/Customers/CartDto.cs new file mode 100644 index 0000000..9b8d492 --- /dev/null +++ b/Webshop.Application/DTOs/Customers/CartDto.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using Webshop.Application.DTOs.Shipping; // Oder wo CartItemDto liegt + +namespace Webshop.Application.DTOs.Customers +{ + public class CartDto + { + public Guid Id { get; set; } + public string UserId { get; set; } = string.Empty; + public List Items { get; set; } = new List(); + public decimal TotalEstimatedPrice { get; set; } // Optional: Summe berechnet + } +} \ No newline at end of file diff --git a/Webshop.Application/Services/Customers/CartService.cs b/Webshop.Application/Services/Customers/CartService.cs index 60538d9..0958bf6 100644 --- a/Webshop.Application/Services/Customers/CartService.cs +++ b/Webshop.Application/Services/Customers/CartService.cs @@ -1,7 +1,12 @@ using Microsoft.EntityFrameworkCore; +using System; using System.Linq; using System.Threading.Tasks; +using Webshop.Application; +using Webshop.Application.DTOs.Customers; +using Webshop.Application.DTOs.Shipping; using Webshop.Application.Services.Customers.Interfaces; +using Webshop.Domain.Entities; using Webshop.Infrastructure.Data; namespace Webshop.Application.Services.Customers @@ -15,24 +20,87 @@ namespace Webshop.Application.Services.Customers _context = context; } + public async Task> GetCartAsync(string userId) + { + var cart = await GetCartEntity(userId); + if (cart == null) return ServiceResult.Ok(new CartDto()); // Leerer Warenkorb + + var dto = new CartDto + { + Id = cart.Id, + UserId = userId, + Items = cart.Items.Select(i => new CartItemDto + { + ProductId = i.ProductId, + ProductVariantId = i.ProductVariantId, + Quantity = i.Quantity + }).ToList() + }; + return ServiceResult.Ok(dto); + } + + public async Task AddToCartAsync(string userId, CartItemDto itemDto) + { + var cart = await GetCartEntity(userId); + if (cart == null) + { + cart = new Cart { UserId = userId, Id = Guid.NewGuid() }; + _context.Carts.Add(cart); + } + + var existingItem = cart.Items.FirstOrDefault(i => i.ProductId == itemDto.ProductId && i.ProductVariantId == itemDto.ProductVariantId); + + if (existingItem != null) + { + existingItem.Quantity += itemDto.Quantity; + } + else + { + var newItem = new CartItem + { + CartId = cart.Id, + ProductId = itemDto.ProductId, + ProductVariantId = itemDto.ProductVariantId, + Quantity = itemDto.Quantity + }; + cart.Items.Add(newItem); // Wichtig: Muss in CartItems DbSet landen + _context.CartItems.Add(newItem); + } + + cart.LastModified = DateTime.UtcNow; + await _context.SaveChangesAsync(); + return ServiceResult.Ok(); + } + + public async Task RemoveFromCartAsync(string userId, Guid productId) + { + var cart = await GetCartEntity(userId); + if (cart == null) return ServiceResult.Fail(ServiceResultType.NotFound, "Warenkorb leer."); + + var item = cart.Items.FirstOrDefault(i => i.ProductId == productId); + if (item != null) + { + _context.CartItems.Remove(item); + await _context.SaveChangesAsync(); + } + return ServiceResult.Ok(); + } + public async Task ClearCartAsync(string userId) { - // Wir suchen den Warenkorb des Users - // Annahme: Es gibt eine 'Carts' Tabelle und 'CartItems' - var cart = await _context.Carts - .Include(c => c.Items) - .FirstOrDefaultAsync(c => c.UserId == userId); - + var cart = await GetCartEntity(userId); if (cart != null && cart.Items.Any()) { - // Option A: Nur Items löschen, Warenkorb behalten _context.CartItems.RemoveRange(cart.Items); - - // Option B: Ganzen Warenkorb löschen (dann wird er beim nächsten AddToCart neu erstellt) - // _context.Carts.Remove(cart); - await _context.SaveChangesAsync(); } } + + private async Task GetCartEntity(string userId) + { + return await _context.Carts + .Include(c => c.Items) + .FirstOrDefaultAsync(c => c.UserId == userId); + } } } \ No newline at end of file diff --git a/Webshop.Application/Services/Customers/Interfaces/ICartService.cs b/Webshop.Application/Services/Customers/Interfaces/ICartService.cs index 51cc2c7..12eec4b 100644 --- a/Webshop.Application/Services/Customers/Interfaces/ICartService.cs +++ b/Webshop.Application/Services/Customers/Interfaces/ICartService.cs @@ -1,9 +1,14 @@ using System.Threading.Tasks; +using Webshop.Application.DTOs.Shipping; // Für CartItemDto +using Webshop.Application; // Für ServiceResult namespace Webshop.Application.Services.Customers.Interfaces { public interface ICartService { + Task> GetCartAsync(string userId); + Task AddToCartAsync(string userId, CartItemDto item); + Task RemoveFromCartAsync(string userId, Guid productId); Task ClearCartAsync(string userId); } } \ No newline at end of file