Browse Source

Add Cart Flow

pull/49/merge
Carlos Cañizares Estévez 8 years ago
parent
commit
b079e6ba79
24 changed files with 290 additions and 142 deletions
  1. +3
    -3
      src/Web/WebMVC/Controllers/CatalogController.cs
  2. +27
    -6
      src/Web/WebMVC/Controllers/OrderController.cs
  3. +23
    -0
      src/Web/WebMVC/Extensions/SessionExtensions.cs
  4. +1
    -1
      src/Web/WebMVC/Models/CatalogItem.cs
  5. +10
    -2
      src/Web/WebMVC/Models/Order.cs
  6. +4
    -3
      src/Web/WebMVC/Models/OrderItem.cs
  7. +0
    -41
      src/Web/WebMVC/Services/CartService.cs
  8. +30
    -30
      src/Web/WebMVC/Services/CatalogService.cs
  9. +0
    -16
      src/Web/WebMVC/Services/ICartService.cs
  10. +1
    -1
      src/Web/WebMVC/Services/ICatalogService.cs
  11. +5
    -3
      src/Web/WebMVC/Services/IOrderingService.cs
  12. +55
    -9
      src/Web/WebMVC/Services/OrderingService.cs
  13. +5
    -2
      src/Web/WebMVC/Startup.cs
  14. +31
    -0
      src/Web/WebMVC/ViewComponents/Cart.cs
  15. +6
    -6
      src/Web/WebMVC/ViewComponents/CartList.cs
  16. +1
    -1
      src/Web/WebMVC/Views/Catalog/Index.cshtml
  17. +3
    -2
      src/Web/WebMVC/Views/Order/Cart.cshtml
  18. +9
    -2
      src/Web/WebMVC/Views/Shared/Components/Cart/Default.cshtml
  19. +2
    -2
      src/Web/WebMVC/Views/Shared/Components/CartList/Default.cshtml
  20. +9
    -10
      src/Web/WebMVC/Views/Shared/_LoginPartial.cshtml
  21. +1
    -0
      src/Web/WebMVC/project.json
  22. +64
    -2
      src/Web/WebMVC/wwwroot/css/site.css
  23. BIN
      src/Web/WebMVC/wwwroot/images/logout.PNG
  24. BIN
      src/Web/WebMVC/wwwroot/images/my_orders.PNG

+ 3
- 3
src/Web/WebMVC/Controllers/CatalogController.cs View File

