Adding Razor Pages Version (#60)
* In progress copying code into new RP project Cleaning up namespaces and whitespace in original Web project * Cleaning up some more namespaces * Removing unused page. * Index page loads correctly. * Fixing up paging. * Moving views; getting ready to convert to RPs * Auto stash before merge of "master" and "origin/master" Basket and Checkout pages wired up * WIP on Account pages * Working on signin/signout * Working on auth * Getting order history working Fixing auth bug * Fixing Checkout issue * Fixing link
This commit is contained in:
54
src/WebRazorPages/Pages/Account/Register.cshtml
Normal file
54
src/WebRazorPages/Pages/Account/Register.cshtml
Normal file
@@ -0,0 +1,54 @@
|
||||
@page
|
||||
@model RegisterModel
|
||||
@{
|
||||
ViewData["Title"] = "Register";
|
||||
}
|
||||
<div class="brand-header-block">
|
||||
<ul class="container">
|
||||
<li class="active" style="margin-right: 65px;">Already have an account?
|
||||
<a asp-page="/Account/Signin">LOGIN</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="container account-login-container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<section>
|
||||
<form asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="UserDetails.Email" class="col-md-2 control-label"></label>
|
||||
<div class="col-md-10">
|
||||
<input asp-for="UserDetails.Email" class="form-control" />
|
||||
<span asp-validation-for="UserDetails.Email" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="UserDetails.Password" class="col-md-2 control-label"></label>
|
||||
<div class="col-md-10">
|
||||
<input asp-for="UserDetails.Password" class="form-control" />
|
||||
<span asp-validation-for="UserDetails.Password" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="UserDetails.ConfirmPassword" class="col-md-2 control-label"></label>
|
||||
<div class="col-md-10">
|
||||
<input asp-for="UserDetails.ConfirmPassword" class="form-control" />
|
||||
<span asp-validation-for="UserDetails.ConfirmPassword" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-default btn-brand btn-brand-big"> REGISTER </button>
|
||||
</div>
|
||||
<p>
|
||||
Note that for demo purposes you don't need to register! Use the credentials shown below the
|
||||
<a asp-action="signin">login screen</a>.
|
||||
</p>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||
}
|
||||
53
src/WebRazorPages/Pages/Account/Register.cshtml.cs
Normal file
53
src/WebRazorPages/Pages/Account/Register.cshtml.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.eShopWeb.RazorPages.ViewModels;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Infrastructure.Identity;
|
||||
|
||||
namespace Microsoft.eShopWeb.RazorPages.Pages.Account
|
||||
{
|
||||
public class RegisterModel : PageModel
|
||||
{
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
|
||||
public RegisterModel(SignInManager<ApplicationUser> signInManager,
|
||||
UserManager<ApplicationUser> userManager
|
||||
)
|
||||
{
|
||||
_signInManager = signInManager;
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public RegisterViewModel UserDetails { get; set; }
|
||||
|
||||
|
||||
public async Task<IActionResult> OnPost(string returnUrl = "/Index")
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var user = new ApplicationUser { UserName = UserDetails.Email, Email = UserDetails.Email };
|
||||
var result = await _userManager.CreateAsync(user, UserDetails.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
await _signInManager.SignInAsync(user, isPersistent: false);
|
||||
return LocalRedirect(returnUrl);
|
||||
}
|
||||
AddErrors(result);
|
||||
}
|
||||
return Page();
|
||||
|
||||
}
|
||||
|
||||
private void AddErrors(IdentityResult result)
|
||||
{
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
ModelState.AddModelError("", error.Description);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
64
src/WebRazorPages/Pages/Account/Signin.cshtml
Normal file
64
src/WebRazorPages/Pages/Account/Signin.cshtml
Normal file
@@ -0,0 +1,64 @@
|
||||
@page
|
||||
@using System.Collections.Generic
|
||||
@using Microsoft.AspNetCore.Http
|
||||
@using Microsoft.AspNetCore.Http.Authentication
|
||||
@model SigninModel
|
||||
@{
|
||||
ViewData["Title"] = "Log in";
|
||||
}
|
||||
<div class="brand-header-block">
|
||||
<ul class="container">
|
||||
@*<li><a asp-area="" asp-controller="Account" asp-action="Register">REGISTER</a></li>*@
|
||||
<li class="active" style="margin-right: 65px;">LOGIN</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="container account-login-container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<section>
|
||||
<form asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal">
|
||||
<h4>ARE YOU REGISTERED?</h4>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="LoginDetails.Email" class="control-label form-label"></label>
|
||||
<input asp-for="LoginDetails.Email" class="form-control form-input form-input-center" />
|
||||
<span asp-validation-for="LoginDetails.Email" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="LoginDetails.Password" class="control-label form-label"></label>
|
||||
<input asp-for="LoginDetails.Password" class="form-control form-input form-input-center" />
|
||||
<span asp-validation-for="LoginDetails.Password" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label asp-for="LoginDetails.RememberMe">
|
||||
<input asp-for="LoginDetails.RememberMe" />
|
||||
@Html.DisplayNameFor(m => m.LoginDetails.RememberMe)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-default btn-brand btn-brand-big"> LOG IN </button>
|
||||
</div>
|
||||
<p>
|
||||
<a asp-page="/Account/Register"
|
||||
asp-route-returnurl="@ViewData["ReturnUrl"]" class="text">Register as a new user?</a>
|
||||
</p>
|
||||
<p>
|
||||
Note that for demo purposes you don't need to register and can login with these credentials:
|
||||
</p>
|
||||
<p>
|
||||
User: <b>demouser@microsoft.com</b>
|
||||
</p>
|
||||
<p>
|
||||
Password: <b>Pass@word1</b>
|
||||
</p>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||
}
|
||||
80
src/WebRazorPages/Pages/Account/Signin.cshtml.cs
Normal file
80
src/WebRazorPages/Pages/Account/Signin.cshtml.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.eShopWeb.RazorPages.ViewModels;
|
||||
using Microsoft.eShopWeb.RazorPages.Interfaces;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Infrastructure.Identity;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Microsoft.eShopWeb.RazorPages.Pages.Account
|
||||
{
|
||||
public class SigninModel : PageModel
|
||||
{
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private readonly IBasketService _basketService;
|
||||
|
||||
public SigninModel(SignInManager<ApplicationUser> signInManager,
|
||||
IBasketService basketService)
|
||||
{
|
||||
_signInManager = signInManager;
|
||||
_basketService = basketService;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public LoginViewModel LoginDetails { get; set; } = new LoginViewModel();
|
||||
|
||||
public class LoginViewModel
|
||||
{
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
public string Email { get; set; }
|
||||
|
||||
[Required]
|
||||
[DataType(DataType.Password)]
|
||||
public string Password { get; set; }
|
||||
|
||||
[Display(Name = "Remember me?")]
|
||||
public bool RememberMe { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public async Task OnGet(string returnUrl = null)
|
||||
{
|
||||
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
|
||||
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
if (!String.IsNullOrEmpty(returnUrl) &&
|
||||
returnUrl.IndexOf("checkout", StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
{
|
||||
ViewData["ReturnUrl"] = "/Basket/Index";
|
||||
}
|
||||
}
|
||||
public async Task<IActionResult> OnPost(string returnUrl = null)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return Page();
|
||||
}
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
|
||||
var result = await _signInManager.PasswordSignInAsync(LoginDetails.Email,
|
||||
LoginDetails.Password, LoginDetails.RememberMe, lockoutOnFailure: false);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
string anonymousBasketId = Request.Cookies[Constants.BASKET_COOKIENAME];
|
||||
if (!String.IsNullOrEmpty(anonymousBasketId))
|
||||
{
|
||||
await _basketService.TransferBasketAsync(anonymousBasketId, LoginDetails.Email);
|
||||
Response.Cookies.Delete(Constants.BASKET_COOKIENAME);
|
||||
}
|
||||
return RedirectToPage(returnUrl ?? "/Index");
|
||||
}
|
||||
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
}
|
||||
6
src/WebRazorPages/Pages/Account/Signout.cshtml
Normal file
6
src/WebRazorPages/Pages/Account/Signout.cshtml
Normal file
@@ -0,0 +1,6 @@
|
||||
@page
|
||||
@model SignoutModel
|
||||
@{
|
||||
ViewData["Title"] = "Signing out";
|
||||
}
|
||||
<h2>Signing out...</h2>
|
||||
32
src/WebRazorPages/Pages/Account/Signout.cshtml.cs
Normal file
32
src/WebRazorPages/Pages/Account/Signout.cshtml.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Infrastructure.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Microsoft.eShopWeb.RazorPages.Pages.Account
|
||||
{
|
||||
public class SignoutModel : PageModel
|
||||
{
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
|
||||
public SignoutModel(SignInManager<ApplicationUser> signInManager)
|
||||
{
|
||||
_signInManager = signInManager;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnGet()
|
||||
{
|
||||
await _signInManager.SignOutAsync();
|
||||
|
||||
return RedirectToPage("/Index");
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPost()
|
||||
{
|
||||
await _signInManager.SignOutAsync();
|
||||
|
||||
return RedirectToPage("/Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/WebRazorPages/Pages/Basket/CheckoutComplete.cshtml
Normal file
15
src/WebRazorPages/Pages/Basket/CheckoutComplete.cshtml
Normal file
@@ -0,0 +1,15 @@
|
||||
@page
|
||||
@{
|
||||
ViewData["Title"] = "Checkout Complete";
|
||||
}
|
||||
<section class="esh-catalog-hero">
|
||||
<div class="container">
|
||||
<img class="esh-catalog-title" src="../images/main_banner_text.png" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="container">
|
||||
<h1>Thanks for your Order!</h1>
|
||||
|
||||
<a asp-page="/Index">Continue Shopping...</a>
|
||||
</div>
|
||||
86
src/WebRazorPages/Pages/Basket/Index.cshtml
Normal file
86
src/WebRazorPages/Pages/Basket/Index.cshtml
Normal file
@@ -0,0 +1,86 @@
|
||||
@page "{handler?}"
|
||||
@model IndexModel
|
||||
@{
|
||||
ViewData["Title"] = "Basket";
|
||||
}
|
||||
<section class="esh-catalog-hero">
|
||||
<div class="container">
|
||||
<img class="esh-catalog-title" src="../images/main_banner_text.png" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="container">
|
||||
|
||||
@if (Model.BasketModel.Items.Any())
|
||||
{
|
||||
<form method="post">
|
||||
<article class="esh-basket-titles row">
|
||||
<br />
|
||||
<section class="esh-basket-title col-xs-3">Product</section>
|
||||
<section class="esh-basket-title col-xs-3 hidden-lg-down"></section>
|
||||
<section class="esh-basket-title col-xs-2">Price</section>
|
||||
<section class="esh-basket-title col-xs-2">Quantity</section>
|
||||
<section class="esh-basket-title col-xs-2">Cost</section>
|
||||
</article>
|
||||
<div class="esh-catalog-items row">
|
||||
@for (int i=0; i< Model.BasketModel.Items.Count; i++)
|
||||
{
|
||||
var item = Model.BasketModel.Items[i];
|
||||
<article class="esh-basket-items row">
|
||||
<div>
|
||||
<section class="esh-basket-item esh-basket-item--middle col-lg-3 hidden-lg-down">
|
||||
<img class="esh-basket-image" src="@item.PictureUrl" />
|
||||
</section>
|
||||
<section class="esh-basket-item esh-basket-item--middle col-xs-3">@item.ProductName</section>
|
||||
<section class="esh-basket-item esh-basket-item--middle col-xs-2">$ @item.UnitPrice.ToString("N2")</section>
|
||||
<section class="esh-basket-item esh-basket-item--middle col-xs-2">
|
||||
<input type="hidden" name="@("Items[" + i + "].Key")" value="@item.Id" />
|
||||
<input type="number" class="esh-basket-input" min="1" name="@("Items[" + i + "].Value")" value="@item.Quantity" />
|
||||
</section>
|
||||
<section class="esh-basket-item esh-basket-item--middle esh-basket-item--mark col-xs-2">$ @Math.Round(item.Quantity * item.UnitPrice, 2).ToString("N2")</section>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</article>
|
||||
@*<div class="esh-catalog-item col-md-4">
|
||||
@item.ProductId
|
||||
</div>*@
|
||||
|
||||
<div class="container">
|
||||
<article class="esh-basket-titles esh-basket-titles--clean row">
|
||||
<section class="esh-basket-title col-xs-10"></section>
|
||||
<section class="esh-basket-title col-xs-2">Total</section>
|
||||
</article>
|
||||
|
||||
<article class="esh-basket-items row">
|
||||
<section class="esh-basket-item col-xs-10"></section>
|
||||
<section class="esh-basket-item esh-basket-item--mark col-xs-2">$ @Model.BasketModel.Total()</section>
|
||||
</article>
|
||||
|
||||
<article class="esh-basket-items row">
|
||||
<section class="esh-basket-item col-xs-7"></section>
|
||||
<section class="esh-basket-item col-xs-2">
|
||||
@*<button class="btn esh-basket-checkout" name="name" value="" type="submit">[ Update ]</button>*@
|
||||
</section>
|
||||
</article>
|
||||
</div>
|
||||
}
|
||||
<section class="esh-basket-item col-xs-push-8 col-xs-4">
|
||||
<button class="btn esh-basket-checkout" name="updatebutton" value="" type="submit"
|
||||
asp-page-handler="Update">[ Update ]</button>
|
||||
<input type="submit" asp-page-handler="Checkout"
|
||||
class="btn esh-basket-checkout"
|
||||
value="[ Checkout ]" name="action" />
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="esh-catalog-items row">
|
||||
Basket is empty.
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
109
src/WebRazorPages/Pages/Basket/Index.cshtml.cs
Normal file
109
src/WebRazorPages/Pages/Basket/Index.cshtml.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.eShopWeb.RazorPages.ViewModels;
|
||||
using Microsoft.eShopWeb.RazorPages.Interfaces;
|
||||
using ApplicationCore.Interfaces;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Infrastructure.Identity;
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.Collections.Generic;
|
||||
using ApplicationCore.Entities.OrderAggregate;
|
||||
|
||||
namespace Microsoft.eShopWeb.RazorPages.Pages.Basket
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
private readonly IBasketService _basketService;
|
||||
private const string _basketSessionKey = "basketId";
|
||||
private readonly IUriComposer _uriComposer;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private readonly IAppLogger<IndexModel> _logger;
|
||||
private readonly IOrderService _orderService;
|
||||
private string _username = null;
|
||||
|
||||
public IndexModel(IBasketService basketService,
|
||||
IUriComposer uriComposer,
|
||||
SignInManager<ApplicationUser> signInManager,
|
||||
IAppLogger<IndexModel> logger,
|
||||
IOrderService orderService)
|
||||
{
|
||||
_basketService = basketService;
|
||||
_uriComposer = uriComposer;
|
||||
_signInManager = signInManager;
|
||||
_logger = logger;
|
||||
_orderService = orderService;
|
||||
}
|
||||
|
||||
public BasketViewModel BasketModel { get; set; } = new BasketViewModel();
|
||||
|
||||
public async Task OnGet()
|
||||
{
|
||||
await SetBasketModelAsync();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPost(CatalogItemViewModel productDetails)
|
||||
{
|
||||
if (productDetails?.Id == null)
|
||||
{
|
||||
return RedirectToPage("/Index");
|
||||
}
|
||||
await SetBasketModelAsync();
|
||||
|
||||
await _basketService.AddItemToBasket(BasketModel.Id, productDetails.Id, productDetails.Price, 1);
|
||||
|
||||
await SetBasketModelAsync();
|
||||
|
||||
return RedirectToPage();
|
||||
}
|
||||
|
||||
public async Task OnPostUpdate(Dictionary<string,int> items)
|
||||
{
|
||||
await SetBasketModelAsync();
|
||||
await _basketService.SetQuantities(BasketModel.Id, items);
|
||||
|
||||
await SetBasketModelAsync();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostCheckout(Dictionary<string,int> items)
|
||||
{
|
||||
await SetBasketModelAsync();
|
||||
|
||||
await _basketService.SetQuantities(BasketModel.Id, items);
|
||||
|
||||
await _orderService.CreateOrderAsync(BasketModel.Id, new Address("123 Main St.", "Kent", "OH", "United States", "44240"));
|
||||
|
||||
await _basketService.DeleteBasketAsync(BasketModel.Id);
|
||||
|
||||
return RedirectToPage("/Basket/CheckoutComplete");
|
||||
}
|
||||
|
||||
private async Task SetBasketModelAsync()
|
||||
{
|
||||
if (_signInManager.IsSignedIn(HttpContext.User))
|
||||
{
|
||||
BasketModel = await _basketService.GetOrCreateBasketForUser(User.Identity.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetOrSetBasketCookieAndUserName();
|
||||
BasketModel = await _basketService.GetOrCreateBasketForUser(_username);
|
||||
}
|
||||
}
|
||||
|
||||
private void GetOrSetBasketCookieAndUserName()
|
||||
{
|
||||
if (Request.Cookies.ContainsKey(Constants.BASKET_COOKIENAME))
|
||||
{
|
||||
_username = Request.Cookies[Constants.BASKET_COOKIENAME];
|
||||
}
|
||||
if (_username != null) return;
|
||||
|
||||
_username = Guid.NewGuid().ToString();
|
||||
var cookieOptions = new CookieOptions();
|
||||
cookieOptions.Expires = DateTime.Today.AddYears(10);
|
||||
Response.Cookies.Append(Constants.BASKET_COOKIENAME, _username, cookieOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/WebRazorPages/Pages/Components/Basket/Default.cshtml
Normal file
15
src/WebRazorPages/Pages/Components/Basket/Default.cshtml
Normal file
@@ -0,0 +1,15 @@
|
||||
@model BasketComponentViewModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "My Basket";
|
||||
}
|
||||
|
||||
<a class="esh-basketstatus "
|
||||
asp-page="/Basket/Index">
|
||||
<div class="esh-basketstatus-image">
|
||||
<img src="~/images/cart.png" />
|
||||
</div>
|
||||
<div class="esh-basketstatus-badge">
|
||||
@Model.ItemsCount
|
||||
</div>
|
||||
</a>
|
||||
23
src/WebRazorPages/Pages/Error.cshtml
Normal file
23
src/WebRazorPages/Pages/Error.cshtml
Normal file
@@ -0,0 +1,23 @@
|
||||
@page
|
||||
@model ErrorModel
|
||||
@{
|
||||
ViewData["Title"] = "Error";
|
||||
}
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (Model.ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
|
||||
</p>
|
||||
17
src/WebRazorPages/Pages/Error.cshtml.cs
Normal file
17
src/WebRazorPages/Pages/Error.cshtml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace Microsoft.eShopWeb.RazorPages.Pages
|
||||
{
|
||||
public class ErrorModel : PageModel
|
||||
{
|
||||
public string RequestId { get; set; }
|
||||
|
||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
public void OnGet()
|
||||
{
|
||||
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
49
src/WebRazorPages/Pages/Index.cshtml
Normal file
49
src/WebRazorPages/Pages/Index.cshtml
Normal file
@@ -0,0 +1,49 @@
|
||||
@page "{pageId?}"
|
||||
@{
|
||||
ViewData["Title"] = "Catalog";
|
||||
@model IndexModel
|
||||
}
|
||||
<section class="esh-catalog-hero">
|
||||
<div class="container">
|
||||
<img class="esh-catalog-title" src="../images/main_banner_text.png" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="esh-catalog-filters">
|
||||
<div class="container">
|
||||
<form method="get">
|
||||
<label class="esh-catalog-label" data-title="brand">
|
||||
<select asp-for="@Model.CatalogModel.BrandFilterApplied" asp-items="@Model.CatalogModel.Brands" class="esh-catalog-filter"></select>
|
||||
</label>
|
||||
<label class="esh-catalog-label" data-title="type">
|
||||
<select asp-for="@Model.CatalogModel.TypesFilterApplied" asp-items="@Model.CatalogModel.Types" class="esh-catalog-filter"></select>
|
||||
</label>
|
||||
<input class="esh-catalog-send" type="image" src="images/arrow-right.svg" />
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="container">
|
||||
|
||||
@if (Model.CatalogModel.CatalogItems.Any())
|
||||
{
|
||||
@Html.Partial("_pagination", Model.CatalogModel.PaginationInfo)
|
||||
|
||||
<div class="esh-catalog-items row">
|
||||
@foreach (var catalogItem in Model.CatalogModel.CatalogItems)
|
||||
{
|
||||
<div class="esh-catalog-item col-md-4">
|
||||
@Html.Partial("_product", catalogItem)
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@Html.Partial("_pagination", Model.CatalogModel.PaginationInfo)
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="esh-catalog-items row">
|
||||
THERE ARE NO RESULTS THAT MATCH YOUR SEARCH
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
25
src/WebRazorPages/Pages/Index.cshtml.cs
Normal file
25
src/WebRazorPages/Pages/Index.cshtml.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.eShopWeb.RazorPages.ViewModels;
|
||||
using Microsoft.eShopWeb.RazorPages.Interfaces;
|
||||
|
||||
namespace Microsoft.eShopWeb.RazorPages.Pages
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
private readonly ICatalogService _catalogService;
|
||||
|
||||
public IndexModel(ICatalogService catalogService)
|
||||
{
|
||||
_catalogService = catalogService;
|
||||
}
|
||||
|
||||
public CatalogIndexViewModel CatalogModel { get; set; } = new CatalogIndexViewModel();
|
||||
|
||||
public async Task OnGet(CatalogIndexViewModel catalogModel, int? pageId)
|
||||
{
|
||||
CatalogModel = await _catalogService.GetCatalogItems(pageId ?? 0, Constants.ITEMS_PER_PAGE, catalogModel.BrandFilterApplied, catalogModel.TypesFilterApplied);
|
||||
}
|
||||
}
|
||||
}
|
||||
88
src/WebRazorPages/Pages/Order/Detail.cshtml
Normal file
88
src/WebRazorPages/Pages/Order/Detail.cshtml
Normal file
@@ -0,0 +1,88 @@
|
||||
@page
|
||||
@model DetailModel
|
||||
@{
|
||||
ViewData["Title"] = "My Order History";
|
||||
}
|
||||
@{
|
||||
ViewData["Title"] = "Order Detail";
|
||||
}
|
||||
|
||||
<div class="esh-orders_detail">
|
||||
<div class="container">
|
||||
<section class="esh-orders_detail-section">
|
||||
<article class="esh-orders_detail-titles row">
|
||||
<section class="esh-orders_detail-title col-xs-3">Order number</section>
|
||||
<section class="esh-orders_detail-title col-xs-3">Date</section>
|
||||
<section class="esh-orders_detail-title col-xs-3">Total</section>
|
||||
<section class="esh-orders_detail-title col-xs-3">Status</section>
|
||||
</article>
|
||||
|
||||
<article class="esh-orders_detail-items row">
|
||||
<section class="esh-orders_detail-item col-xs-3">@Model.OrderDetails.OrderNumber</section>
|
||||
<section class="esh-orders_detail-item col-xs-3">@Model.OrderDetails.OrderDate</section>
|
||||
<section class="esh-orders_detail-item col-xs-3">$@Model.OrderDetails.Total</section>
|
||||
<section class="esh-orders_detail-title col-xs-3">@Model.OrderDetails.Status</section>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
@*<section class="esh-orders_detail-section">
|
||||
<article class="esh-orders_detail-titles row">
|
||||
<section class="esh-orders_detail-title col-xs-12">Description</section>
|
||||
</article>
|
||||
|
||||
<article class="esh-orders_detail-items row">
|
||||
<section class="esh-orders_detail-item col-xs-12">@Model.Description</section>
|
||||
</article>
|
||||
</section>*@
|
||||
|
||||
<section class="esh-orders_detail-section">
|
||||
<article class="esh-orders_detail-titles row">
|
||||
<section class="esh-orders_detail-title col-xs-12">Shipping Address</section>
|
||||
</article>
|
||||
|
||||
<article class="esh-orders_detail-items row">
|
||||
<section class="esh-orders_detail-item col-xs-12">@Model.OrderDetails.ShippingAddress.Street</section>
|
||||
</article>
|
||||
|
||||
<article class="esh-orders_detail-items row">
|
||||
<section class="esh-orders_detail-item col-xs-12">@Model.OrderDetails.ShippingAddress.City</section>
|
||||
</article>
|
||||
|
||||
<article class="esh-orders_detail-items row">
|
||||
<section class="esh-orders_detail-item col-xs-12">@Model.OrderDetails.ShippingAddress.Country</section>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="esh-orders_detail-section">
|
||||
<article class="esh-orders_detail-titles row">
|
||||
<section class="esh-orders_detail-title col-xs-12">ORDER DETAILS</section>
|
||||
</article>
|
||||
|
||||
@for (int i = 0; i < Model.OrderDetails.OrderItems.Count; i++)
|
||||
{
|
||||
var item = Model.OrderDetails.OrderItems[i];
|
||||
<article class="esh-orders_detail-items esh-orders_detail-items--border row">
|
||||
<section class="esh-orders_detail-item col-md-4 hidden-md-down">
|
||||
<img class="esh-orders_detail-image" src="@item.PictureUrl">
|
||||
</section>
|
||||
<section class="esh-orders_detail-item esh-orders_detail-item--middle col-xs-4">@item.ProductName</section>
|
||||
<section class="esh-orders_detail-item esh-orders_detail-item--middle col-xs-1">$ @item.UnitPrice.ToString("N2")</section>
|
||||
<section class="esh-orders_detail-item esh-orders_detail-item--middle col-xs-1">@item.Units</section>
|
||||
<section class="esh-orders_detail-item esh-orders_detail-item--middle col-xs-2">$ @Math.Round(item.Units * item.UnitPrice, 2).ToString("N2")</section>
|
||||
</article>
|
||||
}
|
||||
</section>
|
||||
|
||||
<section class="esh-orders_detail-section esh-orders_detail-section--right">
|
||||
<article class="esh-orders_detail-titles esh-basket-titles--clean row">
|
||||
<section class="esh-orders_detail-title col-xs-9"></section>
|
||||
<section class="esh-orders_detail-title col-xs-2">TOTAL</section>
|
||||
</article>
|
||||
|
||||
<article class="esh-orders_detail-items row">
|
||||
<section class="esh-orders_detail-item col-xs-9"></section>
|
||||
<section class="esh-orders_detail-item esh-orders_detail-item--mark col-xs-2">$ @Model.OrderDetails.Total</section>
|
||||
</article>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
43
src/WebRazorPages/Pages/Order/Detail.cshtml.cs
Normal file
43
src/WebRazorPages/Pages/Order/Detail.cshtml.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.eShopWeb.RazorPages.ViewModels;
|
||||
using ApplicationCore.Interfaces;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.eShopWeb.RazorPages.Pages.Order
|
||||
{
|
||||
public class DetailModel : PageModel
|
||||
{
|
||||
private readonly IOrderRepository _orderRepository;
|
||||
|
||||
public DetailModel(IOrderRepository orderRepository)
|
||||
{
|
||||
_orderRepository = orderRepository;
|
||||
}
|
||||
|
||||
public OrderViewModel OrderDetails { get; set; } = new OrderViewModel();
|
||||
|
||||
|
||||
public async Task OnGet(int orderId)
|
||||
{
|
||||
var order = await _orderRepository.GetByIdWithItemsAsync(orderId);
|
||||
OrderDetails = new OrderViewModel()
|
||||
{
|
||||
OrderDate = order.OrderDate,
|
||||
OrderItems = order.OrderItems.Select(oi => new OrderItemViewModel()
|
||||
{
|
||||
Discount = 0,
|
||||
PictureUrl = oi.ItemOrdered.PictureUri,
|
||||
ProductId = oi.ItemOrdered.CatalogItemId,
|
||||
ProductName = oi.ItemOrdered.ProductName,
|
||||
UnitPrice = oi.UnitPrice,
|
||||
Units = oi.Units
|
||||
}).ToList(),
|
||||
OrderNumber = order.Id,
|
||||
ShippingAddress = order.ShipToAddress,
|
||||
Status = "Pending",
|
||||
Total = order.Total()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/WebRazorPages/Pages/Order/Index.cshtml
Normal file
40
src/WebRazorPages/Pages/Order/Index.cshtml
Normal file
@@ -0,0 +1,40 @@
|
||||
@page
|
||||
@using System.Linq;
|
||||
@model IndexModel
|
||||
@{
|
||||
ViewData["Title"] = "My Order History";
|
||||
}
|
||||
|
||||
<div class="esh-orders">
|
||||
<div class="container">
|
||||
<h1>@ViewData["Title"]</h1>
|
||||
<article class="esh-orders-titles row">
|
||||
<section class="esh-orders-title col-xs-2">Order number</section>
|
||||
<section class="esh-orders-title col-xs-4">Date</section>
|
||||
<section class="esh-orders-title col-xs-2">Total</section>
|
||||
<section class="esh-orders-title col-xs-2">Status</section>
|
||||
<section class="esh-orders-title col-xs-2"></section>
|
||||
</article>
|
||||
@if (Model.Orders != null && Model.Orders.Any())
|
||||
{
|
||||
@foreach (var item in Model.Orders)
|
||||
{
|
||||
<article class="esh-orders-items row">
|
||||
<section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.OrderNumber)</section>
|
||||
<section class="esh-orders-item col-xs-4">@Html.DisplayFor(modelItem => item.OrderDate)</section>
|
||||
<section class="esh-orders-item col-xs-2">$ @Html.DisplayFor(modelItem => item.Total)</section>
|
||||
<section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.Status)</section>
|
||||
<section class="esh-orders-item col-xs-1">
|
||||
<a class="esh-orders-link" asp-page="Detail" asp-route-orderId="@item.OrderNumber">Detail</a>
|
||||
</section>
|
||||
<section class="esh-orders-item col-xs-1">
|
||||
@if (item.Status.ToLower() == "submitted")
|
||||
{
|
||||
<a class="esh-orders-link" asp-page="Cancel" asp-route-orderId="@item.OrderNumber">Cancel</a>
|
||||
}
|
||||
</section>
|
||||
</article>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
48
src/WebRazorPages/Pages/Order/Index.cshtml.cs
Normal file
48
src/WebRazorPages/Pages/Order/Index.cshtml.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.eShopWeb.RazorPages.ViewModels;
|
||||
using ApplicationCore.Interfaces;
|
||||
using ApplicationCore.Specifications;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.eShopWeb.RazorPages.Pages.Order
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
private readonly IOrderRepository _orderRepository;
|
||||
|
||||
public IndexModel(IOrderRepository orderRepository)
|
||||
{
|
||||
_orderRepository = orderRepository;
|
||||
}
|
||||
|
||||
public List<OrderViewModel> Orders { get; set; } = new List<OrderViewModel>();
|
||||
|
||||
|
||||
public async Task OnGet()
|
||||
{
|
||||
var orders = await _orderRepository.ListAsync(new CustomerOrdersWithItemsSpecification(User.Identity.Name));
|
||||
|
||||
Orders = orders
|
||||
.Select(o => new OrderViewModel()
|
||||
{
|
||||
OrderDate = o.OrderDate,
|
||||
OrderItems = o.OrderItems?.Select(oi => new OrderItemViewModel()
|
||||
{
|
||||
Discount = 0,
|
||||
PictureUrl = oi.ItemOrdered.PictureUri,
|
||||
ProductId = oi.ItemOrdered.CatalogItemId,
|
||||
ProductName = oi.ItemOrdered.ProductName,
|
||||
UnitPrice = oi.UnitPrice,
|
||||
Units = oi.Units
|
||||
}).ToList(),
|
||||
OrderNumber = o.Id,
|
||||
ShippingAddress = o.ShipToAddress,
|
||||
Status = "Pending",
|
||||
Total = o.Total()
|
||||
|
||||
}).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
76
src/WebRazorPages/Pages/_Layout.cshtml
Normal file
76
src/WebRazorPages/Pages/_Layout.cshtml
Normal file
@@ -0,0 +1,76 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@ViewData["Title"] - Microsoft.eShopOnWeb</title>
|
||||
|
||||
<environment names="Development">
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
|
||||
<link rel="stylesheet" href="~/css/app.css" />
|
||||
</environment>
|
||||
<environment names="Staging,Production">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"
|
||||
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
|
||||
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
|
||||
<link rel="stylesheet" href="~/css/app.min.css" asp-append-version="true" />
|
||||
</environment>
|
||||
<link rel="stylesheet" href="~/css/app.component.css" />
|
||||
<link rel="stylesheet" href="~/css/basket/basket.component.css" />
|
||||
<link rel="stylesheet" href="~/css/catalog/pager.css" />
|
||||
<link rel="stylesheet" href="~/css/catalog/catalog.component.css" />
|
||||
<link rel="stylesheet" href="~/css/basket/basket-status/basket-status.component.css" />
|
||||
<link rel="stylesheet" href="~/css/orders/orders.component.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header class="navbar navbar-light navbar-static-top">
|
||||
<div class="container">
|
||||
<article class="row">
|
||||
|
||||
<section class="col-lg-7 col-md-6 col-xs-12">
|
||||
<a asp-page="/Index" class="navbar-brand">
|
||||
<img src="../images/brand.png" alt="eShop On Web" />
|
||||
</a>
|
||||
</section>
|
||||
@await Html.PartialAsync("_LoginPartial")
|
||||
</article>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@RenderBody()
|
||||
|
||||
|
||||
<footer class="esh-app-footer">
|
||||
<div class="container">
|
||||
<article class="row">
|
||||
|
||||
<section class="col-sm-6"></section>
|
||||
|
||||
<section class="col-sm-6">
|
||||
<div class="esh-app-footer-text hidden-xs"> e-ShopOnWeb. All rights reserved </div>
|
||||
</section>
|
||||
|
||||
</article>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<environment names="Development">
|
||||
<script src="~/lib/jquery/dist/jquery.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
</environment>
|
||||
<environment names="Staging,Production">
|
||||
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
|
||||
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
|
||||
asp-fallback-test="window.jQuery">
|
||||
</script>
|
||||
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/bootstrap.min.js"
|
||||
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal">
|
||||
</script>
|
||||
<script src="~/js/site.min.js" asp-append-version="true"></script>
|
||||
</environment>
|
||||
|
||||
@RenderSection("scripts", required: false)
|
||||
</body>
|
||||
</html>
|
||||
55
src/WebRazorPages/Pages/_LoginPartial.cshtml
Normal file
55
src/WebRazorPages/Pages/_LoginPartial.cshtml
Normal file
@@ -0,0 +1,55 @@
|
||||
@using Microsoft.AspNetCore.Identity
|
||||
|
||||
@if (Context.User.Identity.IsAuthenticated)
|
||||
{
|
||||
<section class="col-lg-4 col-md-5 col-xs-12">
|
||||
<div class="esh-identity">
|
||||
<form asp-page="/Account/Signout" method="post"
|
||||
id="logoutForm" class="navbar-right">
|
||||
<section class="esh-identity-section">
|
||||
@*<div class="esh-identity-name">@User.FindFirst(x => x.Type == "preferred_username").Value</div>*@
|
||||
<img class="esh-identity-image" src="~/images/arrow-down.png">
|
||||
</section>
|
||||
|
||||
<section class="esh-identity-drop">
|
||||
<a class="esh-identity-item"
|
||||
asp-page="/Order/Index">
|
||||
|
||||
<div class="esh-identity-name esh-identity-name--upper">My orders</div>
|
||||
<img class="esh-identity-image" src="~/images/my_orders.png">
|
||||
</a>
|
||||
|
||||
<a class="esh-identity-item"
|
||||
href="javascript:document.getElementById('logoutForm').submit()">
|
||||
<div class="esh-identity-name esh-identity-name--upper">Log Out</div>
|
||||
<img class="esh-identity-image" src="~/images/logout.png">
|
||||
</a>
|
||||
</section>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="col-lg-1 col-xs-12">
|
||||
@await Component.InvokeAsync("Basket", User.Identity.Name)
|
||||
</section>
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
<section class="col-lg-1 col-lg-offset-3 col-md-3 col-xs-6">
|
||||
<div class="esh-identity">
|
||||
<section class="esh-identity-section">
|
||||
<div class="esh-identity-item">
|
||||
|
||||
<a asp-page="/Account/Signin" class="esh-identity-name esh-identity-name--upper">
|
||||
Login
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="col-lg-1 col-xs-12">
|
||||
@await Component.InvokeAsync("Basket")
|
||||
</section>
|
||||
}
|
||||
18
src/WebRazorPages/Pages/_ValidationScriptsPartial.cshtml
Normal file
18
src/WebRazorPages/Pages/_ValidationScriptsPartial.cshtml
Normal file
@@ -0,0 +1,18 @@
|
||||
<environment include="Development">
|
||||
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"
|
||||
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-Fnqn3nxp3506LP/7Y3j/25BlWeA3PXTyT1l78LjECcPaKCV12TsZP7yyMxOe/G/k">
|
||||
</script>
|
||||
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"
|
||||
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-JrXK+k53HACyavUKOsL+NkmSesD2P+73eDMrbTtTk0h4RmOF8hF8apPlkp26JlyH">
|
||||
</script>
|
||||
</environment>
|
||||
4
src/WebRazorPages/Pages/_ViewImports.cshtml
Normal file
4
src/WebRazorPages/Pages/_ViewImports.cshtml
Normal file
@@ -0,0 +1,4 @@
|
||||
@using Microsoft.eShopWeb.RazorPages
|
||||
@using Microsoft.eShopWeb.RazorPages.ViewModels
|
||||
@namespace Microsoft.eShopWeb.RazorPages.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
3
src/WebRazorPages/Pages/_ViewStart.cshtml
Normal file
3
src/WebRazorPages/Pages/_ViewStart.cshtml
Normal file
@@ -0,0 +1,3 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
34
src/WebRazorPages/Pages/_pagination.cshtml
Normal file
34
src/WebRazorPages/Pages/_pagination.cshtml
Normal file
@@ -0,0 +1,34 @@
|
||||
@model PaginationInfoViewModel
|
||||
|
||||
<div class="esh-pager">
|
||||
<div class="container-fluid">
|
||||
<article class="esh-pager-wrapper row">
|
||||
<nav>
|
||||
<div class="col-md-2 col-xs-12">
|
||||
<a class="esh-pager-item-left esh-pager-item--navigable @Model.Previous"
|
||||
id="Previous"
|
||||
asp-route-pageid="@(Model.ActualPage - 1)"
|
||||
aria-label="Previous">
|
||||
Previous
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8 col-xs-12">
|
||||
<span class="esh-pager-item">
|
||||
Showing @Model.ItemsPerPage of @Model.TotalItems products - Page @(Model.ActualPage + 1) - @Model.TotalPages
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-md-2 col-xs-12">
|
||||
<a class="esh-pager-item-right esh-pager-item--navigable @Model.Next"
|
||||
id="Next"
|
||||
asp-route-pageid="@(Model.ActualPage + 1)"
|
||||
aria-label="Next">
|
||||
Next
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
24
src/WebRazorPages/Pages/_product.cshtml
Normal file
24
src/WebRazorPages/Pages/_product.cshtml
Normal file
@@ -0,0 +1,24 @@
|
||||
@model CatalogItemViewModel
|
||||
|
||||
|
||||
<form asp-page="/Basket/Index" method="post">
|
||||
|
||||
<img class="esh-catalog-thumbnail" src="@Model.PictureUri" />
|
||||
<input class="esh-catalog-button" type="submit" value="[ ADD TO BASKET ]" />
|
||||
|
||||
<div class="esh-catalog-name">
|
||||
<span>@Model.Name</span>
|
||||
</div>
|
||||
<div class="esh-catalog-price">
|
||||
<span>@Model.Price.ToString("N2")</span>
|
||||
</div>
|
||||
@*<input type="hidden" asp-for="@Model.CatalogBrand" name="brand" />
|
||||
<input type="hidden" asp-for="@Model.CatalogBrandId" name="brandId" />
|
||||
<input type="hidden" asp-for="@Model.CatalogType" name="type" />
|
||||
<input type="hidden" asp-for="@Model.CatalogTypeId" name="typeId" />
|
||||
<input type="hidden" asp-for="@Model.Description" name="description" />*@
|
||||
<input type="hidden" asp-for="@Model.Id" name="id" />
|
||||
<input type="hidden" asp-for="@Model.Name" name="name" />
|
||||
<input type="hidden" asp-for="@Model.PictureUri" name="pictureUri" />
|
||||
<input type="hidden" asp-for="@Model.Price" name="price" />
|
||||
</form>
|
||||
Reference in New Issue
Block a user