Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"inputs": [],
"servers": {
"MS Docs": {
"type": "sse",
"url": "https://learn.microsoft.com/api/mcp",
"headers": {}
},
"Playwright": {
"type": "stdio",
"command": "npx",
"args": [
"@playwright/mcp@latest"
],
"env": {}
}
}
}
2 changes: 1 addition & 1 deletion src/HybridApp/Components/Layout/FooterBar.razor
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<footer class='eshop-footer'>
<div class='eshop-footer-content'>
<div class='eshop-footer-row'>
<img src='images/logo-footer.svg' class='logo logo-footer' />
<img src='@Assets["images/logo-footer.svg"]' class='logo logo-footer' />
<p>© AdventureWorks</p>
</div>
</div>
Expand Down
10 changes: 5 additions & 5 deletions src/WebApp/Components/App.razor
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="css/normalize.css" />
<link rel="stylesheet" href="css/app.css" />
<link rel="stylesheet" href="WebApp.styles.css" />
<link rel="shortcut icon" href="images/favicon.png" />
<link rel="stylesheet" href="@Assets["css/normalize.css"]" />
<link rel="stylesheet" href="@Assets["css/app.css"]" />
<link rel="stylesheet" href="@Assets["WebApp.styles.css"]" />
<link rel="shortcut icon" href="@Assets["images/favicon.png"]" />
<HeadOutlet />
</head>

<body>
<Routes />
<script src="_framework/blazor.web.js"></script>
<script src="@Assets["_framework/blazor.web.js"]"></script>
</body>

</html>
2 changes: 1 addition & 1 deletion src/WebApp/Components/Layout/CartMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@implements IDisposable