@ -26,7 +26,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
{ {
var vm = new IndexViewModel() var vm = new IndexViewModel()
{ {
CatalogItems = await _catalogSvc.GetCatalogItems(8 * (page ?? 0), 8),
CatalogItems = await _catalogSvc.GetCatalogItems(6 * (page ?? 0), 6),
Brands = _catalogSvc.GetTypes(), Brands = _catalogSvc.GetTypes(),
Types = _catalogSvc.GetBrands(), Types = _catalogSvc.GetBrands(),
BrandFilterApplied = BrandFilterApplied ?? 0, BrandFilterApplied = BrandFilterApplied ?? 0,
@ -34,9 +34,9 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
PaginationInfo = new PaginationInfo() PaginationInfo = new PaginationInfo()
{ {
ActualPage = page ?? 0, ActualPage = page ?? 0,
ItemsPerPage = 8,
ItemsPerPage = 6,
TotalItems = _catalogSvc.TotalItems, TotalItems = _catalogSvc.TotalItems,
TotalPages = int.Parse(Math.Round(((decimal)_catalogSvc.TotalItems / 8), MidpointRounding.AwayFromZero).ToString())
TotalPages = int.Parse(Math.Round(((decimal)_catalogSvc.TotalItems / 6), MidpointRounding.AwayFromZero).ToString())
} }
}; };


+ 27
- 6
src/Web/WebMVC/Controllers/OrderController.cs View File

@ -5,20 +5,41 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.WebMVC.Services; using Microsoft.eShopOnContainers.WebMVC.Services;
using Microsoft.eShopOnContainers.WebMVC.Models; using Microsoft.eShopOnContainers.WebMVC.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
namespace Microsoft.eShopOnContainers.WebMVC.Controllers namespace Microsoft.eShopOnContainers.WebMVC.Controllers
{ {
[Authorize]
public class OrderController : Controller public class OrderController : Controller
{ {
private IOrderingService _orderSvc; private IOrderingService _orderSvc;
public OrderController(IOrderingService orderSvc)
private ICatalogService _catalogSvc;
private readonly UserManager<ApplicationUser> _userManager;
public OrderController(IOrderingService orderSvc, ICatalogService catalogSvc, UserManager<ApplicationUser> userManager)
{ {
_userManager = userManager;
_orderSvc = orderSvc; _orderSvc = orderSvc;
_catalogSvc = catalogSvc;
} }
public IActionResult AddToCart()
public async Task<IActionResult> AddToCart(string productId)
{ {
return View();
//CCE: I need product details (price, ...), so I retrieve from Catalog service again.
// I don't like POST with a form from the catalog view (I'm avoiding Ajax too),
// I prefer Url.Action and http call here to catalog service to retrieve this info.
var user = await _userManager.GetUserAsync(HttpContext.User);
var productDetails = _catalogSvc.GetCatalogItem(productId);
var product = new OrderItem()
{
ProductId = productId,
Quantity = 1,
ProductName = productDetails.Name,
PicsUrl = productDetails.PicsUrl,
UnitPrice = productDetails.Price
};
_orderSvc.AddToCart(user, product);
return RedirectToAction("Index", "Catalog");
} }
public IActionResult Cart() public IActionResult Cart()
@ -31,10 +52,10 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
return View(); return View();
} }
public IActionResult Index(Order item)
public async Task<IActionResult> Index(Order item)
{ {
_orderSvc.AddOrder(item);
return View(_orderSvc.GetOrders());
var user = await _userManager.GetUserAsync(HttpContext.User);
return View(_orderSvc.GetMyOrders(user));
} }
} }
} }

+ 23
- 0
src/Web/WebMVC/Extensions/SessionExtensions.cs View File

@ -0,0 +1,23 @@
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public static class SessionExtensions
{
public static void SetObject(this ISession session, string key, object value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}
public static T GetObject<T>(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
}
}

+ 1
- 1
src/Web/WebMVC/Models/CatalogItem.cs View File

@ -4,7 +4,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Models
{ {
public class CatalogItem public class CatalogItem
{ {
public Guid Id { get; set; }
public string Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string Description { get; set; } public string Description { get; set; }
public decimal Price { get; set; } public decimal Price { get; set; }


+ 10
- 2
src/Web/WebMVC/Models/Order.cs View File

@ -7,7 +7,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Models
{ {
public class Order public class Order
{ {
Guid Id;
public string Id;
public List<OrderItem> OrderItems { get; set; } public List<OrderItem> OrderItems { get; set; }
public string OrderNumber public string OrderNumber
{ {
@ -17,12 +17,20 @@ namespace Microsoft.eShopOnContainers.WebMVC.Models
} }
} }
public int SequenceNumber { get; set; } public int SequenceNumber { get; set; }
public virtual Guid BuyerId { get; set; }
public virtual string BuyerId { get; set; }
public virtual Address ShippingAddress { get; set; } public virtual Address ShippingAddress { get; set; }
public virtual DateTime OrderDate { get; set; } public virtual DateTime OrderDate { get; set; }
public OrderState State { get; set; }
//(CCE) public virtual Address BillingAddress { get; set; } //(CCE) public virtual Address BillingAddress { get; set; }
//(CDLTLL) public virtual OrderStatus Status { get; set; } //(CDLTLL) public virtual OrderStatus Status { get; set; }
} }
public enum OrderState
{
Active,
InProcess,
Delivered
}
} }

+ 4
- 3
src/Web/WebMVC/Models/OrderItem.cs View File

@ -7,13 +7,14 @@ namespace Microsoft.eShopOnContainers.WebMVC.Models
{ {
public class OrderItem public class OrderItem
{ {
Guid Id;
public Guid ProductId { get; set; }
public Guid OrderId { get; set; }
public string Id;
public string ProductId { get; set; }
public string OrderId { get; set; }
public string ProductName { get; set; } public string ProductName { get; set; }
public decimal UnitPrice { get; set; } public decimal UnitPrice { get; set; }
public int Quantity { get; set; } public int Quantity { get; set; }
public decimal Discount { get; set; } public decimal Discount { get; set; }
public string PicsUrl { get; set; }
public override string ToString() public override string ToString()
{ {
return String.Format("Product Id: {0}, Quantity: {1}", this.Id, this.Quantity); return String.Format("Product Id: {0}, Quantity: {1}", this.Id, this.Quantity);


+ 0
- 41
src/Web/WebMVC/Services/CartService.cs View File

@ -1,41 +0,0 @@
using System;
using System.Threading.Tasks;
using Microsoft.eShopOnContainers.WebMVC.Models;
namespace Microsoft.eShopOnContainers.WebMVC.Services
{
public class CartService : ICartService
{
Order _order;
public CartService()
{
_order = new Order();
_order.OrderItems = new System.Collections.Generic.List<OrderItem>();
_order.OrderItems.Add(new OrderItem()
{
ProductName = "Cart product"
});
}
public void AddItemToOrder(CatalogItem item)
{
throw new NotImplementedException();
}
public int GetItemCountFromOrderInProgress()
{
throw new NotImplementedException();
}
public Task<Order> GetActiveOrder()
{
return Task.Run(() => { return _order; });
}
public void RemoveItemFromOrder(Guid itemIdentifier)
{
throw new NotImplementedException();
}
}
}

+ 30
- 30
src/Web/WebMVC/Services/CatalogService.cs View File

@ -32,41 +32,41 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
#region fake data #region fake data
_items = new List<CatalogItem>() _items = new List<CatalogItem>()
{ {
new CatalogItem() { Id = Guid.NewGuid(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" }
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Cupt Black & White Mug", Name = "Cupt Black & White Mug", Price= 17, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=CuptBlack&WhiteMug" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.PrismWhiteT-Shirt" },
new CatalogItem() { Id = Guid.NewGuid().ToString(), Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = decimal.Parse("19.5"), PicsUrl = "http://fakeimg.pl/370x240/EEEEEE/000/?text=.NETBotBlack" }
}; };
#endregion #endregion
} }
public CatalogItem GetCatalogItem(Guid Id)
public CatalogItem GetCatalogItem(string Id)
{ {
return _items.Where(x => x.Id == Id).FirstOrDefault();
return _items.Where(x => x.Id.Equals(Id)).FirstOrDefault();
} }
public Task<List<CatalogItem>> GetCatalogItems(int? skip,int? take) public Task<List<CatalogItem>> GetCatalogItems(int? skip,int? take)


+ 0
- 16
src/Web/WebMVC/Services/ICartService.cs View File

@ -1,16 +0,0 @@
using Microsoft.eShopOnContainers.WebMVC.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.WebMVC.Services
{
public interface ICartService
{
void AddItemToOrder(CatalogItem item);
void RemoveItemFromOrder(Guid itemIdentifier);
int GetItemCountFromOrderInProgress();
Task<Order> GetActiveOrder();
}
}

+ 1
- 1
src/Web/WebMVC/Services/ICatalogService.cs View File

@ -12,7 +12,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
int TotalItems { get; } int TotalItems { get; }
Task<List<CatalogItem>> GetCatalogItems(int? skip, int? take); Task<List<CatalogItem>> GetCatalogItems(int? skip, int? take);
CatalogItem GetCatalogItem(Guid Id);
CatalogItem GetCatalogItem(string Id);
IEnumerable<SelectListItem> GetBrands(); IEnumerable<SelectListItem> GetBrands();
IEnumerable<SelectListItem> GetTypes(); IEnumerable<SelectListItem> GetTypes();
} }


+ 5
- 3
src/Web/WebMVC/Services/IOrderingService.cs View File

@ -8,8 +8,10 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
{ {
public interface IOrderingService public interface IOrderingService
{ {
List<Order> GetOrders();
Order GetOrder(Guid Id);
void AddOrder(Order Order);
int ItemsInCart { get; }
List<Order> GetMyOrders(ApplicationUser user);
Order GetActiveOrder(ApplicationUser user);
void AddToCart(ApplicationUser user, OrderItem product);
Order GetOrder(ApplicationUser user, Guid orderId);
} }
} }

+ 55
- 9
src/Web/WebMVC/Services/OrderingService.cs View File

@ -3,44 +3,90 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.eShopOnContainers.WebMVC.Models; using Microsoft.eShopOnContainers.WebMVC.Models;
using Microsoft.AspNetCore.Http;
namespace Microsoft.eShopOnContainers.WebMVC.Services namespace Microsoft.eShopOnContainers.WebMVC.Services
{ {
public class OrderingService : IOrderingService public class OrderingService : IOrderingService
{ {
private List<Order> _orders; private List<Order> _orders;
private int _itemsInCart;
private IHttpContextAccessor _httpContextAccessor;
public int ItemsInCart { get { return _itemsInCart; } }
//var ordersUrl = _settings.OrderingUrl + "/api/ordering/orders"; //var ordersUrl = _settings.OrderingUrl + "/api/ordering/orders";
//var dataString = await _http.GetStringAsync(ordersUrl); //var dataString = await _http.GetStringAsync(ordersUrl);
//var items = JsonConvert.DeserializeObject<List<Order>>(dataString); //var items = JsonConvert.DeserializeObject<List<Order>>(dataString);
public OrderingService()
public OrderingService(IHttpContextAccessor httpContextAccessor)
{ {
_httpContextAccessor = httpContextAccessor;
_orders = new List<Order>() _orders = new List<Order>()
{ {
new Order() new Order()
{ {
BuyerId = Guid.NewGuid(), OrderDate = DateTime.Now,
BuyerId = new Guid("ebcbcb4c-b032-4baa-834b-7fd66d37bc95").ToString(),
OrderDate = DateTime.Now,
State = OrderState.Active,
OrderItems = new List<OrderItem>()
{
new OrderItem() { UnitPrice = 12, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt", Quantity = 1, ProductName="Roslyn Red T-Shirt" }
}
},
new Order()
{
BuyerId = new Guid("ebcbcb4c-b032-4baa-834b-7fd66d37bc95").ToString(),
OrderDate = DateTime.Now,
State = OrderState.InProcess,
OrderItems = new List<OrderItem>()
{
new OrderItem() { UnitPrice = 12, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt", Quantity = 1, ProductName="Roslyn Red T-Shirt" }
}
},
new Order()
{
BuyerId = new Guid("ebcbcb4c-b032-4baa-834b-7fd66d37bc95").ToString(),
OrderDate = DateTime.Now,
State = OrderState.InProcess,
OrderItems = new List<OrderItem>() OrderItems = new List<OrderItem>()
{ {
new OrderItem() { UnitPrice = 12 }
new OrderItem() { UnitPrice = 12, PicsUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt", Quantity = 1, ProductName="Roslyn Red T-Shirt" }
} }
} }
}; };
} }
public void AddOrder(Order Order)
public Order GetActiveOrder(ApplicationUser user)
{
//I think could be a good aproach to work with session to store the active order.
//....
Order activeOrder;
activeOrder = _httpContextAccessor.HttpContext.Session.GetObject<Order>("MyActiveOrder");
if (activeOrder == null)
activeOrder = _orders.Where(x => x.BuyerId.Equals(user.Id) && x.State == OrderState.Active).FirstOrDefault();
_itemsInCart = (activeOrder != null) ? activeOrder.OrderItems.Count() : 0;
return activeOrder;
}
public Order GetOrder(ApplicationUser user, Guid Id)
{ {
_orders.Add(Order);
return _orders.Where(x => x.BuyerId.Equals(user.Id) && x.Id.Equals(Id)).FirstOrDefault();
} }
public Order GetOrder(Guid Id)
public List<Order> GetMyOrders(ApplicationUser user)
{ {
return _orders.Where(x => x.BuyerId == Id).FirstOrDefault();
return _orders.Where(x => x.BuyerId.Equals(user.Id)).ToList();
} }
public List<Order> GetOrders()
public void AddToCart(ApplicationUser user, OrderItem product)
{ {
return _orders;
var activeOrder = GetActiveOrder(user);
activeOrder.OrderItems.Add(product);
//CCE: lacks and httpcall to persist in the real back.end service.
_httpContextAccessor.HttpContext.Session.SetObject("MyActiveOrder", activeOrder);
} }
} }
} }

+ 5
- 2
src/Web/WebMVC/Startup.cs View File

@ -49,13 +49,14 @@ namespace Microsoft.eShopOnContainers.WebMVC
.AddDefaultTokenProviders(); .AddDefaultTokenProviders();
services.AddMvc(); services.AddMvc();
services.AddDistributedMemoryCache(); // default implementation (in memory), you can move to SQL or custom store that could be Redis..
services.AddSession();
// Add application services. // Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>(); services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>(); services.AddTransient<ISmsSender, AuthMessageSender>();
services.AddTransient<ICatalogService, CatalogService>();
services.AddSingleton<ICatalogService, CatalogService>();
services.AddTransient<IOrderingService, OrderingService>(); services.AddTransient<IOrderingService, OrderingService>();
services.AddTransient<ICartService, CartService>();
services.Configure<AppSettings>(Configuration); services.Configure<AppSettings>(Configuration);
} }
@ -81,6 +82,8 @@ namespace Microsoft.eShopOnContainers.WebMVC
app.UseIdentity(); app.UseIdentity();
app.UseSession();
// Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715 // Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
app.UseMvc(routes => app.UseMvc(routes =>


+ 31
- 0
src/Web/WebMVC/ViewComponents/Cart.cs View File

@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.WebMVC.Models;
using Microsoft.eShopOnContainers.WebMVC.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.WebMVC.ViewComponents
{
public class Cart : ViewComponent
{
private readonly IOrderingService _cartSvc;
public Cart(IOrderingService cartSvc)
{
_cartSvc = cartSvc;
}
public async Task<IViewComponentResult> InvokeAsync(ApplicationUser user)
{
var itemsInCart = await ItemsInCartAsync(user);
return View(itemsInCart);
}
private Task<int> ItemsInCartAsync(ApplicationUser user)
{
_cartSvc.GetActiveOrder(user);
return Task.Run ( ()=> { return _cartSvc.ItemsInCart; });
}
}
}

+ 6
- 6
src/Web/WebMVC/ViewComponents/CartList.cs View File

@ -10,21 +10,21 @@ namespace Microsoft.eShopOnContainers.WebMVC.ViewComponents
{ {
public class CartList : ViewComponent public class CartList : ViewComponent
{ {
private readonly ICartService _cartSvc;
private readonly IOrderingService _cartSvc;
public CartList(ICartService cartSvc)
public CartList(IOrderingService cartSvc)
{ {
_cartSvc = cartSvc; _cartSvc = cartSvc;
} }
public async Task<IViewComponentResult> InvokeAsync()
public async Task<IViewComponentResult> InvokeAsync(ApplicationUser user)
{ {
var item = await GetItemsAsync();
var item = await GetItemsAsync(user);
return View(item); return View(item);
} }
private Task<Order> GetItemsAsync()
private Task<Order> GetItemsAsync(ApplicationUser user)
{ {
return _cartSvc.GetActiveOrder();
return Task.Run(()=> { return _cartSvc.GetActiveOrder(user); });
} }
} }
} }

+ 1
- 1
src/Web/WebMVC/Views/Catalog/Index.cshtml View File

@ -63,7 +63,7 @@
<div class="col-sm-4 home-catalog-item"> <div class="col-sm-4 home-catalog-item">
<div class="home-catalog-item-image" > <div class="home-catalog-item-image" >
<img src="@catalogItem.PicsUrl" /> <img src="@catalogItem.PicsUrl" />
<a asp-area="" asp-controller="Home" asp-action="About" class="btn-brand home-catalog-item-image-addCart">
<a asp-area="" asp-controller="Order" asp-action="AddToCart" asp-route-productId="@catalogItem.Id" class="btn-brand home-catalog-item-image-addCart">
ADD TO CART ADD TO CART
</a> </a>
</div> </div>


+ 3
- 2
src/Web/WebMVC/Views/Order/Cart.cshtml View File

@ -1,4 +1,5 @@
@model Microsoft.eShopOnContainers.WebMVC.Models.Order @model Microsoft.eShopOnContainers.WebMVC.Models.Order
@inject UserManager<ApplicationUser> UserManager
@{ @{
ViewData["Title"] = "My Cart"; ViewData["Title"] = "My Cart";
@ -17,7 +18,7 @@
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th>
<th class="cart-product-column">
PRODUCT PRODUCT
</th> </th>
<th> <th>
@ -38,7 +39,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@await Component.InvokeAsync("CartList")
@await Component.InvokeAsync("CartList", new { user = await UserManager.GetUserAsync(User) })
</tbody> </tbody>
</table> </table>
</section> </section>


+ 9
- 2
src/Web/WebMVC/Views/Shared/Components/Cart/Default.cshtml View File

@ -1,10 +1,17 @@
@model Microsoft.eShopOnContainers.WebMVC.Models.Order
@model System.Int32
@{ @{
ViewData["Title"] = "My Cart"; ViewData["Title"] = "My Cart";
} }
<a asp-area="" asp-controller="Order" asp-action="Cart"><img src="~/images/cart.PNG" class="layout-cart-image hidden-xs"></a>
<div>
<a asp-area="" asp-controller="Order" asp-action="Cart"><img src="~/images/cart.PNG" class="fr layout-cart-image hidden-xs" />
</a>
<div class="layout-cart-badge">
@Model
</div>
</div>

+ 2
- 2
src/Web/WebMVC/Views/Shared/Components/CartList/Default.cshtml View File

@ -7,12 +7,12 @@
@foreach (var item in Model.OrderItems) @foreach (var item in Model.OrderItems)
{ {
<tr> <tr>
<td>@*image*@</td>
<td class="cart-product-column"><img class="cart-product-image"src="@item.PicsUrl" /></td>
<td>@item.ProductName</td> <td>@item.ProductName</td>
<td>ROSLYN</td> <td>ROSLYN</td>
<td>$&nbsp;@item.UnitPrice</td> <td>$&nbsp;@item.UnitPrice</td>
<td>@item.Quantity</td> <td>@item.Quantity</td>
<td>$&nbsp;@item.Quantity * @item.UnitPrice</td>
<td>$&nbsp;@(item.Quantity * item.UnitPrice)</td>
</tr> </tr>
} }


+ 9
- 10
src/Web/WebMVC/Views/Shared/_LoginPartial.cshtml View File

@ -7,15 +7,15 @@
@if (SignInManager.IsSignedIn(User)) @if (SignInManager.IsSignedIn(User))
{ {
<form asp-area="" asp-controller="Account" asp-action="LogOff" method="post" id="logoutForm" class="navbar-right"> <form asp-area="" asp-controller="Account" asp-action="LogOff" method="post" id="logoutForm" class="navbar-right">
<ul class="nav navbar-nav navbar-right">
<li style="float:right"><a asp-area="" asp-controller="Order" asp-action="Cart"><img src="~/images/cart.PNG" class="layout-cart-image hidden-xs"></a></li>
<li class="fr login-user"><a asp-area="" asp-controller="Manage" asp-action="Index" title="Manage">@UserManager.GetUserName(User)</a></li>
@*<li class="fr"><a href="javascript:document.getElementById('logoutForm').submit()" class="btn-login">&nbsp;Log Out&nbsp;</a></li>*@
</ul>
<div class=".login-user-dropdown-content">
<a href="#">Link 1</a>
<a href="#">Link 2</a>
<a href="#">Link 3</a>
<div class="nav navbar-nav navbar-right mt-15">
@await Component.InvokeAsync("Cart", new { user = await UserManager.GetUserAsync(User) })
<div class="fr login-user">
<span>@UserManager.GetUserName(User)<i class="down-arrow"></i></span>
<div class="login-user-dropdown-content">
<a href="#">MY ORDERS<i class="myorders-icon"></i></a>
<a href="javascript:document.getElementById('logoutForm').submit()">LOG OUT<i class="logout-icon"></i></a>
</div>
</div>
</div> </div>
</form> </form>
} }
@ -23,6 +23,5 @@ else
{ {
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li><a asp-area="" asp-controller="Account" class="btn-login" asp-action="Login">&nbsp;Log In&nbsp;</a></li> <li><a asp-area="" asp-controller="Account" class="btn-login" asp-action="Login">&nbsp;Log In&nbsp;</a></li>
@*<li><a asp-area="" asp-controller="Order" asp-action="Cart"><img src="~/images/cart.PNG" class="layout-cart-image hidden-xs"></a></li>*@
</ul> </ul>
} }

+ 1
- 0
src/Web/WebMVC/project.json View File

@ -10,6 +10,7 @@
"Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "1.0.0", "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "1.0.0",
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0", "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.0", "Microsoft.AspNetCore.Mvc": "1.0.0",
"Microsoft.AspNetCore.Session": "1.0.0",
"Microsoft.AspNetCore.Razor.Tools": { "Microsoft.AspNetCore.Razor.Tools": {
"version": "1.0.0-preview2-final", "version": "1.0.0-preview2-final",
"type": "build" "type": "build"


+ 64
- 2
src/Web/WebMVC/wwwroot/css/site.css View File

@ -16,6 +16,10 @@ body {
font-family: Montserrat,sans-serif; font-family: Montserrat,sans-serif;
} }
.mt-15 {
margin-top:15px;
}
/* Wrapping element */ /* Wrapping element */
/* Set some basic padding to keep content from hitting the edges */ /* Set some basic padding to keep content from hitting the edges */
.body-content { .body-content {
@ -93,6 +97,20 @@ select::-ms-expand {
margin-top: 5px; margin-top: 5px;
} }
.layout-cart-badge {
position: absolute;
margin-top: 2px;
margin-left: 14px;
background-color: #83d01b;
padding: 1px;
color: white;
border-radius: 50%;
width: 18px;
height: 18px;
font-size: 13px;
cursor: pointer;
}
/* buttons and links extension to use brackets: [ click me ] */ /* buttons and links extension to use brackets: [ click me ] */
.btn-bracketed:hover:before { .btn-bracketed:hover:before {
display: inline-block; display: inline-block;
@ -491,6 +509,14 @@ form .col-md-4 {
padding-top: 40px; padding-top: 40px;
} }
.cart-product-column {
max-width: 120px;
}
.cart-product-image {
max-width: 210px;
}
.input-validation-error { .input-validation-error {
border: 1px solid #fb0d0d; border: 1px solid #fb0d0d;
} }
@ -529,10 +555,35 @@ form .col-md-4 {
float:right!important; float:right!important;
} }
.down-arrow {
background-image: url('../images/arrow-down.png');
height: 7px;
width: 10px;
display: inline-block;
margin-left: 20px;
}
.logout-icon {
background-image: url('../images/logout.PNG');
display: inline-block;
height:19px;
width:19px;
margin-left: 15px;
}
.myorders-icon {
background-image: url('../images/my_orders.PNG');
display: inline-block;
height: 20px;
width: 20px;
margin-left: 15px;
}
.login-user { .login-user {
position: absolute!important; position: absolute!important;
top: 15px;
top: 30px;
right: 65px; right: 65px;
cursor:pointer;
} }
.login-user-dropdown { .login-user-dropdown {
@ -543,9 +594,10 @@ form .col-md-4 {
.login-user-dropdown-content { .login-user-dropdown-content {
display: none; display: none;
position: absolute; position: absolute;
background-color: #f9f9f9;
background-color: #FFFFFF;
min-width: 160px; min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
left: 100px;
} }
.login-user-dropdown-content a { .login-user-dropdown-content a {
@ -553,6 +605,16 @@ form .col-md-4 {
padding: 12px 16px; padding: 12px 16px;
text-decoration: none; text-decoration: none;
display: block; display: block;
text-align:right;
text-transform:uppercase;
}
.login-user:hover .login-user-dropdown-content {
display: block;
}
.login-user-dropdown-content a:hover {
color: #f1f1f1;
} }
.es-header { .es-header {


BIN
src/Web/WebMVC/wwwroot/images/logout.PNG View File

Before After
Width: 23  |  Height: 25  |  Size: 429 B

BIN
src/Web/WebMVC/wwwroot/images/my_orders.PNG View File

Before After
Width: 27  |  Height: 27  |  Size: 221 B

Loading…
Cancel
Save