<a aria-label="cart" href="cart">
<img role="presentation" src="icons/cart.svg" />
<img role="presentation" src='@Assets["icons/cart.svg"]' />
@if (basketItems?.Count > 0)
{
<span class="cart-badge">@TotalQuantity</span>
Expand Down
2 changes: 1 addition & 1 deletion src/WebApp/Components/Layout/FooterBar.razor
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<footer class='eshop-footer'>
<div class='eshop-footer-content'>
<div class='eshop-footer-row'>
<img role="presentation" src='images/logo-footer.svg' class='logo logo-footer' />
<img role="presentation" src='@Assets["images/logo-footer.svg"]' class='logo logo-footer' />
<p>© AdventureWorks</p>
</div>
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/WebApp/Components/Layout/HeaderBar.razor
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

<div class="eshop-header @(IsCatalog? "home" : "")">
<div class="eshop-header-hero">
@{
var headerImage = IsCatalog ? "images/header-home.webp" : "images/header.webp";
@{
var headerImage = IsCatalog ? "images/header-home.webp" : "images/header.webp";
}
<img role="presentation" src="@headerImage" />
<img role="presentation" src='@Assets[headerImage]' />
</div>
<div class="eshop-header-container">
<nav class="eshop-header-navbar">
<a class="logo logo-header" href="">
<img alt="AdventureWorks" src="images/logo-header.svg" class="logo logo-header" />
<img alt="AdventureWorks" src='@Assets["images/logo-header.svg"]' class="logo logo-header" />
</a>

<UserMenu />
Expand Down
4 changes: 2 additions & 2 deletions src/WebApp/Components/Layout/UserMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<Authorized>
<h3>@context.User.Identity?.Name</h3>
<div class="dropdown-menu">
<span class="dropdown-button"><img role="presentation" src="icons/user.svg" /></span>
<span class="dropdown-button"><img role="presentation" src='@Assets["icons/user.svg"]' /></span>
<div class="dropdown-content">
<a class="dropdown-item" href="user/orders">My orders</a>
<form class="dropdown-item" method="post" action="user/logout" @formname="logout" @onsubmit="LogOutAsync">
Expand All @@ -20,7 +20,7 @@
</div>
</Authorized>
<NotAuthorized>
<a aria-label="Sign in" href="@Pages.User.LogIn.Url(Nav)"><img role="presentation" src="icons/user.svg" /></a>
<a aria-label="Sign in" href="@Pages.User.LogIn.Url(Nav)"><img role="presentation" src='@Assets["icons/user.svg"]' /></a>
</NotAuthorized>
</AuthorizeView>

Expand Down
4 changes: 2 additions & 2 deletions src/WebApp/Components/Pages/Cart/CartPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
<div class="cart-summary">
<div class="cart-summary-container">
<div class="cart-summary-header">
<img role="presentation" src="icons/cart.svg" />
<img role="presentation" src='@Assets["icons/cart.svg"]' />
Your shopping bag
<span class="filter-badge">@TotalQuantity</span>
</div>
Expand All @@ -72,7 +72,7 @@
</div>
<a href="checkout" class="button button-primary">Check out</a>
<a href="" class="cart-summary-link">
<img role="presentation" src="icons/arrow-left.svg" />
<img role="presentation" src='@Assets["icons/arrow-left.svg"]' />
<p>Continue shopping</p>
</a>
</div>
Expand Down
34 changes: 32 additions & 2 deletions src/WebApp/Components/Pages/Checkout/Checkout.razor
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,38 @@
</label>
</div>
</div>
<div class="form-section">
<h2>Payment information</h2>
<label>
Card number
<InputText @bind-Value="@Info.PaymentCard!.CardNumber" />
<ValidationMessage For="@(() => Info.PaymentCard!.CardNumber)" />
</label>
<label>
Cardholder name
<InputText @bind-Value="@Info.PaymentCard!.CardHolderName" />
<ValidationMessage For="@(() => Info.PaymentCard!.CardHolderName)" />
</label>
<div class="form-group">
<div class="form-group-item">
<label>
Expiration date
<InputDate @bind-Value="@Info.PaymentCard!.CardExpiration" />
<ValidationMessage For="@(() => Info.PaymentCard!.CardExpiration)" />
</label>
</div>
<div class="form-group-item">
<label>
Security code (CVV)
<InputText @bind-Value="@Info.PaymentCard!.CardSecurityNumber" />
<ValidationMessage For="@(() => Info.PaymentCard!.CardSecurityNumber)" />
</label>
</div>
</div>
</div>
<div class="form-section">
<div class="form-buttons">
<a href="cart" class="button button-secondary"><img role="presentation" src="icons/arrow-left.svg" />Back to the shopping bag</a>
<a href="cart" class="button button-secondary"><img role="presentation" src='@Assets["icons/arrow-left.svg"]' />Back to the shopping bag</a>
<button class="button button-primary" type="submit">Place order</button>
</div>
</div>
Expand Down Expand Up @@ -91,6 +120,7 @@
State = ReadClaim("address_state"),
Country = ReadClaim("address_country"),
ZipCode = ReadClaim("address_zip_code"),
PaymentCard = new PaymentCardInfo(),
RequestId = Guid.NewGuid()
};

Expand All @@ -110,7 +140,7 @@

private async Task HandleValidSubmitAsync()
{
Info.CardTypeId = 1;
Info.PaymentCard!.CardTypeId = 1;
await Basket.CheckoutAsync(Info);
Nav.NavigateTo("user/orders");
}
Expand Down
40 changes: 40 additions & 0 deletions src/WebApp/Components/Pages/NotFound.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
@page "/not-found"

<PageTitle>Not Found</PageTitle>

<div class="not-found-container">
<h1>404 - Page Not Found</h1>
<p>Sorry, the page you are looking for could not be found.</p>
<p><a href="/">Return to Home</a></p>
</div>

<style>
.not-found-container {
text-align: center;
padding: 4rem 2rem;
max-width: 600px;
margin: 0 auto;
}

.not-found-container h1 {
font-size: 2.5rem;
margin-bottom: 1rem;
color: var(--text-color, #333);
}

.not-found-container p {
font-size: 1.125rem;
margin-bottom: 1rem;
color: var(--text-muted, #666);
}

.not-found-container a {
color: var(--primary-color, #0066cc);
text-decoration: none;
font-weight: 500;
}

.not-found-container a:hover {
text-decoration: underline;
}
</style>
2 changes: 1 addition & 1 deletion src/WebApp/Components/Routes.razor
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Router AppAssembly="@typeof(Program).Assembly">
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
Expand Down
6 changes: 5 additions & 1 deletion src/WebApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

builder.Services.AddRazorComponents().AddInteractiveServerComponents();

builder.Services.AddValidation();

builder.AddApplicationServices();

var app = builder.Build();
Expand All @@ -21,11 +23,13 @@
app.UseHsts();
}

app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);

app.UseAntiforgery();

app.UseHttpsRedirection();

app.UseStaticFiles();
app.MapStaticAssets();

app.MapRazorComponents<App>().AddInteractiveServerRenderMode();

Expand Down
14 changes: 5 additions & 9 deletions src/WebApp/Services/BasketCheckoutInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace eShop.WebApp.Services;

#pragma warning disable ASP0029 // Microsoft.Extensions.Validation is experimental
[Microsoft.Extensions.Validation.ValidatableType]
#pragma warning restore ASP0029
public class BasketCheckoutInfo
{
[Required]
Expand All @@ -19,15 +22,8 @@ public class BasketCheckoutInfo
[Required]
public string? ZipCode { get; set; }

public string? CardNumber { get; set; }

public string? CardHolderName { get; set; }

public string? CardSecurityNumber { get; set; }

public DateTime? CardExpiration { get; set; }

public int CardTypeId { get; set; }
[Required]
public PaymentCardInfo? PaymentCard { get; set; }

public string? Buyer { get; set; }
public Guid RequestId { get; set; }
Expand Down
10 changes: 5 additions & 5 deletions src/WebApp/Services/BasketState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ public async Task CheckoutAsync(BasketCheckoutInfo checkoutInfo)
State: checkoutInfo.State!,
Country: checkoutInfo.Country!,
ZipCode: checkoutInfo.ZipCode!,
CardNumber: "1111222233334444",
CardHolderName: "TESTUSER",
CardExpiration: DateTime.UtcNow.AddYears(1),
CardSecurityNumber: "111",
CardTypeId: checkoutInfo.CardTypeId,
CardNumber: checkoutInfo.PaymentCard!.CardNumber!,
CardHolderName: checkoutInfo.PaymentCard!.CardHolderName!,
CardExpiration: checkoutInfo.PaymentCard!.CardExpiration!.Value,
CardSecurityNumber: checkoutInfo.PaymentCard!.CardSecurityNumber!,
CardTypeId: checkoutInfo.PaymentCard!.CardTypeId,
Buyer: buyerId,
Items: [.. orderItems]);
await orderingService.CreateOrder(request, checkoutInfo.RequestId);
Expand Down
46 changes: 46 additions & 0 deletions src/WebApp/Services/PaymentCardInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.ComponentModel.DataAnnotations;

namespace eShop.WebApp.Services;

#pragma warning disable ASP0029 // Microsoft.Extensions.Validation is experimental
[Microsoft.Extensions.Validation.ValidatableType]
#pragma warning restore ASP0029
public class PaymentCardInfo
{
[Required]
[StringLength(19, MinimumLength = 13)]
[RegularExpression(@"^\d{13,19}$")]
public string? CardNumber { get; set; }

[Required]
[StringLength(100, MinimumLength = 2)]
public string? CardHolderName { get; set; }

[Required]
[RegularExpression(@"^\d{3,4}$")]
public string? CardSecurityNumber { get; set; }

[Required]
[DataType(DataType.Date)]
[FutureDate]
public DateTime? CardExpiration { get; set; }

[Required]
[Range(1, int.MaxValue)]
public int CardTypeId { get; set; }
}

public class FutureDateAttribute : ValidationAttribute
{
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
if (value is DateTime date)
{
if (date <= DateTime.UtcNow)
{
return new ValidationResult(ErrorMessage ?? "The field must be a date in the future.");
}
}
return ValidationResult.Success;
}
}
2 changes: 1 addition & 1 deletion src/WebAppComponents/Catalog/CatalogSearch.razor
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{
<div class="catalog-search">
<div class="catalog-search-header">
<img role="presentation" src="icons/filters.svg" />
<img role="presentation" src='@Assets["icons/filters.svg"]' />
Filters
</div>
<div class="catalog-search-types">
Expand Down
6 changes: 3 additions & 3 deletions src/WebhookClient/Components/App.razor
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="WebhookClient.styles.css" />
<link rel="stylesheet" href="@Assets["app.css"]" />
<link rel="stylesheet" href="@Assets["WebhookClient.styles.css"]" />
<HeadOutlet @rendermode="InteractiveServer" />
</head>

<body>
<Routes @rendermode="InteractiveServer" />
<script src="_framework/blazor.web.js"></script>
<script src="@Assets["_framework/blazor.web.js"]"></script>
</body>

</html>