├── .devcontainer ├── Dockerfile ├── devcontainer.json └── library-scripts │ └── azcli-debian.sh ├── .editorconfig ├── .gitignore ├── Directory.Build.props ├── LICENSE ├── README.md ├── THIRD-PARTY-NOTICES.md ├── docs ├── 00-get-started.md ├── 01-HomeScreen.md ├── 02-managing-state.md ├── 03-validation.md ├── 04-authentication.md └── 05-components.md ├── notes ├── outline.md └── speaker-notes.md ├── nuget.config ├── save-points ├── 0-Start │ ├── BlazingPizza.Client │ │ ├── BlazingPizza.Client.csproj │ │ ├── Program.cs │ │ └── _Imports.razor │ ├── BlazingPizza.ComponentsLibrary │ │ ├── BlazingPizza.ComponentsLibrary.csproj │ │ ├── LocalStorage.cs │ │ ├── Map │ │ │ ├── Map.razor │ │ │ ├── Marker.cs │ │ │ └── Point.cs │ │ ├── _Imports.razor │ │ └── wwwroot │ │ │ ├── deliveryMap.js │ │ │ ├── leaflet │ │ │ ├── images │ │ │ │ ├── layers-2x.png │ │ │ │ ├── layers.png │ │ │ │ ├── marker-icon-2x.png │ │ │ │ ├── marker-icon.png │ │ │ │ └── marker-shadow.png │ │ │ ├── leaflet.css │ │ │ └── leaflet.js │ │ │ ├── localStorage.js │ │ │ └── pushNotifications.js │ ├── BlazingPizza.Shared │ │ ├── Address.cs │ │ ├── BlazingPizza.Shared.csproj │ │ ├── IRepository.cs │ │ ├── LatLong.cs │ │ ├── NotificationSubscription.cs │ │ ├── Order.cs │ │ ├── OrderWithStatus.cs │ │ ├── Pizza.cs │ │ ├── PizzaSpecial.cs │ │ ├── PizzaTopping.cs │ │ ├── Topping.cs │ │ └── UserInfo.cs │ ├── BlazingPizza.sln │ └── BlazingPizza │ │ ├── BlazingPizza.csproj │ │ ├── Components │ │ ├── App.razor │ │ ├── Layout │ │ │ ├── MainLayout.razor │ │ │ └── MainLayout.razor.css │ │ ├── Pages │ │ │ ├── Error.razor │ │ │ └── Home.razor │ │ ├── Routes.razor │ │ └── _Imports.razor │ │ ├── EfRepository.cs │ │ ├── OrdersController.cs │ │ ├── PizzaApiExtensions.cs │ │ ├── PizzaStoreContext.cs │ │ ├── PizzaStoreUser.cs │ │ ├── Program.cs │ │ ├── SeedData.cs │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ └── wwwroot │ │ ├── css │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── font │ │ │ ├── quicksand-v8-latin-300.woff │ │ │ ├── quicksand-v8-latin-300.woff2 │ │ │ ├── quicksand-v8-latin-500.woff │ │ │ ├── quicksand-v8-latin-500.woff2 │ │ │ ├── quicksand-v8-latin-700.woff │ │ │ ├── quicksand-v8-latin-700.woff2 │ │ │ ├── quicksand-v8-latin-regular.woff │ │ │ ├── quicksand-v8-latin-regular.woff2 │ │ │ └── quicksand.css │ │ └── site.css │ │ ├── img │ │ ├── bike.svg │ │ ├── icon-512.png │ │ ├── logo.svg │ │ ├── pizza-slice.svg │ │ ├── pizzas │ │ │ ├── bacon.jpg │ │ │ ├── brit.jpg │ │ │ ├── cheese.jpg │ │ │ ├── margherita.jpg │ │ │ ├── meaty.jpg │ │ │ ├── mushroom.jpg │ │ │ ├── pepperoni.jpg │ │ │ └── salad.jpg │ │ └── user.svg │ │ └── index.html ├── 1-HomeScreen │ ├── BlazingPizza.Client │ │ ├── BlazingPizza.Client.csproj │ │ ├── ConfigurePizzaDialog.razor │ │ ├── ConfiguredPizzaItem.razor │ │ ├── Home.razor │ │ ├── HttpRepository.cs │ │ ├── Program.cs │ │ └── _Imports.razor │ ├── BlazingPizza.ComponentsLibrary │ │ ├── BlazingPizza.ComponentsLibrary.csproj │ │ ├── LocalStorage.cs │ │ ├── Map │ │ │ ├── Map.razor │ │ │ ├── Marker.cs │ │ │ └── Point.cs │ │ ├── _Imports.razor │ │ └── wwwroot │ │ │ ├── deliveryMap.js │ │ │ ├── leaflet │ │ │ ├── images │ │ │ │ ├── layers-2x.png │ │ │ │ ├── layers.png │ │ │ │ ├── marker-icon-2x.png │ │ │ │ ├── marker-icon.png │ │ │ │ └── marker-shadow.png │ │ │ ├── leaflet.css │ │ │ └── leaflet.js │ │ │ ├── localStorage.js │ │ │ └── pushNotifications.js │ ├── BlazingPizza.Shared │ │ ├── Address.cs │ │ ├── BlazingPizza.Shared.csproj │ │ ├── IRepository.cs │ │ ├── LatLong.cs │ │ ├── NotificationSubscription.cs │ │ ├── Order.cs │ │ ├── OrderWithStatus.cs │ │ ├── Pizza.cs │ │ ├── PizzaSpecial.cs │ │ ├── PizzaTopping.cs │ │ ├── Topping.cs │ │ └── UserInfo.cs │ ├── BlazingPizza.sln │ └── BlazingPizza │ │ ├── BlazingPizza.csproj │ │ ├── Components │ │ ├── App.razor │ │ ├── Layout │ │ │ ├── MainLayout.razor │ │ │ └── MainLayout.razor.css │ │ ├── Pages │ │ │ └── Error.razor │ │ ├── Routes.razor │ │ └── _Imports.razor │ │ ├── EfRepository.cs │ │ ├── OrdersController.cs │ │ ├── PizzaApiExtensions.cs │ │ ├── PizzaStoreContext.cs │ │ ├── PizzaStoreUser.cs │ │ ├── Program.cs │ │ ├── SeedData.cs │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ └── wwwroot │ │ ├── css │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── font │ │ │ ├── quicksand-v8-latin-300.woff │ │ │ ├── quicksand-v8-latin-300.woff2 │ │ │ ├── quicksand-v8-latin-500.woff │ │ │ ├── quicksand-v8-latin-500.woff2 │ │ │ ├── quicksand-v8-latin-700.woff │ │ │ ├── quicksand-v8-latin-700.woff2 │ │ │ ├── quicksand-v8-latin-regular.woff │ │ │ ├── quicksand-v8-latin-regular.woff2 │ │ │ └── quicksand.css │ │ └── site.css │ │ ├── img │ │ ├── bike.svg │ │ ├── icon-512.png │ │ ├── logo.svg │ │ ├── pizza-slice.svg │ │ ├── pizzas │ │ │ ├── bacon.jpg │ │ │ ├── brit.jpg │ │ │ ├── cheese.jpg │ │ │ ├── margherita.jpg │ │ │ ├── meaty.jpg │ │ │ ├── mushroom.jpg │ │ │ ├── pepperoni.jpg │ │ │ └── salad.jpg │ │ └── user.svg │ │ └── index.html ├── 2-State │ ├── BlazingPizza.Client │ │ ├── BlazingPizza.Client.csproj │ │ ├── Components │ │ │ ├── ConfigurePizzaDialog.razor │ │ │ ├── ConfiguredPizzaItem.razor │ │ │ ├── OrderReview.razor │ │ │ └── Pages │ │ │ │ └── Home.razor │ │ ├── HttpRepository.cs │ │ ├── OrderState.cs │ │ ├── Program.cs │ │ └── _Imports.razor │ ├── BlazingPizza.ComponentsLibrary │ │ ├── BlazingPizza.ComponentsLibrary.csproj │ │ ├── LocalStorage.cs │ │ ├── Map │ │ │ ├── Map.razor │ │ │ ├── Marker.cs │ │ │ └── Point.cs │ │ ├── _Imports.razor │ │ └── wwwroot │ │ │ ├── deliveryMap.js │ │ │ ├── leaflet │ │ │ ├── images │ │ │ │ ├── layers-2x.png │ │ │ │ ├── layers.png │ │ │ │ ├── marker-icon-2x.png │ │ │ │ ├── marker-icon.png │ │ │ │ └── marker-shadow.png │ │ │ ├── leaflet.css │ │ │ └── leaflet.js │ │ │ ├── localStorage.js │ │ │ └── pushNotifications.js │ ├── BlazingPizza.Shared │ │ ├── Address.cs │ │ ├── BlazingPizza.Shared.csproj │ │ ├── IRepository.cs │ │ ├── LatLong.cs │ │ ├── NotificationSubscription.cs │ │ ├── Order.cs │ │ ├── OrderWithStatus.cs │ │ ├── Pizza.cs │ │ ├── PizzaSpecial.cs │ │ ├── PizzaTopping.cs │ │ ├── Topping.cs │ │ └── UserInfo.cs │ ├── BlazingPizza.sln │ └── BlazingPizza │ │ ├── BlazingPizza.csproj │ │ ├── Components │ │ ├── App.razor │ │ ├── Layout │ │ │ ├── MainLayout.razor │ │ │ └── MainLayout.razor.css │ │ ├── Pages │ │ │ ├── Error.razor │ │ │ ├── MyOrders.razor │ │ │ └── OrderDetails.razor │ │ ├── Routes.razor │ │ └── _Imports.razor │ │ ├── EfRepository.cs │ │ ├── OrdersController.cs │ │ ├── PizzaApiExtensions.cs │ │ ├── PizzaStoreContext.cs │ │ ├── PizzaStoreUser.cs │ │ ├── Program.cs │ │ ├── SeedData.cs │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ └── wwwroot │ │ ├── css │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── font │ │ │ ├── quicksand-v8-latin-300.woff │ │ │ ├── quicksand-v8-latin-300.woff2 │ │ │ ├── quicksand-v8-latin-500.woff │ │ │ ├── quicksand-v8-latin-500.woff2 │ │ │ ├── quicksand-v8-latin-700.woff │ │ │ ├── quicksand-v8-latin-700.woff2 │ │ │ ├── quicksand-v8-latin-regular.woff │ │ │ ├── quicksand-v8-latin-regular.woff2 │ │ │ └── quicksand.css │ │ └── site.css │ │ ├── img │ │ ├── bike.svg │ │ ├── icon-512.png │ │ ├── logo.svg │ │ ├── pizza-slice.svg │ │ ├── pizzas │ │ │ ├── bacon.jpg │ │ │ ├── brit.jpg │ │ │ ├── cheese.jpg │ │ │ ├── margherita.jpg │ │ │ ├── meaty.jpg │ │ │ ├── mushroom.jpg │ │ │ ├── pepperoni.jpg │ │ │ └── salad.jpg │ │ └── user.svg │ │ └── index.html ├── 3-Validation │ ├── BlazingPizza.Client │ │ ├── BlazingPizza.Client.csproj │ │ ├── BootstrapFieldClassProvider.cs │ │ ├── Components │ │ │ ├── AddressEditor.razor │ │ │ ├── ConfigurePizzaDialog.razor │ │ │ ├── ConfiguredPizzaItem.razor │ │ │ ├── OrderReview.razor │ │ │ └── Pages │ │ │ │ ├── Checkout.razor │ │ │ │ └── Home.razor │ │ ├── HttpRepository.cs │ │ ├── OrderState.cs │ │ ├── Program.cs │ │ └── _Imports.razor │ ├── BlazingPizza.ComponentsLibrary │ │ ├── BlazingPizza.ComponentsLibrary.csproj │ │ ├── LocalStorage.cs │ │ ├── Map │ │ │ ├── Map.razor │ │ │ ├── Marker.cs │ │ │ └── Point.cs │ │ ├── _Imports.razor │ │ └── wwwroot │ │ │ ├── deliveryMap.js │ │ │ ├── leaflet │ │ │ ├── images │ │ │ │ ├── layers-2x.png │ │ │ │ ├── layers.png │ │ │ │ ├── marker-icon-2x.png │ │ │ │ ├── marker-icon.png │ │ │ │ └── marker-shadow.png │ │ │ ├── leaflet.css │ │ │ └── leaflet.js │ │ │ ├── localStorage.js │ │ │ └── pushNotifications.js │ ├── BlazingPizza.Shared │ │ ├── Address.cs │ │ ├── BlazingPizza.Shared.csproj │ │ ├── IRepository.cs │ │ ├── LatLong.cs │ │ ├── NotificationSubscription.cs │ │ ├── Order.cs │ │ ├── OrderWithStatus.cs │ │ ├── Pizza.cs │ │ ├── PizzaSpecial.cs │ │ ├── PizzaTopping.cs │ │ ├── Topping.cs │ │ └── UserInfo.cs │ ├── BlazingPizza.sln │ └── BlazingPizza │ │ ├── BlazingPizza.csproj │ │ ├── Components │ │ ├── App.razor │ │ ├── Layout │ │ │ ├── MainLayout.razor │ │ │ └── MainLayout.razor.css │ │ ├── Pages │ │ │ ├── Error.razor │ │ │ ├── MyOrders.razor │ │ │ └── OrderDetails.razor │ │ ├── Routes.razor │ │ └── _Imports.razor │ │ ├── EfRepository.cs │ │ ├── OrdersController.cs │ │ ├── PizzaApiExtensions.cs │ │ ├── PizzaStoreContext.cs │ │ ├── PizzaStoreUser.cs │ │ ├── Program.cs │ │ ├── SeedData.cs │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ └── wwwroot │ │ ├── css │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── font │ │ │ ├── quicksand-v8-latin-300.woff │ │ │ ├── quicksand-v8-latin-300.woff2 │ │ │ ├── quicksand-v8-latin-500.woff │ │ │ ├── quicksand-v8-latin-500.woff2 │ │ │ ├── quicksand-v8-latin-700.woff │ │ │ ├── quicksand-v8-latin-700.woff2 │ │ │ ├── quicksand-v8-latin-regular.woff │ │ │ ├── quicksand-v8-latin-regular.woff2 │ │ │ └── quicksand.css │ │ └── site.css │ │ ├── img │ │ ├── bike.svg │ │ ├── icon-512.png │ │ ├── logo.svg │ │ ├── pizza-slice.svg │ │ ├── pizzas │ │ │ ├── bacon.jpg │ │ │ ├── brit.jpg │ │ │ ├── cheese.jpg │ │ │ ├── margherita.jpg │ │ │ ├── meaty.jpg │ │ │ ├── mushroom.jpg │ │ │ ├── pepperoni.jpg │ │ │ └── salad.jpg │ │ └── user.svg │ │ └── index.html ├── 4-Authentication │ ├── BlazingPizza.Client │ │ ├── BlazingPizza.Client.csproj │ │ ├── BootstrapFieldClassProvider.cs │ │ ├── Components │ │ │ ├── AddressEditor.razor │ │ │ ├── ConfigurePizzaDialog.razor │ │ │ ├── ConfiguredPizzaItem.razor │ │ │ ├── OrderReview.razor │ │ │ └── Pages │ │ │ │ ├── Checkout.razor │ │ │ │ └── Home.razor │ │ ├── HttpRepository.cs │ │ ├── OrderState.cs │ │ ├── PersistentAuthenticationStateProvider.cs │ │ ├── Program.cs │ │ ├── UserInfo.cs │ │ └── _Imports.razor │ ├── BlazingPizza.ComponentsLibrary │ │ ├── BlazingPizza.ComponentsLibrary.csproj │ │ ├── LocalStorage.cs │ │ ├── Map │ │ │ ├── Map.razor │ │ │ ├── Marker.cs │ │ │ └── Point.cs │ │ ├── _Imports.razor │ │ └── wwwroot │ │ │ ├── deliveryMap.js │ │ │ ├── leaflet │ │ │ ├── images │ │ │ │ ├── layers-2x.png │ │ │ │ ├── layers.png │ │ │ │ ├── marker-icon-2x.png │ │ │ │ ├── marker-icon.png │ │ │ │ └── marker-shadow.png │ │ │ ├── leaflet.css │ │ │ └── leaflet.js │ │ │ ├── localStorage.js │ │ │ └── pushNotifications.js │ ├── BlazingPizza.Shared │ │ ├── Address.cs │ │ ├── BlazingPizza.Shared.csproj │ │ ├── IRepository.cs │ │ ├── LatLong.cs │ │ ├── NotificationSubscription.cs │ │ ├── Order.cs │ │ ├── OrderWithStatus.cs │ │ ├── Pizza.cs │ │ ├── PizzaSpecial.cs │ │ ├── PizzaTopping.cs │ │ ├── Topping.cs │ │ └── UserInfo.cs │ ├── BlazingPizza.sln │ └── BlazingPizza │ │ ├── BlazingPizza.csproj │ │ ├── Components │ │ ├── Account │ │ │ ├── IdentityComponentsEndpointRouteBuilderExtensions.cs │ │ │ ├── IdentityNoOpEmailSender.cs │ │ │ ├── IdentityRedirectManager.cs │ │ │ ├── IdentityRevalidatingAuthenticationStateProvider.cs │ │ │ ├── IdentityUserAccessor.cs │ │ │ ├── Pages │ │ │ │ ├── AccessDenied.razor │ │ │ │ ├── ConfirmEmail.razor │ │ │ │ ├── ConfirmEmailChange.razor │ │ │ │ ├── ExternalLogin.razor │ │ │ │ ├── ForgotPassword.razor │ │ │ │ ├── ForgotPasswordConfirmation.razor │ │ │ │ ├── InvalidPasswordReset.razor │ │ │ │ ├── InvalidUser.razor │ │ │ │ ├── Lockout.razor │ │ │ │ ├── Login.razor │ │ │ │ ├── LoginWith2fa.razor │ │ │ │ ├── LoginWithRecoveryCode.razor │ │ │ │ ├── Manage │ │ │ │ │ ├── ChangePassword.razor │ │ │ │ │ ├── DeletePersonalData.razor │ │ │ │ │ ├── Disable2fa.razor │ │ │ │ │ ├── Email.razor │ │ │ │ │ ├── EnableAuthenticator.razor │ │ │ │ │ ├── ExternalLogins.razor │ │ │ │ │ ├── GenerateRecoveryCodes.razor │ │ │ │ │ ├── Index.razor │ │ │ │ │ ├── PersonalData.razor │ │ │ │ │ ├── ResetAuthenticator.razor │ │ │ │ │ ├── SetPassword.razor │ │ │ │ │ ├── TwoFactorAuthentication.razor │ │ │ │ │ └── _Imports.razor │ │ │ │ ├── Register.razor │ │ │ │ ├── RegisterConfirmation.razor │ │ │ │ ├── ResendEmailConfirmation.razor │ │ │ │ ├── ResetPassword.razor │ │ │ │ ├── ResetPasswordConfirmation.razor │ │ │ │ └── _Imports.razor │ │ │ └── Shared │ │ │ │ ├── AccountLayout.razor │ │ │ │ ├── ExternalLoginPicker.razor │ │ │ │ ├── ManageLayout.razor │ │ │ │ ├── ManageNavMenu.razor │ │ │ │ ├── RedirectToLogin.razor │ │ │ │ ├── ShowRecoveryCodes.razor │ │ │ │ └── StatusMessage.razor │ │ ├── App.razor │ │ ├── Layout │ │ │ ├── MainLayout.razor │ │ │ └── MainLayout.razor.css │ │ ├── LoginDisplay.razor │ │ ├── Pages │ │ │ ├── Error.razor │ │ │ ├── MyOrders.razor │ │ │ └── OrderDetails.razor │ │ ├── Routes.razor │ │ └── _Imports.razor │ │ ├── EfRepository.cs │ │ ├── OrdersController.cs │ │ ├── PizzaApiExtensions.cs │ │ ├── PizzaStoreContext.cs │ │ ├── PizzaStoreUser.cs │ │ ├── Program.cs │ │ ├── SeedData.cs │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ └── wwwroot │ │ ├── css │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── font │ │ │ ├── quicksand-v8-latin-300.woff │ │ │ ├── quicksand-v8-latin-300.woff2 │ │ │ ├── quicksand-v8-latin-500.woff │ │ │ ├── quicksand-v8-latin-500.woff2 │ │ │ ├── quicksand-v8-latin-700.woff │ │ │ ├── quicksand-v8-latin-700.woff2 │ │ │ ├── quicksand-v8-latin-regular.woff │ │ │ ├── quicksand-v8-latin-regular.woff2 │ │ │ └── quicksand.css │ │ └── site.css │ │ ├── img │ │ ├── bike.svg │ │ ├── icon-512.png │ │ ├── logo.svg │ │ ├── pizza-slice.svg │ │ ├── pizzas │ │ │ ├── bacon.jpg │ │ │ ├── brit.jpg │ │ │ ├── cheese.jpg │ │ │ ├── margherita.jpg │ │ │ ├── meaty.jpg │ │ │ ├── mushroom.jpg │ │ │ ├── pepperoni.jpg │ │ │ └── salad.jpg │ │ └── user.svg │ │ └── index.html ├── 5-Components │ ├── BlazingPizza.Client │ │ ├── BlazingPizza.Client.csproj │ │ ├── BootstrapFieldClassProvider.cs │ │ ├── Components │ │ │ ├── AddressEditor.razor │ │ │ ├── ConfigurePizzaDialog.razor │ │ │ ├── ConfiguredPizzaItem.razor │ │ │ ├── OrderReview.razor │ │ │ └── Pages │ │ │ │ ├── Checkout.razor │ │ │ │ └── Home.razor │ │ ├── HttpRepository.cs │ │ ├── JSRuntimeExtensions.cs │ │ ├── OrderState.cs │ │ ├── PersistentAuthenticationStateProvider.cs │ │ ├── Program.cs │ │ ├── UserInfo.cs │ │ └── _Imports.razor │ ├── BlazingPizza.ComponentsLibrary │ │ ├── BlazingPizza.ComponentsLibrary.csproj │ │ ├── LocalStorage.cs │ │ ├── Map │ │ │ ├── Map.razor │ │ │ ├── Marker.cs │ │ │ └── Point.cs │ │ ├── TemplatedDialog.razor │ │ ├── TemplatedList.razor │ │ ├── _Imports.razor │ │ └── wwwroot │ │ │ ├── deliveryMap.js │ │ │ ├── leaflet │ │ │ ├── images │ │ │ │ ├── layers-2x.png │ │ │ │ ├── layers.png │ │ │ │ ├── marker-icon-2x.png │ │ │ │ ├── marker-icon.png │ │ │ │ └── marker-shadow.png │ │ │ ├── leaflet.css │ │ │ └── leaflet.js │ │ │ ├── localStorage.js │ │ │ └── pushNotifications.js │ ├── BlazingPizza.Shared │ │ ├── Address.cs │ │ ├── BlazingPizza.Shared.csproj │ │ ├── IRepository.cs │ │ ├── LatLong.cs │ │ ├── NotificationSubscription.cs │ │ ├── Order.cs │ │ ├── OrderWithStatus.cs │ │ ├── Pizza.cs │ │ ├── PizzaSpecial.cs │ │ ├── PizzaTopping.cs │ │ ├── Topping.cs │ │ └── UserInfo.cs │ ├── BlazingPizza.sln │ └── BlazingPizza │ │ ├── BlazingPizza.csproj │ │ ├── Components │ │ ├── Account │ │ │ ├── IdentityComponentsEndpointRouteBuilderExtensions.cs │ │ │ ├── IdentityNoOpEmailSender.cs │ │ │ ├── IdentityRedirectManager.cs │ │ │ ├── IdentityRevalidatingAuthenticationStateProvider.cs │ │ │ ├── IdentityUserAccessor.cs │ │ │ ├── Pages │ │ │ │ ├── AccessDenied.razor │ │ │ │ ├── ConfirmEmail.razor │ │ │ │ ├── ConfirmEmailChange.razor │ │ │ │ ├── ExternalLogin.razor │ │ │ │ ├── ForgotPassword.razor │ │ │ │ ├── ForgotPasswordConfirmation.razor │ │ │ │ ├── InvalidPasswordReset.razor │ │ │ │ ├── InvalidUser.razor │ │ │ │ ├── Lockout.razor │ │ │ │ ├── Login.razor │ │ │ │ ├── LoginWith2fa.razor │ │ │ │ ├── LoginWithRecoveryCode.razor │ │ │ │ ├── Manage │ │ │ │ │ ├── ChangePassword.razor │ │ │ │ │ ├── DeletePersonalData.razor │ │ │ │ │ ├── Disable2fa.razor │ │ │ │ │ ├── Email.razor │ │ │ │ │ ├── EnableAuthenticator.razor │ │ │ │ │ ├── ExternalLogins.razor │ │ │ │ │ ├── GenerateRecoveryCodes.razor │ │ │ │ │ ├── Index.razor │ │ │ │ │ ├── PersonalData.razor │ │ │ │ │ ├── ResetAuthenticator.razor │ │ │ │ │ ├── SetPassword.razor │ │ │ │ │ ├── TwoFactorAuthentication.razor │ │ │ │ │ └── _Imports.razor │ │ │ │ ├── Register.razor │ │ │ │ ├── RegisterConfirmation.razor │ │ │ │ ├── ResendEmailConfirmation.razor │ │ │ │ ├── ResetPassword.razor │ │ │ │ ├── ResetPasswordConfirmation.razor │ │ │ │ └── _Imports.razor │ │ │ └── Shared │ │ │ │ ├── AccountLayout.razor │ │ │ │ ├── ExternalLoginPicker.razor │ │ │ │ ├── ManageLayout.razor │ │ │ │ ├── ManageNavMenu.razor │ │ │ │ ├── RedirectToLogin.razor │ │ │ │ ├── ShowRecoveryCodes.razor │ │ │ │ └── StatusMessage.razor │ │ ├── App.razor │ │ ├── Layout │ │ │ ├── MainLayout.razor │ │ │ └── MainLayout.razor.css │ │ ├── LoginDisplay.razor │ │ ├── Pages │ │ │ ├── Error.razor │ │ │ ├── MyOrders.razor │ │ │ └── OrderDetails.razor │ │ ├── Routes.razor │ │ └── _Imports.razor │ │ ├── EfRepository.cs │ │ ├── OrdersController.cs │ │ ├── PizzaApiExtensions.cs │ │ ├── PizzaStoreContext.cs │ │ ├── PizzaStoreUser.cs │ │ ├── Program.cs │ │ ├── SeedData.cs │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ └── wwwroot │ │ ├── css │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── font │ │ │ ├── quicksand-v8-latin-300.woff │ │ │ ├── quicksand-v8-latin-300.woff2 │ │ │ ├── quicksand-v8-latin-500.woff │ │ │ ├── quicksand-v8-latin-500.woff2 │ │ │ ├── quicksand-v8-latin-700.woff │ │ │ ├── quicksand-v8-latin-700.woff2 │ │ │ ├── quicksand-v8-latin-regular.woff │ │ │ ├── quicksand-v8-latin-regular.woff2 │ │ │ └── quicksand.css │ │ └── site.css │ │ ├── img │ │ ├── bike.svg │ │ ├── icon-512.png │ │ ├── logo.svg │ │ ├── pizza-slice.svg │ │ ├── pizzas │ │ │ ├── bacon.jpg │ │ │ ├── brit.jpg │ │ │ ├── cheese.jpg │ │ │ ├── margherita.jpg │ │ │ ├── meaty.jpg │ │ │ ├── mushroom.jpg │ │ │ ├── pepperoni.jpg │ │ │ └── salad.jpg │ │ └── user.svg │ │ └── index.html └── 6-PWA │ ├── BlazingPizza.Client │ ├── BlazingPizza.Client.csproj │ ├── BootstrapFieldClassProvider.cs │ ├── Components │ │ ├── AddressEditor.razor │ │ ├── ConfigurePizzaDialog.razor │ │ ├── ConfiguredPizzaItem.razor │ │ ├── OrderReview.razor │ │ └── Pages │ │ │ ├── Checkout.razor │ │ │ └── Home.razor │ ├── HttpRepository.cs │ ├── JSRuntimeExtensions.cs │ ├── OrderState.cs │ ├── PersistentAuthenticationStateProvider.cs │ ├── Program.cs │ ├── UserInfo.cs │ └── _Imports.razor │ ├── BlazingPizza.ComponentsLibrary │ ├── BlazingPizza.ComponentsLibrary.csproj │ ├── LocalStorage.cs │ ├── Map │ │ ├── Map.razor │ │ ├── Marker.cs │ │ └── Point.cs │ ├── TemplatedDialog.razor │ ├── TemplatedList.razor │ ├── _Imports.razor │ └── wwwroot │ │ ├── deliveryMap.js │ │ ├── leaflet │ │ ├── images │ │ │ ├── layers-2x.png │ │ │ ├── layers.png │ │ │ ├── marker-icon-2x.png │ │ │ ├── marker-icon.png │ │ │ └── marker-shadow.png │ │ ├── leaflet.css │ │ └── leaflet.js │ │ ├── localStorage.js │ │ └── pushNotifications.js │ ├── BlazingPizza.Shared │ ├── Address.cs │ ├── BlazingPizza.Shared.csproj │ ├── IRepository.cs │ ├── LatLong.cs │ ├── NotificationSubscription.cs │ ├── Order.cs │ ├── OrderWithStatus.cs │ ├── Pizza.cs │ ├── PizzaSpecial.cs │ ├── PizzaTopping.cs │ ├── Topping.cs │ └── UserInfo.cs │ ├── BlazingPizza.sln │ └── BlazingPizza │ ├── BlazingPizza.csproj │ ├── Components │ ├── Account │ │ ├── IdentityComponentsEndpointRouteBuilderExtensions.cs │ │ ├── IdentityNoOpEmailSender.cs │ │ ├── IdentityRedirectManager.cs │ │ ├── IdentityRevalidatingAuthenticationStateProvider.cs │ │ ├── IdentityUserAccessor.cs │ │ ├── Pages │ │ │ ├── AccessDenied.razor │ │ │ ├── ConfirmEmail.razor │ │ │ ├── ConfirmEmailChange.razor │ │ │ ├── ExternalLogin.razor │ │ │ ├── ForgotPassword.razor │ │ │ ├── ForgotPasswordConfirmation.razor │ │ │ ├── InvalidPasswordReset.razor │ │ │ ├── InvalidUser.razor │ │ │ ├── Lockout.razor │ │ │ ├── Login.razor │ │ │ ├── LoginWith2fa.razor │ │ │ ├── LoginWithRecoveryCode.razor │ │ │ ├── Manage │ │ │ │ ├── ChangePassword.razor │ │ │ │ ├── DeletePersonalData.razor │ │ │ │ ├── Disable2fa.razor │ │ │ │ ├── Email.razor │ │ │ │ ├── EnableAuthenticator.razor │ │ │ │ ├── ExternalLogins.razor │ │ │ │ ├── GenerateRecoveryCodes.razor │ │ │ │ ├── Index.razor │ │ │ │ ├── PersonalData.razor │ │ │ │ ├── ResetAuthenticator.razor │ │ │ │ ├── SetPassword.razor │ │ │ │ ├── TwoFactorAuthentication.razor │ │ │ │ └── _Imports.razor │ │ │ ├── Register.razor │ │ │ ├── RegisterConfirmation.razor │ │ │ ├── ResendEmailConfirmation.razor │ │ │ ├── ResetPassword.razor │ │ │ ├── ResetPasswordConfirmation.razor │ │ │ └── _Imports.razor │ │ └── Shared │ │ │ ├── AccountLayout.razor │ │ │ ├── ExternalLoginPicker.razor │ │ │ ├── ManageLayout.razor │ │ │ ├── ManageNavMenu.razor │ │ │ ├── RedirectToLogin.razor │ │ │ ├── ShowRecoveryCodes.razor │ │ │ └── StatusMessage.razor │ ├── App.razor │ ├── Layout │ │ ├── MainLayout.razor │ │ └── MainLayout.razor.css │ ├── LoginDisplay.razor │ ├── Pages │ │ ├── Error.razor │ │ ├── MyOrders.razor │ │ └── OrderDetails.razor │ ├── Routes.razor │ └── _Imports.razor │ ├── EfRepository.cs │ ├── OrdersController.cs │ ├── PizzaApiExtensions.cs │ ├── PizzaStoreContext.cs │ ├── PizzaStoreUser.cs │ ├── Program.cs │ ├── SeedData.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── wwwroot │ ├── css │ ├── bootstrap │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── font │ │ ├── quicksand-v8-latin-300.woff │ │ ├── quicksand-v8-latin-300.woff2 │ │ ├── quicksand-v8-latin-500.woff │ │ ├── quicksand-v8-latin-500.woff2 │ │ ├── quicksand-v8-latin-700.woff │ │ ├── quicksand-v8-latin-700.woff2 │ │ ├── quicksand-v8-latin-regular.woff │ │ ├── quicksand-v8-latin-regular.woff2 │ │ └── quicksand.css │ └── site.css │ ├── img │ ├── bike.svg │ ├── icon-512.png │ ├── logo.svg │ ├── pizza-slice.svg │ ├── pizzas │ │ ├── bacon.jpg │ │ ├── brit.jpg │ │ ├── cheese.jpg │ │ ├── margherita.jpg │ │ ├── meaty.jpg │ │ ├── mushroom.jpg │ │ ├── pepperoni.jpg │ │ └── salad.jpg │ └── user.svg │ ├── index.html │ ├── manifest.json │ └── service-worker.js ├── src ├── BlazingPizza.Client │ ├── BlazingPizza.Client.csproj │ ├── BootstrapFieldClassProvider.cs │ ├── Components │ │ ├── AddressEditor.razor │ │ ├── ConfigurePizzaDialog.razor │ │ ├── ConfiguredPizzaItem.razor │ │ ├── OrderReview.razor │ │ └── Pages │ │ │ ├── Checkout.razor │ │ │ └── Home.razor │ ├── HttpRepository.cs │ ├── JSRuntimeExtensions.cs │ ├── OrderState.cs │ ├── PersistentAuthenticationStateProvider.cs │ ├── Program.cs │ ├── UserInfo.cs │ └── _Imports.razor ├── BlazingPizza.ComponentsLibrary │ ├── BlazingPizza.ComponentsLibrary.csproj │ ├── LocalStorage.cs │ ├── Map │ │ ├── Map.razor │ │ ├── Marker.cs │ │ └── Point.cs │ ├── TemplatedDialog.razor │ ├── TemplatedList.razor │ ├── _Imports.razor │ └── wwwroot │ │ ├── deliveryMap.js │ │ ├── leaflet │ │ ├── images │ │ │ ├── layers-2x.png │ │ │ ├── layers.png │ │ │ ├── marker-icon-2x.png │ │ │ ├── marker-icon.png │ │ │ └── marker-shadow.png │ │ ├── leaflet.css │ │ └── leaflet.js │ │ ├── localStorage.js │ │ └── pushNotifications.js ├── BlazingPizza.Shared │ ├── Address.cs │ ├── BlazingPizza.Shared.csproj │ ├── IRepository.cs │ ├── LatLong.cs │ ├── NotificationSubscription.cs │ ├── Order.cs │ ├── OrderWithStatus.cs │ ├── Pizza.cs │ ├── PizzaSpecial.cs │ ├── PizzaTopping.cs │ ├── Topping.cs │ └── UserInfo.cs ├── BlazingPizza.sln └── BlazingPizza │ ├── BlazingPizza.csproj │ ├── Components │ ├── Account │ │ ├── IdentityComponentsEndpointRouteBuilderExtensions.cs │ │ ├── IdentityNoOpEmailSender.cs │ │ ├── IdentityRedirectManager.cs │ │ ├── IdentityRevalidatingAuthenticationStateProvider.cs │ │ ├── IdentityUserAccessor.cs │ │ ├── Pages │ │ │ ├── AccessDenied.razor │ │ │ ├── ConfirmEmail.razor │ │ │ ├── ConfirmEmailChange.razor │ │ │ ├── ExternalLogin.razor │ │ │ ├── ForgotPassword.razor │ │ │ ├── ForgotPasswordConfirmation.razor │ │ │ ├── InvalidPasswordReset.razor │ │ │ ├── InvalidUser.razor │ │ │ ├── Lockout.razor │ │ │ ├── Login.razor │ │ │ ├── LoginWith2fa.razor │ │ │ ├── LoginWithRecoveryCode.razor │ │ │ ├── Manage │ │ │ │ ├── ChangePassword.razor │ │ │ │ ├── DeletePersonalData.razor │ │ │ │ ├── Disable2fa.razor │ │ │ │ ├── Email.razor │ │ │ │ ├── EnableAuthenticator.razor │ │ │ │ ├── ExternalLogins.razor │ │ │ │ ├── GenerateRecoveryCodes.razor │ │ │ │ ├── Index.razor │ │ │ │ ├── PersonalData.razor │ │ │ │ ├── ResetAuthenticator.razor │ │ │ │ ├── SetPassword.razor │ │ │ │ ├── TwoFactorAuthentication.razor │ │ │ │ └── _Imports.razor │ │ │ ├── Register.razor │ │ │ ├── RegisterConfirmation.razor │ │ │ ├── ResendEmailConfirmation.razor │ │ │ ├── ResetPassword.razor │ │ │ ├── ResetPasswordConfirmation.razor │ │ │ └── _Imports.razor │ │ └── Shared │ │ │ ├── AccountLayout.razor │ │ │ ├── ExternalLoginPicker.razor │ │ │ ├── ManageLayout.razor │ │ │ ├── ManageNavMenu.razor │ │ │ ├── RedirectToLogin.razor │ │ │ ├── ShowRecoveryCodes.razor │ │ │ └── StatusMessage.razor │ ├── App.razor │ ├── Layout │ │ ├── MainLayout.razor │ │ └── MainLayout.razor.css │ ├── LoginDisplay.razor │ ├── Pages │ │ ├── Error.razor │ │ ├── MyOrders.razor │ │ └── OrderDetails.razor │ ├── Routes.razor │ └── _Imports.razor │ ├── EfRepository.cs │ ├── OrdersController.cs │ ├── PizzaApiExtensions.cs │ ├── PizzaStoreContext.cs │ ├── PizzaStoreUser.cs │ ├── Program.cs │ ├── SeedData.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── wwwroot │ ├── css │ ├── bootstrap │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── font │ │ ├── quicksand-v8-latin-300.woff │ │ ├── quicksand-v8-latin-300.woff2 │ │ ├── quicksand-v8-latin-500.woff │ │ ├── quicksand-v8-latin-500.woff2 │ │ ├── quicksand-v8-latin-700.woff │ │ ├── quicksand-v8-latin-700.woff2 │ │ ├── quicksand-v8-latin-regular.woff │ │ ├── quicksand-v8-latin-regular.woff2 │ │ └── quicksand.css │ └── site.css │ ├── img │ ├── bike.svg │ ├── icon-512.png │ ├── logo.svg │ ├── pizza-slice.svg │ ├── pizzas │ │ ├── bacon.jpg │ │ ├── brit.jpg │ │ ├── cheese.jpg │ │ ├── margherita.jpg │ │ ├── meaty.jpg │ │ ├── mushroom.jpg │ │ ├── pepperoni.jpg │ │ └── salad.jpg │ └── user.svg │ ├── index.html │ ├── manifest.json │ └── service-worker.js └── ui-mockup.pptx /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8.0.0 4 | 8.0.0 5 | 8.0.0 6 | net8.0 7 | 8.0.0 8 | 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BlazingPizzaWorkshop 2 | The Blazing Pizza Workshop, updated for .NET 8 3 | 4 | Updated and derived from https://github.com/csharpfritz/blazor-workshop 5 | 6 | Watch the videos that accompany this at: https://www.youtube.com/watch?v=sWTpxFcHbfY&list=PLdo4fOcmZ0oXv32dOd36UydQYLejKR61R&index=78 7 | 8 | Here are the list of modules that accompany this workshop: 9 | 10 | | Title | 11 | | --- | 12 | | [Get Started with Blazor](docs/00-get-started.md) | 13 | | [Building our first home screen and learning about interactivity](docs/01-HomeScreen.md) | 14 | | [Our first component and Managing State](docs/02-managing-state.md) | 15 | | [Validating Data](docs/03-validation.md) | 16 | | [Authenticating Users with Blazor](docs/04-authentication.md) | 17 | | [Sharing Components with other projects](docs/05-components.md) | 18 | -------------------------------------------------------------------------------- /docs/00-get-started.md: -------------------------------------------------------------------------------- 1 | # Get started 2 | 3 | In this session, you'll setup your machine for Blazor development and build your first Blazor app. 4 | 5 | ## Setup 6 | 7 | To get started with Blazor, follow the getting instructions on [blazor.net](https://dotnet.microsoft.com/en-us/learn/aspnet/blazor-tutorial/intro). 8 | 9 | ## Build your first app 10 | 11 | Once you have your first Blazor app running, try [building a Blazor todo list app](https://aka.ms/blazor/todo). 12 | 13 | Next up - [Starting our app, the Home Screen, and more](01-HomeScreen.md) -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.Client/BlazingPizza.Client.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | true 8 | Default 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.Client/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 2 | 3 | var builder = WebAssemblyHostBuilder.CreateDefault(args); 4 | 5 | await builder.Build().RunAsync(); 6 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazingPizza.Client 10 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.ComponentsLibrary/LocalStorage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace BlazingPizza.ComponentsLibrary; 4 | 5 | public static class LocalStorage 6 | { 7 | public static ValueTask GetAsync(IJSRuntime jsRuntime, string key) 8 | => jsRuntime.InvokeAsync("blazorLocalStorage.get", key); 9 | 10 | public static ValueTask SetAsync(IJSRuntime jsRuntime, string key, object value) 11 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.set", key, value); 12 | 13 | public static ValueTask DeleteAsync(IJSRuntime jsRuntime, string key) 14 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.delete", key); 15 | } 16 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.ComponentsLibrary/Map/Map.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.JSInterop 2 | @inject IJSRuntime JSRuntime 3 | 4 |
5 | 6 | @code { 7 | string elementId = $"map-{Guid.NewGuid().ToString("D")}"; 8 | 9 | [Parameter] public double Zoom { get; set; } 10 | [Parameter, EditorRequired] public List Markers { get; set; } = new(); 11 | 12 | protected async override Task OnAfterRenderAsync(bool firstRender) 13 | { 14 | await JSRuntime.InvokeVoidAsync( 15 | "deliveryMap.showOrUpdate", 16 | elementId, 17 | Markers); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.ComponentsLibrary/Map/Marker.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Marker 4 | { 5 | public string Description { get; set; } = string.Empty; 6 | 7 | public double X { get; set; } 8 | 9 | public double Y { get; set; } 10 | 11 | public bool ShowPopup { get; set; } 12 | } -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.ComponentsLibrary/Map/Point.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Point 4 | { 5 | public double X { get; set; } 6 | 7 | public double Y { get; set; } 8 | } -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.ComponentsLibrary/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.ComponentsLibrary/wwwroot/localStorage.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | window.blazorLocalStorage = { 3 | get: key => key in localStorage ? JSON.parse(localStorage[key]) : null, 4 | set: (key, value) => { localStorage[key] = JSON.stringify(value); }, 5 | delete: key => { delete localStorage[key]; } 6 | }; 7 | })(); 8 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.Shared/Address.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class Address 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | public string Line1 { get; set; } = string.Empty; 10 | 11 | public string Line2 { get; set; } = string.Empty; 12 | 13 | public string City { get; set; } = string.Empty; 14 | 15 | public string Region { get; set; } = string.Empty; 16 | 17 | public string PostalCode { get; set; } = string.Empty; 18 | } 19 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.Shared/BlazingPizza.Shared.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.Shared/IRepository.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public interface IRepository 4 | { 5 | 6 | Task> GetToppings(); 7 | 8 | Task> GetSpecials(); 9 | 10 | Task> GetOrdersAsync(); 11 | 12 | Task GetOrderWithStatus(int orderId); 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.Shared/LatLong.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class LatLong 4 | { 5 | public LatLong() 6 | { 7 | } 8 | 9 | public LatLong(double latitude, double longitude) : this() 10 | { 11 | Latitude = latitude; 12 | Longitude = longitude; 13 | } 14 | 15 | public double Latitude { get; set; } 16 | 17 | public double Longitude { get; set; } 18 | 19 | public static LatLong Interpolate(LatLong start, LatLong end, double proportion) 20 | { 21 | // The Earth is flat, right? So no need for spherical interpolation. 22 | return new LatLong( 23 | start.Latitude + (end.Latitude - start.Latitude) * proportion, 24 | start.Longitude + (end.Longitude - start.Longitude) * proportion); 25 | } 26 | } -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.Shared/NotificationSubscription.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class NotificationSubscription 4 | { 5 | public int? NotificationSubscriptionId { get; set; } 6 | 7 | public string? UserId { get; set; } 8 | 9 | public string? Url { get; set; } 10 | 11 | public string? P256dh { get; set; } 12 | 13 | public string? Auth { get; set; } 14 | } -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.Shared/PizzaSpecial.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | /// 4 | /// Represents a pre-configured template for a pizza a user can order 5 | /// 6 | public class PizzaSpecial 7 | { 8 | public int Id { get; set; } 9 | 10 | public string Name { get; set; } = string.Empty; 11 | 12 | public decimal BasePrice { get; set; } 13 | 14 | public string Description { get; set; } = string.Empty; 15 | 16 | public string ImageUrl { get; set; } = "img/pizzas/cheese.jpg"; 17 | 18 | public string GetFormattedBasePrice() => BasePrice.ToString("0.00"); 19 | } -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.Shared/PizzaTopping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | 4 | public class PizzaTopping 5 | { 6 | public Topping? Topping { get; set; } 7 | 8 | public int ToppingId { get; set; } 9 | 10 | public int PizzaId { get; set; } 11 | 12 | } -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.Shared/Topping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class Topping 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | public decimal Price { get; set; } 10 | 11 | public string GetFormattedPrice() => Price.ToString("0.00"); 12 | 13 | } -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza.Shared/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class UserInfo 4 | { 5 | public bool IsAuthenticated { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | } -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/Components/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/Components/Layout/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | @Body 4 | 5 |
6 | An unhandled error has occurred. 7 | Reload 8 | 🗙 9 |
10 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/Components/Layout/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | #blazor-error-ui { 2 | background: lightyellow; 3 | bottom: 0; 4 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 5 | display: none; 6 | left: 0; 7 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 8 | position: fixed; 9 | width: 100%; 10 | z-index: 1000; 11 | } 12 | 13 | #blazor-error-ui .dismiss { 14 | cursor: pointer; 15 | position: absolute; 16 | right: 0.75rem; 17 | top: 0.5rem; 18 | } 19 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/Components/Pages/Home.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | 3 | Blazing Pizzas 4 | 5 |

Blazing Pizzas

6 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/Components/Routes.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/Components/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazingPizza 10 | @using BlazingPizza.Client 11 | @using BlazingPizza.Components 12 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/PizzaStoreUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace BlazingPizza; 4 | 5 | public class PizzaStoreUser : IdentityUser 6 | { 7 | } -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2 -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2 -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2 -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2 -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/img/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/img/icon-512.png -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/bacon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/bacon.jpg -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/brit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/brit.jpg -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/cheese.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/cheese.jpg -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/margherita.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/margherita.jpg -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/meaty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/meaty.jpg -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg -------------------------------------------------------------------------------- /save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/salad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/0-Start/BlazingPizza/wwwroot/img/pizzas/salad.jpg -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.Client/ConfiguredPizzaItem.razor: -------------------------------------------------------------------------------- 1 | 
2 | x 3 |
@(Pizza.Size)" @Pizza.Special?.Name
4 |
    5 | @foreach (var topping in Pizza.Toppings) 6 | { 7 |
  • + @topping.Topping?.Name
  • 8 | } 9 |
10 |
11 | @Pizza.GetFormattedTotalPrice() 12 |
13 |
14 | 15 | @code { 16 | [Parameter, EditorRequired] public Pizza Pizza { get; set; } = new(); 17 | [Parameter, EditorRequired] public EventCallback OnRemoved { get; set; } 18 | } -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.Client/Program.cs: -------------------------------------------------------------------------------- 1 | global using BlazingPizza.Shared; 2 | 3 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 4 | using System; 5 | using System.Net.Http; 6 | using System.Threading.Tasks; 7 | 8 | var builder = WebAssemblyHostBuilder.CreateDefault(args); 9 | 10 | // Configure HttpClient to use the base address of the server project 11 | builder.Services.AddScoped(sp => 12 | new HttpClient 13 | { 14 | BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) 15 | }); 16 | 17 | builder.Services.AddScoped(); 18 | 19 | 20 | await builder.Build().RunAsync(); 21 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazingPizza.Client 10 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/LocalStorage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace BlazingPizza.ComponentsLibrary; 4 | 5 | public static class LocalStorage 6 | { 7 | public static ValueTask GetAsync(IJSRuntime jsRuntime, string key) 8 | => jsRuntime.InvokeAsync("blazorLocalStorage.get", key); 9 | 10 | public static ValueTask SetAsync(IJSRuntime jsRuntime, string key, object value) 11 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.set", key, value); 12 | 13 | public static ValueTask DeleteAsync(IJSRuntime jsRuntime, string key) 14 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.delete", key); 15 | } 16 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/Map/Map.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.JSInterop 2 | @inject IJSRuntime JSRuntime 3 | 4 |
5 | 6 | @code { 7 | string elementId = $"map-{Guid.NewGuid().ToString("D")}"; 8 | 9 | [Parameter] public double Zoom { get; set; } 10 | [Parameter, EditorRequired] public List Markers { get; set; } = new(); 11 | 12 | protected async override Task OnAfterRenderAsync(bool firstRender) 13 | { 14 | await JSRuntime.InvokeVoidAsync( 15 | "deliveryMap.showOrUpdate", 16 | elementId, 17 | Markers); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/Map/Marker.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Marker 4 | { 5 | public string Description { get; set; } = string.Empty; 6 | 7 | public double X { get; set; } 8 | 9 | public double Y { get; set; } 10 | 11 | public bool ShowPopup { get; set; } 12 | } -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/Map/Point.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Point 4 | { 5 | public double X { get; set; } 6 | 7 | public double Y { get; set; } 8 | } -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.ComponentsLibrary/wwwroot/localStorage.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | window.blazorLocalStorage = { 3 | get: key => key in localStorage ? JSON.parse(localStorage[key]) : null, 4 | set: (key, value) => { localStorage[key] = JSON.stringify(value); }, 5 | delete: key => { delete localStorage[key]; } 6 | }; 7 | })(); 8 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.Shared/Address.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class Address 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | public string Line1 { get; set; } = string.Empty; 10 | 11 | public string Line2 { get; set; } = string.Empty; 12 | 13 | public string City { get; set; } = string.Empty; 14 | 15 | public string Region { get; set; } = string.Empty; 16 | 17 | public string PostalCode { get; set; } = string.Empty; 18 | } 19 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.Shared/BlazingPizza.Shared.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.Shared/IRepository.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public interface IRepository 4 | { 5 | 6 | Task> GetToppings(); 7 | 8 | Task> GetSpecials(); 9 | 10 | Task> GetOrdersAsync(); 11 | 12 | Task GetOrderWithStatus(int orderId); 13 | 14 | Task PlaceOrder(Order order); 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.Shared/LatLong.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class LatLong 4 | { 5 | public LatLong() 6 | { 7 | } 8 | 9 | public LatLong(double latitude, double longitude) : this() 10 | { 11 | Latitude = latitude; 12 | Longitude = longitude; 13 | } 14 | 15 | public double Latitude { get; set; } 16 | 17 | public double Longitude { get; set; } 18 | 19 | public static LatLong Interpolate(LatLong start, LatLong end, double proportion) 20 | { 21 | // The Earth is flat, right? So no need for spherical interpolation. 22 | return new LatLong( 23 | start.Latitude + (end.Latitude - start.Latitude) * proportion, 24 | start.Longitude + (end.Longitude - start.Longitude) * proportion); 25 | } 26 | } -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.Shared/NotificationSubscription.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class NotificationSubscription 4 | { 5 | public int? NotificationSubscriptionId { get; set; } 6 | 7 | public string? UserId { get; set; } 8 | 9 | public string? Url { get; set; } 10 | 11 | public string? P256dh { get; set; } 12 | 13 | public string? Auth { get; set; } 14 | } -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.Shared/PizzaSpecial.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | /// 4 | /// Represents a pre-configured template for a pizza a user can order 5 | /// 6 | public class PizzaSpecial 7 | { 8 | public int Id { get; set; } 9 | 10 | public string Name { get; set; } = string.Empty; 11 | 12 | public decimal BasePrice { get; set; } 13 | 14 | public string Description { get; set; } = string.Empty; 15 | 16 | public string ImageUrl { get; set; } = "img/pizzas/cheese.jpg"; 17 | 18 | public string GetFormattedBasePrice() => BasePrice.ToString("0.00"); 19 | } -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.Shared/PizzaTopping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | 4 | public class PizzaTopping 5 | { 6 | public Topping? Topping { get; set; } 7 | 8 | public int ToppingId { get; set; } 9 | 10 | public int PizzaId { get; set; } 11 | 12 | } -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.Shared/Topping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class Topping 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | public decimal Price { get; set; } 10 | 11 | public string GetFormattedPrice() => Price.ToString("0.00"); 12 | 13 | } -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza.Shared/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class UserInfo 4 | { 5 | public bool IsAuthenticated { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | } -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/Components/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/Components/Layout/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 7 | 8 | 9 | 10 |
Get Pizza
11 |
12 |
13 | 14 |
15 | @Body 16 |
17 | 18 |
19 | An unhandled error has occurred. 20 | Reload 21 | 🗙 22 |
23 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/Components/Layout/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | #blazor-error-ui { 2 | background: lightyellow; 3 | bottom: 0; 4 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 5 | display: none; 6 | left: 0; 7 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 8 | position: fixed; 9 | width: 100%; 10 | z-index: 1000; 11 | } 12 | 13 | #blazor-error-ui .dismiss { 14 | cursor: pointer; 15 | position: absolute; 16 | right: 0.75rem; 17 | top: 0.5rem; 18 | } 19 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/Components/Routes.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/Components/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazingPizza 10 | @using BlazingPizza.Client 11 | @using BlazingPizza.Components 12 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/PizzaStoreUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace BlazingPizza; 4 | 5 | public class PizzaStoreUser : IdentityUser 6 | { 7 | } -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2 -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2 -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2 -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2 -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/img/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/img/icon-512.png -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/bacon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/bacon.jpg -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/brit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/brit.jpg -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/cheese.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/cheese.jpg -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/margherita.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/margherita.jpg -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/meaty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/meaty.jpg -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg -------------------------------------------------------------------------------- /save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/salad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/1-HomeScreen/BlazingPizza/wwwroot/img/pizzas/salad.jpg -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Client/BlazingPizza.Client.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | true 8 | Default 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Client/Components/ConfiguredPizzaItem.razor: -------------------------------------------------------------------------------- 1 | 
2 | x 3 |
@(Pizza.Size)" @Pizza.Special?.Name
4 |
    5 | @foreach (var topping in Pizza.Toppings) 6 | { 7 |
  • + @topping.Topping?.Name
  • 8 | } 9 |
10 |
11 | @Pizza.GetFormattedTotalPrice() 12 |
13 |
14 | 15 | @code { 16 | [Parameter, EditorRequired] public Pizza Pizza { get; set; } = new(); 17 | [Parameter, EditorRequired] public EventCallback OnRemoved { get; set; } 18 | } -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Client/Components/OrderReview.razor: -------------------------------------------------------------------------------- 1 | @foreach (var pizza in Order.Pizzas) 2 | { 3 |

4 | 5 | @(pizza.Size)" 6 | @pizza.Special?.Name 7 | (£@pizza.GetFormattedTotalPrice()) 8 | 9 |

10 | 11 |
    12 | @foreach (var topping in pizza.Toppings) 13 | { 14 |
  • + @topping.Topping?.Name
  • 15 | } 16 |
17 | } 18 | 19 |

20 | 21 | Total price: 22 | £@Order.GetFormattedTotalPrice() 23 | 24 |

25 | 26 | @code { 27 | [Parameter, EditorRequired] public Order Order { get; set; } = new(); 28 | } -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Client/Program.cs: -------------------------------------------------------------------------------- 1 | global using BlazingPizza.Shared; 2 | global using BlazingPizza.Client; 3 | 4 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 5 | using System; 6 | using System.Net.Http; 7 | using System.Threading.Tasks; 8 | 9 | var builder = WebAssemblyHostBuilder.CreateDefault(args); 10 | 11 | // Configure HttpClient to use the base address of the server project 12 | builder.Services.AddScoped(sp => 13 | new HttpClient 14 | { 15 | BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) 16 | }); 17 | 18 | builder.Services.AddScoped(); 19 | builder.Services.AddScoped(); 20 | 21 | 22 | await builder.Build().RunAsync(); 23 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazingPizza.Client 10 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.ComponentsLibrary/LocalStorage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace BlazingPizza.ComponentsLibrary; 4 | 5 | public static class LocalStorage 6 | { 7 | public static ValueTask GetAsync(IJSRuntime jsRuntime, string key) 8 | => jsRuntime.InvokeAsync("blazorLocalStorage.get", key); 9 | 10 | public static ValueTask SetAsync(IJSRuntime jsRuntime, string key, object value) 11 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.set", key, value); 12 | 13 | public static ValueTask DeleteAsync(IJSRuntime jsRuntime, string key) 14 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.delete", key); 15 | } 16 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.ComponentsLibrary/Map/Map.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.JSInterop 2 | @inject IJSRuntime JSRuntime 3 | 4 |
5 | 6 | @code { 7 | string elementId = $"map-{Guid.NewGuid().ToString("D")}"; 8 | 9 | [Parameter] public double Zoom { get; set; } 10 | [Parameter, EditorRequired] public List Markers { get; set; } = new(); 11 | 12 | protected async override Task OnAfterRenderAsync(bool firstRender) 13 | { 14 | await JSRuntime.InvokeVoidAsync( 15 | "deliveryMap.showOrUpdate", 16 | elementId, 17 | Markers); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.ComponentsLibrary/Map/Marker.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Marker 4 | { 5 | public string Description { get; set; } = string.Empty; 6 | 7 | public double X { get; set; } 8 | 9 | public double Y { get; set; } 10 | 11 | public bool ShowPopup { get; set; } 12 | } -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.ComponentsLibrary/Map/Point.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Point 4 | { 5 | public double X { get; set; } 6 | 7 | public double Y { get; set; } 8 | } -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.ComponentsLibrary/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.ComponentsLibrary/wwwroot/localStorage.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | window.blazorLocalStorage = { 3 | get: key => key in localStorage ? JSON.parse(localStorage[key]) : null, 4 | set: (key, value) => { localStorage[key] = JSON.stringify(value); }, 5 | delete: key => { delete localStorage[key]; } 6 | }; 7 | })(); 8 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Shared/Address.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class Address 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | public string Line1 { get; set; } = string.Empty; 10 | 11 | public string Line2 { get; set; } = string.Empty; 12 | 13 | public string City { get; set; } = string.Empty; 14 | 15 | public string Region { get; set; } = string.Empty; 16 | 17 | public string PostalCode { get; set; } = string.Empty; 18 | } 19 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Shared/BlazingPizza.Shared.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Shared/IRepository.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public interface IRepository 4 | { 5 | 6 | Task> GetToppings(); 7 | 8 | Task> GetSpecials(); 9 | 10 | Task> GetOrdersAsync(); 11 | 12 | Task GetOrderWithStatus(int orderId); 13 | 14 | Task PlaceOrder(Order order); 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Shared/LatLong.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class LatLong 4 | { 5 | public LatLong() 6 | { 7 | } 8 | 9 | public LatLong(double latitude, double longitude) : this() 10 | { 11 | Latitude = latitude; 12 | Longitude = longitude; 13 | } 14 | 15 | public double Latitude { get; set; } 16 | 17 | public double Longitude { get; set; } 18 | 19 | public static LatLong Interpolate(LatLong start, LatLong end, double proportion) 20 | { 21 | // The Earth is flat, right? So no need for spherical interpolation. 22 | return new LatLong( 23 | start.Latitude + (end.Latitude - start.Latitude) * proportion, 24 | start.Longitude + (end.Longitude - start.Longitude) * proportion); 25 | } 26 | } -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Shared/NotificationSubscription.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class NotificationSubscription 4 | { 5 | public int? NotificationSubscriptionId { get; set; } 6 | 7 | public string? UserId { get; set; } 8 | 9 | public string? Url { get; set; } 10 | 11 | public string? P256dh { get; set; } 12 | 13 | public string? Auth { get; set; } 14 | } -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Shared/PizzaSpecial.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | /// 4 | /// Represents a pre-configured template for a pizza a user can order 5 | /// 6 | public class PizzaSpecial 7 | { 8 | public int Id { get; set; } 9 | 10 | public string Name { get; set; } = string.Empty; 11 | 12 | public decimal BasePrice { get; set; } 13 | 14 | public string Description { get; set; } = string.Empty; 15 | 16 | public string ImageUrl { get; set; } = "img/pizzas/cheese.jpg"; 17 | 18 | public string GetFormattedBasePrice() => BasePrice.ToString("0.00"); 19 | } -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Shared/PizzaTopping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | 4 | public class PizzaTopping 5 | { 6 | public Topping? Topping { get; set; } 7 | 8 | public int ToppingId { get; set; } 9 | 10 | public int PizzaId { get; set; } 11 | 12 | } -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Shared/Topping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class Topping 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | public decimal Price { get; set; } 10 | 11 | public string GetFormattedPrice() => Price.ToString("0.00"); 12 | 13 | } -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza.Shared/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class UserInfo 4 | { 5 | public bool IsAuthenticated { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | } -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/Components/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/Components/Layout/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 7 | 8 | 9 | 10 |
Get Pizza
11 |
12 | 13 | 14 | 15 |
My Orders
16 |
17 | 18 |
19 | 20 |
21 | @Body 22 |
23 | 24 |
25 | An unhandled error has occurred. 26 | Reload 27 | 🗙 28 |
29 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/Components/Layout/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | #blazor-error-ui { 2 | background: lightyellow; 3 | bottom: 0; 4 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 5 | display: none; 6 | left: 0; 7 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 8 | position: fixed; 9 | width: 100%; 10 | z-index: 1000; 11 | } 12 | 13 | #blazor-error-ui .dismiss { 14 | cursor: pointer; 15 | position: absolute; 16 | right: 0.75rem; 17 | top: 0.5rem; 18 | } 19 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/Components/Routes.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/Components/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazingPizza 10 | @using BlazingPizza.Client 11 | @using BlazingPizza.Client.Components 12 | @using BlazingPizza.Components 13 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/PizzaStoreUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace BlazingPizza; 4 | 5 | public class PizzaStoreUser : IdentityUser 6 | { 7 | } -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2 -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2 -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2 -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2 -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/img/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/img/icon-512.png -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/img/pizzas/bacon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/img/pizzas/bacon.jpg -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/img/pizzas/brit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/img/pizzas/brit.jpg -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/img/pizzas/cheese.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/img/pizzas/cheese.jpg -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/img/pizzas/margherita.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/img/pizzas/margherita.jpg -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/img/pizzas/meaty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/img/pizzas/meaty.jpg -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg -------------------------------------------------------------------------------- /save-points/2-State/BlazingPizza/wwwroot/img/pizzas/salad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/2-State/BlazingPizza/wwwroot/img/pizzas/salad.jpg -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Client/BootstrapFieldClassProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Forms; 2 | 3 | namespace BlazingPizza.Client; 4 | 5 | public class BootstrapFieldClassProvider : FieldCssClassProvider 6 | { 7 | public override string GetFieldCssClass(EditContext editContext, 8 | in FieldIdentifier fieldIdentifier) 9 | { 10 | var isValid = editContext.IsValid(fieldIdentifier); 11 | 12 | return isValid ? "is-valid" : "is-invalid"; 13 | } 14 | } -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Client/Components/ConfiguredPizzaItem.razor: -------------------------------------------------------------------------------- 1 | 
2 | x 3 |
@(Pizza.Size)" @Pizza.Special?.Name
4 |
    5 | @foreach (var topping in Pizza.Toppings) 6 | { 7 |
  • + @topping.Topping?.Name
  • 8 | } 9 |
10 |
11 | @Pizza.GetFormattedTotalPrice() 12 |
13 |
14 | 15 | @code { 16 | [Parameter, EditorRequired] public Pizza Pizza { get; set; } = new(); 17 | [Parameter, EditorRequired] public EventCallback OnRemoved { get; set; } 18 | } -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Client/Components/OrderReview.razor: -------------------------------------------------------------------------------- 1 | @foreach (var pizza in Order.Pizzas) 2 | { 3 |

4 | 5 | @(pizza.Size)" 6 | @pizza.Special?.Name 7 | (£@pizza.GetFormattedTotalPrice()) 8 | 9 |

10 | 11 |
    12 | @foreach (var topping in pizza.Toppings) 13 | { 14 |
  • + @topping.Topping?.Name
  • 15 | } 16 |
17 | } 18 | 19 |

20 | 21 | Total price: 22 | £@Order.GetFormattedTotalPrice() 23 | 24 |

25 | 26 | @code { 27 | [Parameter, EditorRequired] public Order Order { get; set; } = new(); 28 | } -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Client/Program.cs: -------------------------------------------------------------------------------- 1 | global using BlazingPizza.Shared; 2 | global using BlazingPizza.Client; 3 | 4 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 5 | using System; 6 | using System.Net.Http; 7 | using System.Threading.Tasks; 8 | 9 | var builder = WebAssemblyHostBuilder.CreateDefault(args); 10 | 11 | // Configure HttpClient to use the base address of the server project 12 | builder.Services.AddScoped(sp => 13 | new HttpClient 14 | { 15 | BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) 16 | }); 17 | 18 | builder.Services.AddScoped(); 19 | builder.Services.AddScoped(); 20 | 21 | 22 | await builder.Build().RunAsync(); 23 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazingPizza.Client 10 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.ComponentsLibrary/LocalStorage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace BlazingPizza.ComponentsLibrary; 4 | 5 | public static class LocalStorage 6 | { 7 | public static ValueTask GetAsync(IJSRuntime jsRuntime, string key) 8 | => jsRuntime.InvokeAsync("blazorLocalStorage.get", key); 9 | 10 | public static ValueTask SetAsync(IJSRuntime jsRuntime, string key, object value) 11 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.set", key, value); 12 | 13 | public static ValueTask DeleteAsync(IJSRuntime jsRuntime, string key) 14 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.delete", key); 15 | } 16 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.ComponentsLibrary/Map/Map.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.JSInterop 2 | @inject IJSRuntime JSRuntime 3 | 4 |
5 | 6 | @code { 7 | string elementId = $"map-{Guid.NewGuid().ToString("D")}"; 8 | 9 | [Parameter] public double Zoom { get; set; } 10 | [Parameter, EditorRequired] public List Markers { get; set; } = new(); 11 | 12 | protected async override Task OnAfterRenderAsync(bool firstRender) 13 | { 14 | await JSRuntime.InvokeVoidAsync( 15 | "deliveryMap.showOrUpdate", 16 | elementId, 17 | Markers); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.ComponentsLibrary/Map/Marker.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Marker 4 | { 5 | public string Description { get; set; } = string.Empty; 6 | 7 | public double X { get; set; } 8 | 9 | public double Y { get; set; } 10 | 11 | public bool ShowPopup { get; set; } 12 | } -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.ComponentsLibrary/Map/Point.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Point 4 | { 5 | public double X { get; set; } 6 | 7 | public double Y { get; set; } 8 | } -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.ComponentsLibrary/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.ComponentsLibrary/wwwroot/localStorage.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | window.blazorLocalStorage = { 3 | get: key => key in localStorage ? JSON.parse(localStorage[key]) : null, 4 | set: (key, value) => { localStorage[key] = JSON.stringify(value); }, 5 | delete: key => { delete localStorage[key]; } 6 | }; 7 | })(); 8 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Shared/BlazingPizza.Shared.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Shared/IRepository.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public interface IRepository 4 | { 5 | 6 | Task> GetToppings(); 7 | 8 | Task> GetSpecials(); 9 | 10 | Task> GetOrdersAsync(); 11 | 12 | Task GetOrderWithStatus(int orderId); 13 | 14 | Task PlaceOrder(Order order); 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Shared/LatLong.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class LatLong 4 | { 5 | public LatLong() 6 | { 7 | } 8 | 9 | public LatLong(double latitude, double longitude) : this() 10 | { 11 | Latitude = latitude; 12 | Longitude = longitude; 13 | } 14 | 15 | public double Latitude { get; set; } 16 | 17 | public double Longitude { get; set; } 18 | 19 | public static LatLong Interpolate(LatLong start, LatLong end, double proportion) 20 | { 21 | // The Earth is flat, right? So no need for spherical interpolation. 22 | return new LatLong( 23 | start.Latitude + (end.Latitude - start.Latitude) * proportion, 24 | start.Longitude + (end.Longitude - start.Longitude) * proportion); 25 | } 26 | } -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Shared/NotificationSubscription.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class NotificationSubscription 4 | { 5 | public int? NotificationSubscriptionId { get; set; } 6 | 7 | public string? UserId { get; set; } 8 | 9 | public string? Url { get; set; } 10 | 11 | public string? P256dh { get; set; } 12 | 13 | public string? Auth { get; set; } 14 | } -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Shared/PizzaSpecial.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | /// 4 | /// Represents a pre-configured template for a pizza a user can order 5 | /// 6 | public class PizzaSpecial 7 | { 8 | public int Id { get; set; } 9 | 10 | public string Name { get; set; } = string.Empty; 11 | 12 | public decimal BasePrice { get; set; } 13 | 14 | public string Description { get; set; } = string.Empty; 15 | 16 | public string ImageUrl { get; set; } = "img/pizzas/cheese.jpg"; 17 | 18 | public string GetFormattedBasePrice() => BasePrice.ToString("0.00"); 19 | } -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Shared/PizzaTopping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | 4 | public class PizzaTopping 5 | { 6 | public Topping? Topping { get; set; } 7 | 8 | public int ToppingId { get; set; } 9 | 10 | public int PizzaId { get; set; } 11 | 12 | } -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Shared/Topping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class Topping 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | public decimal Price { get; set; } 10 | 11 | public string GetFormattedPrice() => Price.ToString("0.00"); 12 | 13 | } -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza.Shared/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class UserInfo 4 | { 5 | public bool IsAuthenticated { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | } -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/Components/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/Components/Layout/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 7 | 8 | 9 | 10 |
Get Pizza
11 |
12 | 13 | 14 | 15 |
My Orders
16 |
17 | 18 |
19 | 20 |
21 | @Body 22 |
23 | 24 |
25 | An unhandled error has occurred. 26 | Reload 27 | 🗙 28 |
29 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/Components/Layout/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | #blazor-error-ui { 2 | background: lightyellow; 3 | bottom: 0; 4 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 5 | display: none; 6 | left: 0; 7 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 8 | position: fixed; 9 | width: 100%; 10 | z-index: 1000; 11 | } 12 | 13 | #blazor-error-ui .dismiss { 14 | cursor: pointer; 15 | position: absolute; 16 | right: 0.75rem; 17 | top: 0.5rem; 18 | } 19 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/Components/Routes.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/Components/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazingPizza 10 | @using BlazingPizza.Client 11 | @using BlazingPizza.Client.Components 12 | @using BlazingPizza.Components 13 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/PizzaStoreUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace BlazingPizza; 4 | 5 | public class PizzaStoreUser : IdentityUser 6 | { 7 | } -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2 -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2 -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2 -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2 -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/img/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/img/icon-512.png -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/bacon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/bacon.jpg -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/brit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/brit.jpg -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/cheese.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/cheese.jpg -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/margherita.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/margherita.jpg -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/meaty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/meaty.jpg -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg -------------------------------------------------------------------------------- /save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/salad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/3-Validation/BlazingPizza/wwwroot/img/pizzas/salad.jpg -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Client/BootstrapFieldClassProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Forms; 2 | 3 | namespace BlazingPizza.Client; 4 | 5 | public class BootstrapFieldClassProvider : FieldCssClassProvider 6 | { 7 | public override string GetFieldCssClass(EditContext editContext, 8 | in FieldIdentifier fieldIdentifier) 9 | { 10 | var isValid = editContext.IsValid(fieldIdentifier); 11 | 12 | return isValid ? "is-valid" : "is-invalid"; 13 | } 14 | } -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Client/Components/ConfiguredPizzaItem.razor: -------------------------------------------------------------------------------- 1 | 
2 | x 3 |
@(Pizza.Size)" @Pizza.Special?.Name
4 |
    5 | @foreach (var topping in Pizza.Toppings) 6 | { 7 |
  • + @topping.Topping?.Name
  • 8 | } 9 |
10 |
11 | @Pizza.GetFormattedTotalPrice() 12 |
13 |
14 | 15 | @code { 16 | [Parameter, EditorRequired] public Pizza Pizza { get; set; } = new(); 17 | [Parameter, EditorRequired] public EventCallback OnRemoved { get; set; } 18 | } -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Client/Components/OrderReview.razor: -------------------------------------------------------------------------------- 1 | @foreach (var pizza in Order.Pizzas) 2 | { 3 |

4 | 5 | @(pizza.Size)" 6 | @pizza.Special?.Name 7 | (£@pizza.GetFormattedTotalPrice()) 8 | 9 |

10 | 11 |
    12 | @foreach (var topping in pizza.Toppings) 13 | { 14 |
  • + @topping.Topping?.Name
  • 15 | } 16 |
17 | } 18 | 19 |

20 | 21 | Total price: 22 | £@Order.GetFormattedTotalPrice() 23 | 24 |

25 | 26 | @code { 27 | [Parameter, EditorRequired] public Order Order { get; set; } = new(); 28 | } -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Client/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Client; 2 | 3 | // Add properties to this class and update the server and client AuthenticationStateProviders 4 | // to expose more information about the authenticated user to the client. 5 | public class UserInfo 6 | { 7 | public required string UserId { get; set; } 8 | public required string Email { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazingPizza.Client 10 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.ComponentsLibrary/LocalStorage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace BlazingPizza.ComponentsLibrary; 4 | 5 | public static class LocalStorage 6 | { 7 | public static ValueTask GetAsync(IJSRuntime jsRuntime, string key) 8 | => jsRuntime.InvokeAsync("blazorLocalStorage.get", key); 9 | 10 | public static ValueTask SetAsync(IJSRuntime jsRuntime, string key, object value) 11 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.set", key, value); 12 | 13 | public static ValueTask DeleteAsync(IJSRuntime jsRuntime, string key) 14 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.delete", key); 15 | } 16 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.ComponentsLibrary/Map/Map.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.JSInterop 2 | @inject IJSRuntime JSRuntime 3 | 4 |
5 | 6 | @code { 7 | string elementId = $"map-{Guid.NewGuid().ToString("D")}"; 8 | 9 | [Parameter] public double Zoom { get; set; } 10 | [Parameter, EditorRequired] public List Markers { get; set; } = new(); 11 | 12 | protected async override Task OnAfterRenderAsync(bool firstRender) 13 | { 14 | await JSRuntime.InvokeVoidAsync( 15 | "deliveryMap.showOrUpdate", 16 | elementId, 17 | Markers); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.ComponentsLibrary/Map/Marker.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Marker 4 | { 5 | public string Description { get; set; } = string.Empty; 6 | 7 | public double X { get; set; } 8 | 9 | public double Y { get; set; } 10 | 11 | public bool ShowPopup { get; set; } 12 | } -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.ComponentsLibrary/Map/Point.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Point 4 | { 5 | public double X { get; set; } 6 | 7 | public double Y { get; set; } 8 | } -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.ComponentsLibrary/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.ComponentsLibrary/wwwroot/localStorage.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | window.blazorLocalStorage = { 3 | get: key => key in localStorage ? JSON.parse(localStorage[key]) : null, 4 | set: (key, value) => { localStorage[key] = JSON.stringify(value); }, 5 | delete: key => { delete localStorage[key]; } 6 | }; 7 | })(); 8 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Shared/BlazingPizza.Shared.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Shared/IRepository.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public interface IRepository 4 | { 5 | 6 | Task> GetToppings(); 7 | 8 | Task> GetSpecials(); 9 | 10 | Task> GetOrdersAsync(); 11 | 12 | Task> GetOrdersAsync(string userId); 13 | 14 | Task GetOrderWithStatus(int orderId); 15 | 16 | Task GetOrderWithStatus(int orderId, string userId); 17 | 18 | Task PlaceOrder(Order order); 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Shared/LatLong.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class LatLong 4 | { 5 | public LatLong() 6 | { 7 | } 8 | 9 | public LatLong(double latitude, double longitude) : this() 10 | { 11 | Latitude = latitude; 12 | Longitude = longitude; 13 | } 14 | 15 | public double Latitude { get; set; } 16 | 17 | public double Longitude { get; set; } 18 | 19 | public static LatLong Interpolate(LatLong start, LatLong end, double proportion) 20 | { 21 | // The Earth is flat, right? So no need for spherical interpolation. 22 | return new LatLong( 23 | start.Latitude + (end.Latitude - start.Latitude) * proportion, 24 | start.Longitude + (end.Longitude - start.Longitude) * proportion); 25 | } 26 | } -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Shared/NotificationSubscription.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class NotificationSubscription 4 | { 5 | public int? NotificationSubscriptionId { get; set; } 6 | 7 | public string? UserId { get; set; } 8 | 9 | public string? Url { get; set; } 10 | 11 | public string? P256dh { get; set; } 12 | 13 | public string? Auth { get; set; } 14 | } -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Shared/PizzaSpecial.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | /// 4 | /// Represents a pre-configured template for a pizza a user can order 5 | /// 6 | public class PizzaSpecial 7 | { 8 | public int Id { get; set; } 9 | 10 | public string Name { get; set; } = string.Empty; 11 | 12 | public decimal BasePrice { get; set; } 13 | 14 | public string Description { get; set; } = string.Empty; 15 | 16 | public string ImageUrl { get; set; } = "img/pizzas/cheese.jpg"; 17 | 18 | public string GetFormattedBasePrice() => BasePrice.ToString("0.00"); 19 | } -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Shared/PizzaTopping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | 4 | public class PizzaTopping 5 | { 6 | public Topping? Topping { get; set; } 7 | 8 | public int ToppingId { get; set; } 9 | 10 | public int PizzaId { get; set; } 11 | 12 | } -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Shared/Topping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class Topping 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | public decimal Price { get; set; } 10 | 11 | public string GetFormattedPrice() => Price.ToString("0.00"); 12 | 13 | } -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza.Shared/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class UserInfo 4 | { 5 | public bool IsAuthenticated { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | } -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Account/IdentityUserAccessor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace BlazingPizza.Components.Account; 4 | 5 | internal sealed class IdentityUserAccessor(UserManager userManager, IdentityRedirectManager redirectManager) 6 | { 7 | public async Task GetRequiredUserAsync(HttpContext context) 8 | { 9 | var user = await userManager.GetUserAsync(context.User); 10 | 11 | if (user is null) 12 | { 13 | redirectManager.RedirectToWithStatus("Account/InvalidUser", $"Error: Unable to load user with ID '{userManager.GetUserId(context.User)}'.", context); 14 | } 15 | 16 | return user; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Account/Pages/AccessDenied.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/AccessDenied" 2 | 3 | Access denied 4 | 5 |
6 |

Access denied

7 |

You do not have access to this resource.

8 |
9 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Account/Pages/ForgotPasswordConfirmation.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/ForgotPasswordConfirmation" 2 | 3 | Forgot password confirmation 4 | 5 |

Forgot password confirmation

6 |

7 | Please check your email to reset your password. 8 |

9 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Account/Pages/InvalidPasswordReset.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/InvalidPasswordReset" 2 | 3 | Invalid password reset 4 | 5 |

Invalid password reset

6 |

7 | The password reset link is invalid. 8 |

9 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Account/Pages/InvalidUser.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/InvalidUser" 2 | 3 | Invalid user 4 | 5 |

Invalid user

6 | 7 | 8 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Account/Pages/Lockout.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/Lockout" 2 | 3 | Locked out 4 | 5 |
6 |

Locked out

7 |

This account has been locked out, please try again later.

8 |
9 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Account/Pages/Manage/_Imports.razor: -------------------------------------------------------------------------------- 1 | @layout ManageLayout 2 | @attribute [Microsoft.AspNetCore.Authorization.Authorize] 3 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Account/Pages/ResetPasswordConfirmation.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/ResetPasswordConfirmation" 2 | Reset password confirmation 3 | 4 |

Reset password confirmation

5 |

6 | Your password has been reset. Please click here to log in. 7 |

8 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Account/Pages/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using BlazingPizza.Components.Account.Shared 2 | @layout AccountLayout 3 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Account/Shared/ManageLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | @layout AccountLayout 3 | 4 |

Manage your account

5 | 6 |
7 |

Change your account settings

8 |
9 |
10 |
11 | 12 |
13 |
14 | @Body 15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Account/Shared/RedirectToLogin.razor: -------------------------------------------------------------------------------- 1 | @inject NavigationManager NavigationManager 2 | 3 | @code { 4 | protected override void OnInitialized() 5 | { 6 | NavigationManager.NavigateTo($"Account/Login?returnUrl={Uri.EscapeDataString(NavigationManager.Uri)}", forceLoad: true); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Layout/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 7 | 8 | 9 | 10 |
Get Pizza
11 |
12 | 13 | 14 | 15 | 16 |
My Orders
17 |
18 |
19 | 20 | 21 | 22 |
23 | 24 |
25 | @Body 26 |
27 | 28 |
29 | An unhandled error has occurred. 30 | Reload 31 | 🗙 32 |
33 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Layout/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | #blazor-error-ui { 2 | background: lightyellow; 3 | bottom: 0; 4 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 5 | display: none; 6 | left: 0; 7 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 8 | position: fixed; 9 | width: 100%; 10 | z-index: 1000; 11 | } 12 | 13 | #blazor-error-ui .dismiss { 14 | cursor: pointer; 15 | position: absolute; 16 | right: 0.75rem; 17 | top: 0.5rem; 18 | } 19 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/Routes.razor: -------------------------------------------------------------------------------- 1 | @using BlazingPizza.Components.Account.Shared 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Authorizing... Please wait 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/Components/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 8 | @using Microsoft.AspNetCore.Components.Web.Virtualization 9 | @using Microsoft.JSInterop 10 | @using BlazingPizza 11 | @using BlazingPizza.Client 12 | @using BlazingPizza.Client.Components 13 | @using BlazingPizza.Components 14 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/PizzaStoreUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace BlazingPizza; 4 | 5 | public class PizzaStoreUser : IdentityUser 6 | { 7 | } -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2 -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2 -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2 -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2 -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/img/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/img/icon-512.png -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/bacon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/bacon.jpg -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/brit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/brit.jpg -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/cheese.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/cheese.jpg -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/margherita.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/margherita.jpg -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/meaty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/meaty.jpg -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg -------------------------------------------------------------------------------- /save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/salad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/4-Authentication/BlazingPizza/wwwroot/img/pizzas/salad.jpg -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Client/BootstrapFieldClassProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Forms; 2 | 3 | namespace BlazingPizza.Client; 4 | 5 | public class BootstrapFieldClassProvider : FieldCssClassProvider 6 | { 7 | public override string GetFieldCssClass(EditContext editContext, 8 | in FieldIdentifier fieldIdentifier) 9 | { 10 | var isValid = editContext.IsValid(fieldIdentifier); 11 | 12 | return isValid ? "is-valid" : "is-invalid"; 13 | } 14 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Client/Components/ConfiguredPizzaItem.razor: -------------------------------------------------------------------------------- 1 | 
2 | x 3 |
@(Pizza.Size)" @Pizza.Special?.Name
4 |
    5 | @foreach (var topping in Pizza.Toppings) 6 | { 7 |
  • + @topping.Topping?.Name
  • 8 | } 9 |
10 |
11 | @Pizza.GetFormattedTotalPrice() 12 |
13 |
14 | 15 | @code { 16 | [Parameter, EditorRequired] public Pizza Pizza { get; set; } = new(); 17 | [Parameter, EditorRequired] public EventCallback OnRemoved { get; set; } 18 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Client/Components/OrderReview.razor: -------------------------------------------------------------------------------- 1 | @foreach (var pizza in Order.Pizzas) 2 | { 3 |

4 | 5 | @(pizza.Size)" 6 | @pizza.Special?.Name 7 | (£@pizza.GetFormattedTotalPrice()) 8 | 9 |

10 | 11 |
    12 | @foreach (var topping in pizza.Toppings) 13 | { 14 |
  • + @topping.Topping?.Name
  • 15 | } 16 |
17 | } 18 | 19 |

20 | 21 | Total price: 22 | £@Order.GetFormattedTotalPrice() 23 | 24 |

25 | 26 | @code { 27 | [Parameter, EditorRequired] public Order Order { get; set; } = new(); 28 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Client/JSRuntimeExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace BlazingPizza.Client; 4 | 5 | public static class JSRuntimeExtensions 6 | { 7 | public static ValueTask Confirm(this IJSRuntime jsRuntime, string message) 8 | { 9 | return jsRuntime.InvokeAsync("confirm", message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Client/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Client; 2 | 3 | // Add properties to this class and update the server and client AuthenticationStateProviders 4 | // to expose more information about the authenticated user to the client. 5 | public class UserInfo 6 | { 7 | public required string UserId { get; set; } 8 | public required string Email { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazingPizza.Client 10 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/LocalStorage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace BlazingPizza.ComponentsLibrary; 4 | 5 | public static class LocalStorage 6 | { 7 | public static ValueTask GetAsync(IJSRuntime jsRuntime, string key) 8 | => jsRuntime.InvokeAsync("blazorLocalStorage.get", key); 9 | 10 | public static ValueTask SetAsync(IJSRuntime jsRuntime, string key, object value) 11 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.set", key, value); 12 | 13 | public static ValueTask DeleteAsync(IJSRuntime jsRuntime, string key) 14 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.delete", key); 15 | } 16 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/Map/Map.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.JSInterop 2 | @inject IJSRuntime JSRuntime 3 | 4 | The map 5 |
6 | 7 | 8 | @code { 9 | 10 | string elementId = $"map-{Guid.NewGuid().ToString("D")}"; 11 | 12 | [Parameter] public double Zoom { get; set; } 13 | [Parameter, EditorRequired] public List Markers { get; set; } = new(); 14 | 15 | protected override async Task OnAfterRenderAsync(bool firstRender) 16 | { 17 | Console.WriteLine("OnAfterRender"); 18 | await JSRuntime.InvokeVoidAsync( 19 | "deliveryMap.showOrUpdate", 20 | elementId, 21 | Markers); 22 | 23 | await base.OnAfterRenderAsync(firstRender); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/Map/Marker.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Marker 4 | { 5 | public string Description { get; set; } = string.Empty; 6 | 7 | public double X { get; set; } 8 | 9 | public double Y { get; set; } 10 | 11 | public bool ShowPopup { get; set; } 12 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/Map/Point.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Point 4 | { 5 | public double X { get; set; } 6 | 7 | public double Y { get; set; } 8 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/TemplatedDialog.razor: -------------------------------------------------------------------------------- 1 | @if (Show) { 2 | 3 |
4 |
5 | @ChildContent 6 |
7 |
8 | 9 | } 10 | 11 | @code { 12 | 13 | [Parameter, EditorRequired] 14 | public RenderFragment? ChildContent { get; set; } 15 | 16 | [Parameter] 17 | public bool Show { get; set; } 18 | 19 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.ComponentsLibrary/wwwroot/localStorage.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | window.blazorLocalStorage = { 3 | get: key => key in localStorage ? JSON.parse(localStorage[key]) : null, 4 | set: (key, value) => { localStorage[key] = JSON.stringify(value); }, 5 | delete: key => { delete localStorage[key]; } 6 | }; 7 | })(); 8 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Shared/BlazingPizza.Shared.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Shared/IRepository.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public interface IRepository 4 | { 5 | 6 | Task> GetToppings(); 7 | 8 | Task> GetSpecials(); 9 | 10 | Task> GetOrdersAsync(); 11 | 12 | Task> GetOrdersAsync(string userId); 13 | 14 | Task GetOrderWithStatus(int orderId); 15 | 16 | Task GetOrderWithStatus(int orderId, string userId); 17 | 18 | Task PlaceOrder(Order order); 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Shared/LatLong.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class LatLong 4 | { 5 | public LatLong() 6 | { 7 | } 8 | 9 | public LatLong(double latitude, double longitude) : this() 10 | { 11 | Latitude = latitude; 12 | Longitude = longitude; 13 | } 14 | 15 | public double Latitude { get; set; } 16 | 17 | public double Longitude { get; set; } 18 | 19 | public static LatLong Interpolate(LatLong start, LatLong end, double proportion) 20 | { 21 | // The Earth is flat, right? So no need for spherical interpolation. 22 | return new LatLong( 23 | start.Latitude + (end.Latitude - start.Latitude) * proportion, 24 | start.Longitude + (end.Longitude - start.Longitude) * proportion); 25 | } 26 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Shared/NotificationSubscription.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class NotificationSubscription 4 | { 5 | public int? NotificationSubscriptionId { get; set; } 6 | 7 | public string? UserId { get; set; } 8 | 9 | public string? Url { get; set; } 10 | 11 | public string? P256dh { get; set; } 12 | 13 | public string? Auth { get; set; } 14 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Shared/PizzaSpecial.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | /// 4 | /// Represents a pre-configured template for a pizza a user can order 5 | /// 6 | public class PizzaSpecial 7 | { 8 | public int Id { get; set; } 9 | 10 | public string Name { get; set; } = string.Empty; 11 | 12 | public decimal BasePrice { get; set; } 13 | 14 | public string Description { get; set; } = string.Empty; 15 | 16 | public string ImageUrl { get; set; } = "img/pizzas/cheese.jpg"; 17 | 18 | public string GetFormattedBasePrice() => BasePrice.ToString("0.00"); 19 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Shared/PizzaTopping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | 4 | public class PizzaTopping 5 | { 6 | public Topping? Topping { get; set; } 7 | 8 | public int ToppingId { get; set; } 9 | 10 | public int PizzaId { get; set; } 11 | 12 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Shared/Topping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class Topping 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | public decimal Price { get; set; } 10 | 11 | public string GetFormattedPrice() => Price.ToString("0.00"); 12 | 13 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza.Shared/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class UserInfo 4 | { 5 | public bool IsAuthenticated { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Account/IdentityUserAccessor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace BlazingPizza.Components.Account; 4 | 5 | internal sealed class IdentityUserAccessor(UserManager userManager, IdentityRedirectManager redirectManager) 6 | { 7 | public async Task GetRequiredUserAsync(HttpContext context) 8 | { 9 | var user = await userManager.GetUserAsync(context.User); 10 | 11 | if (user is null) 12 | { 13 | redirectManager.RedirectToWithStatus("Account/InvalidUser", $"Error: Unable to load user with ID '{userManager.GetUserId(context.User)}'.", context); 14 | } 15 | 16 | return user; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Account/Pages/AccessDenied.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/AccessDenied" 2 | 3 | Access denied 4 | 5 |
6 |

Access denied

7 |

You do not have access to this resource.

8 |
9 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Account/Pages/ForgotPasswordConfirmation.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/ForgotPasswordConfirmation" 2 | 3 | Forgot password confirmation 4 | 5 |

Forgot password confirmation

6 |

7 | Please check your email to reset your password. 8 |

9 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Account/Pages/InvalidPasswordReset.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/InvalidPasswordReset" 2 | 3 | Invalid password reset 4 | 5 |

Invalid password reset

6 |

7 | The password reset link is invalid. 8 |

9 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Account/Pages/InvalidUser.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/InvalidUser" 2 | 3 | Invalid user 4 | 5 |

Invalid user

6 | 7 | 8 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Account/Pages/Lockout.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/Lockout" 2 | 3 | Locked out 4 | 5 |
6 |

Locked out

7 |

This account has been locked out, please try again later.

8 |
9 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Account/Pages/Manage/_Imports.razor: -------------------------------------------------------------------------------- 1 | @layout ManageLayout 2 | @attribute [Microsoft.AspNetCore.Authorization.Authorize] 3 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Account/Pages/ResetPasswordConfirmation.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/ResetPasswordConfirmation" 2 | Reset password confirmation 3 | 4 |

Reset password confirmation

5 |

6 | Your password has been reset. Please click here to log in. 7 |

8 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Account/Pages/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using BlazingPizza.Components.Account.Shared 2 | @layout AccountLayout 3 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Account/Shared/ManageLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | @layout AccountLayout 3 | 4 |

Manage your account

5 | 6 |
7 |

Change your account settings

8 |
9 |
10 |
11 | 12 |
13 |
14 | @Body 15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Account/Shared/RedirectToLogin.razor: -------------------------------------------------------------------------------- 1 | @inject NavigationManager NavigationManager 2 | 3 | @code { 4 | protected override void OnInitialized() 5 | { 6 | NavigationManager.NavigateTo($"Account/Login?returnUrl={Uri.EscapeDataString(NavigationManager.Uri)}", forceLoad: true); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Layout/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 7 | 8 | 9 | 10 |
Get Pizza
11 |
12 | 13 | 14 | 15 | 16 |
My Orders
17 |
18 |
19 | 20 | 21 | 22 |
23 | 24 |
25 | @Body 26 |
27 | 28 |
29 | An unhandled error has occurred. 30 | Reload 31 | 🗙 32 |
33 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Layout/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | #blazor-error-ui { 2 | background: lightyellow; 3 | bottom: 0; 4 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 5 | display: none; 6 | left: 0; 7 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 8 | position: fixed; 9 | width: 100%; 10 | z-index: 1000; 11 | } 12 | 13 | #blazor-error-ui .dismiss { 14 | cursor: pointer; 15 | position: absolute; 16 | right: 0.75rem; 17 | top: 0.5rem; 18 | } 19 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/Routes.razor: -------------------------------------------------------------------------------- 1 | @using BlazingPizza.Components.Account.Shared 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Authorizing... Please wait 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/Components/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 8 | @using Microsoft.AspNetCore.Components.Web.Virtualization 9 | @using Microsoft.JSInterop 10 | @using BlazingPizza 11 | @using BlazingPizza.Client 12 | @using BlazingPizza.Client.Components 13 | @using BlazingPizza.Components 14 | @using BlazingPizza.ComponentsLibrary 15 | @using BlazingPizza.ComponentsLibrary.Map 16 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/PizzaStoreUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace BlazingPizza; 4 | 5 | public class PizzaStoreUser : IdentityUser 6 | { 7 | } -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2 -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2 -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2 -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2 -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/img/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/img/icon-512.png -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/bacon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/bacon.jpg -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/brit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/brit.jpg -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/cheese.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/cheese.jpg -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/margherita.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/margherita.jpg -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/meaty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/meaty.jpg -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg -------------------------------------------------------------------------------- /save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/salad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/5-Components/BlazingPizza/wwwroot/img/pizzas/salad.jpg -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Client/BootstrapFieldClassProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Forms; 2 | 3 | namespace BlazingPizza.Client; 4 | 5 | public class BootstrapFieldClassProvider : FieldCssClassProvider 6 | { 7 | public override string GetFieldCssClass(EditContext editContext, 8 | in FieldIdentifier fieldIdentifier) 9 | { 10 | var isValid = editContext.IsValid(fieldIdentifier); 11 | 12 | return isValid ? "is-valid" : "is-invalid"; 13 | } 14 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Client/Components/ConfiguredPizzaItem.razor: -------------------------------------------------------------------------------- 1 | 
2 | x 3 |
@(Pizza.Size)" @Pizza.Special?.Name
4 |
    5 | @foreach (var topping in Pizza.Toppings) 6 | { 7 |
  • + @topping.Topping?.Name
  • 8 | } 9 |
10 |
11 | @Pizza.GetFormattedTotalPrice() 12 |
13 |
14 | 15 | @code { 16 | [Parameter, EditorRequired] public Pizza Pizza { get; set; } = new(); 17 | [Parameter, EditorRequired] public EventCallback OnRemoved { get; set; } 18 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Client/Components/OrderReview.razor: -------------------------------------------------------------------------------- 1 | @foreach (var pizza in Order.Pizzas) 2 | { 3 |

4 | 5 | @(pizza.Size)" 6 | @pizza.Special?.Name 7 | (£@pizza.GetFormattedTotalPrice()) 8 | 9 |

10 | 11 |
    12 | @foreach (var topping in pizza.Toppings) 13 | { 14 |
  • + @topping.Topping?.Name
  • 15 | } 16 |
17 | } 18 | 19 |

20 | 21 | Total price: 22 | £@Order.GetFormattedTotalPrice() 23 | 24 |

25 | 26 | @code { 27 | [Parameter, EditorRequired] public Order Order { get; set; } = new(); 28 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Client/JSRuntimeExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace BlazingPizza.Client; 4 | 5 | public static class JSRuntimeExtensions 6 | { 7 | public static ValueTask Confirm(this IJSRuntime jsRuntime, string message) 8 | { 9 | return jsRuntime.InvokeAsync("confirm", message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Client/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Client; 2 | 3 | // Add properties to this class and update the server and client AuthenticationStateProviders 4 | // to expose more information about the authenticated user to the client. 5 | public class UserInfo 6 | { 7 | public required string UserId { get; set; } 8 | public required string Email { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazingPizza.Client 10 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/LocalStorage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace BlazingPizza.ComponentsLibrary; 4 | 5 | public static class LocalStorage 6 | { 7 | public static ValueTask GetAsync(IJSRuntime jsRuntime, string key) 8 | => jsRuntime.InvokeAsync("blazorLocalStorage.get", key); 9 | 10 | public static ValueTask SetAsync(IJSRuntime jsRuntime, string key, object value) 11 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.set", key, value); 12 | 13 | public static ValueTask DeleteAsync(IJSRuntime jsRuntime, string key) 14 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.delete", key); 15 | } 16 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/Map/Map.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.JSInterop 2 | @inject IJSRuntime JSRuntime 3 | 4 | The map 5 |
6 | 7 | 8 | @code { 9 | 10 | string elementId = $"map-{Guid.NewGuid().ToString("D")}"; 11 | 12 | [Parameter] public double Zoom { get; set; } 13 | [Parameter, EditorRequired] public List Markers { get; set; } = new(); 14 | 15 | protected override async Task OnAfterRenderAsync(bool firstRender) 16 | { 17 | Console.WriteLine("OnAfterRender"); 18 | await JSRuntime.InvokeVoidAsync( 19 | "deliveryMap.showOrUpdate", 20 | elementId, 21 | Markers); 22 | 23 | await base.OnAfterRenderAsync(firstRender); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/Map/Marker.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Marker 4 | { 5 | public string Description { get; set; } = string.Empty; 6 | 7 | public double X { get; set; } 8 | 9 | public double Y { get; set; } 10 | 11 | public bool ShowPopup { get; set; } 12 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/Map/Point.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Point 4 | { 5 | public double X { get; set; } 6 | 7 | public double Y { get; set; } 8 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/TemplatedDialog.razor: -------------------------------------------------------------------------------- 1 | @if (Show) { 2 | 3 |
4 |
5 | @ChildContent 6 |
7 |
8 | 9 | } 10 | 11 | @code { 12 | 13 | [Parameter, EditorRequired] 14 | public RenderFragment? ChildContent { get; set; } 15 | 16 | [Parameter] 17 | public bool Show { get; set; } 18 | 19 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.ComponentsLibrary/wwwroot/localStorage.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | window.blazorLocalStorage = { 3 | get: key => key in localStorage ? JSON.parse(localStorage[key]) : null, 4 | set: (key, value) => { localStorage[key] = JSON.stringify(value); }, 5 | delete: key => { delete localStorage[key]; } 6 | }; 7 | })(); 8 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Shared/Address.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace BlazingPizza.Shared; 4 | 5 | public class Address 6 | { 7 | public int Id { get; set; } 8 | 9 | [Required, MaxLength(100)] 10 | public string Name { get; set; } = string.Empty; 11 | 12 | [Required, MaxLength(100)] 13 | public string Line1 { get; set; } = string.Empty; 14 | 15 | [MaxLength(100)] 16 | public string Line2 { get; set; } = string.Empty; 17 | 18 | [Required(ErrorMessage = "We need to know which city to deliver to"), MaxLength(50)] 19 | public string City { get; set; } = string.Empty; 20 | 21 | [Required, MaxLength(20)] 22 | public string Region { get; set; } = string.Empty; 23 | 24 | [Required, MaxLength(20)] 25 | public string PostalCode { get; set; } = string.Empty; 26 | } 27 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Shared/BlazingPizza.Shared.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Shared/IRepository.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public interface IRepository 4 | { 5 | 6 | Task> GetToppings(); 7 | 8 | Task> GetSpecials(); 9 | 10 | Task> GetOrdersAsync(); 11 | 12 | Task> GetOrdersAsync(string userId); 13 | 14 | Task GetOrderWithStatus(int orderId); 15 | 16 | Task GetOrderWithStatus(int orderId, string userId); 17 | 18 | Task PlaceOrder(Order order); 19 | 20 | Task SubscribeToNotifications(NotificationSubscription subscription); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Shared/LatLong.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class LatLong 4 | { 5 | public LatLong() 6 | { 7 | } 8 | 9 | public LatLong(double latitude, double longitude) : this() 10 | { 11 | Latitude = latitude; 12 | Longitude = longitude; 13 | } 14 | 15 | public double Latitude { get; set; } 16 | 17 | public double Longitude { get; set; } 18 | 19 | public static LatLong Interpolate(LatLong start, LatLong end, double proportion) 20 | { 21 | // The Earth is flat, right? So no need for spherical interpolation. 22 | return new LatLong( 23 | start.Latitude + (end.Latitude - start.Latitude) * proportion, 24 | start.Longitude + (end.Longitude - start.Longitude) * proportion); 25 | } 26 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Shared/NotificationSubscription.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class NotificationSubscription 4 | { 5 | public int? NotificationSubscriptionId { get; set; } 6 | 7 | public string? UserId { get; set; } 8 | 9 | public string? Url { get; set; } 10 | 11 | public string? P256dh { get; set; } 12 | 13 | public string? Auth { get; set; } 14 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Shared/PizzaSpecial.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | /// 4 | /// Represents a pre-configured template for a pizza a user can order 5 | /// 6 | public class PizzaSpecial 7 | { 8 | public int Id { get; set; } 9 | 10 | public string Name { get; set; } = string.Empty; 11 | 12 | public decimal BasePrice { get; set; } 13 | 14 | public string Description { get; set; } = string.Empty; 15 | 16 | public string ImageUrl { get; set; } = "img/pizzas/cheese.jpg"; 17 | 18 | public string GetFormattedBasePrice() => BasePrice.ToString("0.00"); 19 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Shared/PizzaTopping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | 4 | public class PizzaTopping 5 | { 6 | public Topping? Topping { get; set; } 7 | 8 | public int ToppingId { get; set; } 9 | 10 | public int PizzaId { get; set; } 11 | 12 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Shared/Topping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class Topping 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | public decimal Price { get; set; } 10 | 11 | public string GetFormattedPrice() => Price.ToString("0.00"); 12 | 13 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza.Shared/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class UserInfo 4 | { 5 | public bool IsAuthenticated { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Account/IdentityUserAccessor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace BlazingPizza.Components.Account; 4 | 5 | internal sealed class IdentityUserAccessor(UserManager userManager, IdentityRedirectManager redirectManager) 6 | { 7 | public async Task GetRequiredUserAsync(HttpContext context) 8 | { 9 | var user = await userManager.GetUserAsync(context.User); 10 | 11 | if (user is null) 12 | { 13 | redirectManager.RedirectToWithStatus("Account/InvalidUser", $"Error: Unable to load user with ID '{userManager.GetUserId(context.User)}'.", context); 14 | } 15 | 16 | return user; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Account/Pages/AccessDenied.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/AccessDenied" 2 | 3 | Access denied 4 | 5 |
6 |

Access denied

7 |

You do not have access to this resource.

8 |
9 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Account/Pages/ForgotPasswordConfirmation.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/ForgotPasswordConfirmation" 2 | 3 | Forgot password confirmation 4 | 5 |

Forgot password confirmation

6 |

7 | Please check your email to reset your password. 8 |

9 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Account/Pages/InvalidPasswordReset.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/InvalidPasswordReset" 2 | 3 | Invalid password reset 4 | 5 |

Invalid password reset

6 |

7 | The password reset link is invalid. 8 |

9 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Account/Pages/InvalidUser.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/InvalidUser" 2 | 3 | Invalid user 4 | 5 |

Invalid user

6 | 7 | 8 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Account/Pages/Lockout.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/Lockout" 2 | 3 | Locked out 4 | 5 |
6 |

Locked out

7 |

This account has been locked out, please try again later.

8 |
9 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Account/Pages/Manage/_Imports.razor: -------------------------------------------------------------------------------- 1 | @layout ManageLayout 2 | @attribute [Microsoft.AspNetCore.Authorization.Authorize] 3 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Account/Pages/ResetPasswordConfirmation.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/ResetPasswordConfirmation" 2 | Reset password confirmation 3 | 4 |

Reset password confirmation

5 |

6 | Your password has been reset. Please click here to log in. 7 |

8 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Account/Pages/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using BlazingPizza.Components.Account.Shared 2 | @layout AccountLayout 3 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Account/Shared/ManageLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | @layout AccountLayout 3 | 4 |

Manage your account

5 | 6 |
7 |

Change your account settings

8 |
9 |
10 |
11 | 12 |
13 |
14 | @Body 15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Account/Shared/RedirectToLogin.razor: -------------------------------------------------------------------------------- 1 | @inject NavigationManager NavigationManager 2 | 3 | @code { 4 | protected override void OnInitialized() 5 | { 6 | NavigationManager.NavigateTo($"Account/Login?returnUrl={Uri.EscapeDataString(NavigationManager.Uri)}", forceLoad: true); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Layout/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 7 | 8 | 9 | 10 |
Get Pizza
11 |
12 | 13 | 14 | 15 | 16 |
My Orders
17 |
18 |
19 | 20 | 21 | 22 |
23 | 24 |
25 | @Body 26 |
27 | 28 |
29 | An unhandled error has occurred. 30 | Reload 31 | 🗙 32 |
33 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Layout/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | #blazor-error-ui { 2 | background: lightyellow; 3 | bottom: 0; 4 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 5 | display: none; 6 | left: 0; 7 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 8 | position: fixed; 9 | width: 100%; 10 | z-index: 1000; 11 | } 12 | 13 | #blazor-error-ui .dismiss { 14 | cursor: pointer; 15 | position: absolute; 16 | right: 0.75rem; 17 | top: 0.5rem; 18 | } 19 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/Routes.razor: -------------------------------------------------------------------------------- 1 | @using BlazingPizza.Components.Account.Shared 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Authorizing... Please wait 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/Components/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 8 | @using Microsoft.AspNetCore.Components.Web.Virtualization 9 | @using Microsoft.JSInterop 10 | @using BlazingPizza 11 | @using BlazingPizza.Client 12 | @using BlazingPizza.Client.Components 13 | @using BlazingPizza.Components 14 | @using BlazingPizza.ComponentsLibrary 15 | @using BlazingPizza.ComponentsLibrary.Map 16 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/PizzaStoreUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace BlazingPizza; 4 | 5 | public class PizzaStoreUser : IdentityUser 6 | { 7 | } -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2 -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2 -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2 -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2 -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/img/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/img/icon-512.png -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/bacon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/bacon.jpg -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/brit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/brit.jpg -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/cheese.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/cheese.jpg -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/margherita.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/margherita.jpg -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/meaty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/meaty.jpg -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/salad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/save-points/6-PWA/BlazingPizza/wwwroot/img/pizzas/salad.jpg -------------------------------------------------------------------------------- /save-points/6-PWA/BlazingPizza/wwwroot/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Blazing Pizza", 3 | "name": "Blazing Pizza", 4 | "icons": [ 5 | { 6 | "src": "img/icon-512.png", 7 | "type": "image/png", 8 | "sizes": "512x512" 9 | } 10 | ], 11 | "start_url": "/", 12 | "background_color": "#860000", 13 | "display": "standalone", 14 | "scope": "/", 15 | "theme_color": "#860000" 16 | } -------------------------------------------------------------------------------- /src/BlazingPizza.Client/BootstrapFieldClassProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Forms; 2 | 3 | namespace BlazingPizza.Client; 4 | 5 | public class BootstrapFieldClassProvider : FieldCssClassProvider 6 | { 7 | public override string GetFieldCssClass(EditContext editContext, 8 | in FieldIdentifier fieldIdentifier) 9 | { 10 | var isValid = editContext.IsValid(fieldIdentifier); 11 | 12 | return isValid ? "is-valid" : "is-invalid"; 13 | } 14 | } -------------------------------------------------------------------------------- /src/BlazingPizza.Client/Components/ConfiguredPizzaItem.razor: -------------------------------------------------------------------------------- 1 | 
2 | x 3 |
@(Pizza.Size)" @Pizza.Special?.Name
4 |
    5 | @foreach (var topping in Pizza.Toppings) 6 | { 7 |
  • + @topping.Topping?.Name
  • 8 | } 9 |
10 |
11 | @Pizza.GetFormattedTotalPrice() 12 |
13 |
14 | 15 | @code { 16 | [Parameter, EditorRequired] public Pizza Pizza { get; set; } = new(); 17 | [Parameter, EditorRequired] public EventCallback OnRemoved { get; set; } 18 | } -------------------------------------------------------------------------------- /src/BlazingPizza.Client/Components/OrderReview.razor: -------------------------------------------------------------------------------- 1 | @foreach (var pizza in Order.Pizzas) 2 | { 3 |

4 | 5 | @(pizza.Size)" 6 | @pizza.Special?.Name 7 | (£@pizza.GetFormattedTotalPrice()) 8 | 9 |

10 | 11 |
    12 | @foreach (var topping in pizza.Toppings) 13 | { 14 |
  • + @topping.Topping?.Name
  • 15 | } 16 |
17 | } 18 | 19 |

20 | 21 | Total price: 22 | £@Order.GetFormattedTotalPrice() 23 | 24 |

25 | 26 | @code { 27 | [Parameter, EditorRequired] public Order Order { get; set; } = new(); 28 | } -------------------------------------------------------------------------------- /src/BlazingPizza.Client/JSRuntimeExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace BlazingPizza.Client; 4 | 5 | public static class JSRuntimeExtensions 6 | { 7 | public static ValueTask Confirm(this IJSRuntime jsRuntime, string message) 8 | { 9 | return jsRuntime.InvokeAsync("confirm", message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/BlazingPizza.Client/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Client; 2 | 3 | // Add properties to this class and update the server and client AuthenticationStateProviders 4 | // to expose more information about the authenticated user to the client. 5 | public class UserInfo 6 | { 7 | public required string UserId { get; set; } 8 | public required string Email { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/BlazingPizza.Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazingPizza.Client 10 | -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/BlazingPizza.ComponentsLibrary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/LocalStorage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace BlazingPizza.ComponentsLibrary; 4 | 5 | public static class LocalStorage 6 | { 7 | public static ValueTask GetAsync(IJSRuntime jsRuntime, string key) 8 | => jsRuntime.InvokeAsync("blazorLocalStorage.get", key); 9 | 10 | public static ValueTask SetAsync(IJSRuntime jsRuntime, string key, object value) 11 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.set", key, value); 12 | 13 | public static ValueTask DeleteAsync(IJSRuntime jsRuntime, string key) 14 | => jsRuntime.InvokeVoidAsync("blazorLocalStorage.delete", key); 15 | } 16 | -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/Map/Map.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.JSInterop 2 | @inject IJSRuntime JSRuntime 3 | 4 | The map 5 |
6 | 7 | 8 | @code { 9 | 10 | string elementId = $"map-{Guid.NewGuid().ToString("D")}"; 11 | 12 | [Parameter] public double Zoom { get; set; } 13 | [Parameter, EditorRequired] public List Markers { get; set; } = new(); 14 | 15 | protected override async Task OnAfterRenderAsync(bool firstRender) 16 | { 17 | Console.WriteLine("OnAfterRender"); 18 | await JSRuntime.InvokeVoidAsync( 19 | "deliveryMap.showOrUpdate", 20 | elementId, 21 | Markers); 22 | 23 | await base.OnAfterRenderAsync(firstRender); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/Map/Marker.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Marker 4 | { 5 | public string Description { get; set; } = string.Empty; 6 | 7 | public double X { get; set; } 8 | 9 | public double Y { get; set; } 10 | 11 | public bool ShowPopup { get; set; } 12 | } -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/Map/Point.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.ComponentsLibrary.Map; 2 | 3 | public class Point 4 | { 5 | public double X { get; set; } 6 | 7 | public double Y { get; set; } 8 | } -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/TemplatedDialog.razor: -------------------------------------------------------------------------------- 1 | @if (Show) { 2 | 3 |
4 |
5 | @ChildContent 6 |
7 |
8 | 9 | } 10 | 11 | @code { 12 | 13 | [Parameter, EditorRequired] 14 | public RenderFragment? ChildContent { get; set; } 15 | 16 | [Parameter] 17 | public bool Show { get; set; } 18 | 19 | } -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/layers.png -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png -------------------------------------------------------------------------------- /src/BlazingPizza.ComponentsLibrary/wwwroot/localStorage.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | window.blazorLocalStorage = { 3 | get: key => key in localStorage ? JSON.parse(localStorage[key]) : null, 4 | set: (key, value) => { localStorage[key] = JSON.stringify(value); }, 5 | delete: key => { delete localStorage[key]; } 6 | }; 7 | })(); 8 | -------------------------------------------------------------------------------- /src/BlazingPizza.Shared/Address.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace BlazingPizza.Shared; 4 | 5 | public class Address 6 | { 7 | public int Id { get; set; } 8 | 9 | [Required, MaxLength(100)] 10 | public string Name { get; set; } = string.Empty; 11 | 12 | [Required, MaxLength(100)] 13 | public string Line1 { get; set; } = string.Empty; 14 | 15 | [MaxLength(100)] 16 | public string Line2 { get; set; } = string.Empty; 17 | 18 | [Required(ErrorMessage = "We need to know which city to deliver to"), MaxLength(50)] 19 | public string City { get; set; } = string.Empty; 20 | 21 | [Required, MaxLength(20)] 22 | public string Region { get; set; } = string.Empty; 23 | 24 | [Required, MaxLength(20)] 25 | public string PostalCode { get; set; } = string.Empty; 26 | } 27 | -------------------------------------------------------------------------------- /src/BlazingPizza.Shared/BlazingPizza.Shared.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/BlazingPizza.Shared/IRepository.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public interface IRepository 4 | { 5 | 6 | Task> GetToppings(); 7 | 8 | Task> GetSpecials(); 9 | 10 | Task> GetOrdersAsync(); 11 | 12 | Task> GetOrdersAsync(string userId); 13 | 14 | Task GetOrderWithStatus(int orderId); 15 | 16 | Task GetOrderWithStatus(int orderId, string userId); 17 | 18 | Task PlaceOrder(Order order); 19 | 20 | Task SubscribeToNotifications(NotificationSubscription subscription); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/BlazingPizza.Shared/LatLong.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class LatLong 4 | { 5 | public LatLong() 6 | { 7 | } 8 | 9 | public LatLong(double latitude, double longitude) : this() 10 | { 11 | Latitude = latitude; 12 | Longitude = longitude; 13 | } 14 | 15 | public double Latitude { get; set; } 16 | 17 | public double Longitude { get; set; } 18 | 19 | public static LatLong Interpolate(LatLong start, LatLong end, double proportion) 20 | { 21 | // The Earth is flat, right? So no need for spherical interpolation. 22 | return new LatLong( 23 | start.Latitude + (end.Latitude - start.Latitude) * proportion, 24 | start.Longitude + (end.Longitude - start.Longitude) * proportion); 25 | } 26 | } -------------------------------------------------------------------------------- /src/BlazingPizza.Shared/NotificationSubscription.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class NotificationSubscription 4 | { 5 | public int? NotificationSubscriptionId { get; set; } 6 | 7 | public string? UserId { get; set; } 8 | 9 | public string? Url { get; set; } 10 | 11 | public string? P256dh { get; set; } 12 | 13 | public string? Auth { get; set; } 14 | } -------------------------------------------------------------------------------- /src/BlazingPizza.Shared/PizzaSpecial.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | /// 4 | /// Represents a pre-configured template for a pizza a user can order 5 | /// 6 | public class PizzaSpecial 7 | { 8 | public int Id { get; set; } 9 | 10 | public string Name { get; set; } = string.Empty; 11 | 12 | public decimal BasePrice { get; set; } 13 | 14 | public string Description { get; set; } = string.Empty; 15 | 16 | public string ImageUrl { get; set; } = "img/pizzas/cheese.jpg"; 17 | 18 | public string GetFormattedBasePrice() => BasePrice.ToString("0.00"); 19 | } -------------------------------------------------------------------------------- /src/BlazingPizza.Shared/PizzaTopping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | 4 | public class PizzaTopping 5 | { 6 | public Topping? Topping { get; set; } 7 | 8 | public int ToppingId { get; set; } 9 | 10 | public int PizzaId { get; set; } 11 | 12 | } -------------------------------------------------------------------------------- /src/BlazingPizza.Shared/Topping.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class Topping 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | public decimal Price { get; set; } 10 | 11 | public string GetFormattedPrice() => Price.ToString("0.00"); 12 | 13 | } -------------------------------------------------------------------------------- /src/BlazingPizza.Shared/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BlazingPizza.Shared; 2 | 3 | public class UserInfo 4 | { 5 | public bool IsAuthenticated { get; set; } 6 | 7 | public string Name { get; set; } = string.Empty; 8 | 9 | } -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Account/IdentityUserAccessor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace BlazingPizza.Components.Account; 4 | 5 | internal sealed class IdentityUserAccessor(UserManager userManager, IdentityRedirectManager redirectManager) 6 | { 7 | public async Task GetRequiredUserAsync(HttpContext context) 8 | { 9 | var user = await userManager.GetUserAsync(context.User); 10 | 11 | if (user is null) 12 | { 13 | redirectManager.RedirectToWithStatus("Account/InvalidUser", $"Error: Unable to load user with ID '{userManager.GetUserId(context.User)}'.", context); 14 | } 15 | 16 | return user; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Account/Pages/AccessDenied.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/AccessDenied" 2 | 3 | Access denied 4 | 5 |
6 |

Access denied

7 |

You do not have access to this resource.

8 |
9 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Account/Pages/ForgotPasswordConfirmation.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/ForgotPasswordConfirmation" 2 | 3 | Forgot password confirmation 4 | 5 |

Forgot password confirmation

6 |

7 | Please check your email to reset your password. 8 |

9 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Account/Pages/InvalidPasswordReset.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/InvalidPasswordReset" 2 | 3 | Invalid password reset 4 | 5 |

Invalid password reset

6 |

7 | The password reset link is invalid. 8 |

9 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Account/Pages/InvalidUser.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/InvalidUser" 2 | 3 | Invalid user 4 | 5 |

Invalid user

6 | 7 | 8 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Account/Pages/Lockout.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/Lockout" 2 | 3 | Locked out 4 | 5 |
6 |

Locked out

7 |

This account has been locked out, please try again later.

8 |
9 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Account/Pages/Manage/_Imports.razor: -------------------------------------------------------------------------------- 1 | @layout ManageLayout 2 | @attribute [Microsoft.AspNetCore.Authorization.Authorize] 3 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Account/Pages/ResetPasswordConfirmation.razor: -------------------------------------------------------------------------------- 1 | @page "/Account/ResetPasswordConfirmation" 2 | Reset password confirmation 3 | 4 |

Reset password confirmation

5 |

6 | Your password has been reset. Please click here to log in. 7 |

8 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Account/Pages/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using BlazingPizza.Components.Account.Shared 2 | @layout AccountLayout 3 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Account/Shared/ManageLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | @layout AccountLayout 3 | 4 |

Manage your account

5 | 6 |
7 |

Change your account settings

8 |
9 |
10 |
11 | 12 |
13 |
14 | @Body 15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Account/Shared/RedirectToLogin.razor: -------------------------------------------------------------------------------- 1 | @inject NavigationManager NavigationManager 2 | 3 | @code { 4 | protected override void OnInitialized() 5 | { 6 | NavigationManager.NavigateTo($"Account/Login?returnUrl={Uri.EscapeDataString(NavigationManager.Uri)}", forceLoad: true); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Layout/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 7 | 8 | 9 | 10 |
Get Pizza
11 |
12 | 13 | 14 | 15 | 16 |
My Orders
17 |
18 |
19 | 20 | 21 | 22 |
23 | 24 |
25 | @Body 26 |
27 | 28 |
29 | An unhandled error has occurred. 30 | Reload 31 | 🗙 32 |
33 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Layout/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | #blazor-error-ui { 2 | background: lightyellow; 3 | bottom: 0; 4 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 5 | display: none; 6 | left: 0; 7 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 8 | position: fixed; 9 | width: 100%; 10 | z-index: 1000; 11 | } 12 | 13 | #blazor-error-ui .dismiss { 14 | cursor: pointer; 15 | position: absolute; 16 | right: 0.75rem; 17 | top: 0.5rem; 18 | } 19 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/Routes.razor: -------------------------------------------------------------------------------- 1 | @using BlazingPizza.Components.Account.Shared 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Authorizing... Please wait 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/BlazingPizza/Components/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 8 | @using Microsoft.AspNetCore.Components.Web.Virtualization 9 | @using Microsoft.JSInterop 10 | @using BlazingPizza 11 | @using BlazingPizza.Client 12 | @using BlazingPizza.Client.Components 13 | @using BlazingPizza.Components 14 | @using BlazingPizza.ComponentsLibrary 15 | @using BlazingPizza.ComponentsLibrary.Map 16 | -------------------------------------------------------------------------------- /src/BlazingPizza/PizzaStoreUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace BlazingPizza; 4 | 5 | public class PizzaStoreUser : IdentityUser 6 | { 7 | } -------------------------------------------------------------------------------- /src/BlazingPizza/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/BlazingPizza/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-300.woff2 -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-500.woff2 -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-700.woff2 -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/css/font/quicksand-v8-latin-regular.woff2 -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/img/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/img/icon-512.png -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/img/pizzas/bacon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/img/pizzas/bacon.jpg -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/img/pizzas/brit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/img/pizzas/brit.jpg -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/img/pizzas/cheese.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/img/pizzas/cheese.jpg -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/img/pizzas/margherita.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/img/pizzas/margherita.jpg -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/img/pizzas/meaty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/img/pizzas/meaty.jpg -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/img/pizzas/mushroom.jpg -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/img/pizzas/pepperoni.jpg -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/img/pizzas/salad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/src/BlazingPizza/wwwroot/img/pizzas/salad.jpg -------------------------------------------------------------------------------- /src/BlazingPizza/wwwroot/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Blazing Pizza", 3 | "name": "Blazing Pizza", 4 | "icons": [ 5 | { 6 | "src": "img/icon-512.png", 7 | "type": "image/png", 8 | "sizes": "512x512" 9 | } 10 | ], 11 | "start_url": "/", 12 | "background_color": "#860000", 13 | "display": "standalone", 14 | "scope": "/", 15 | "theme_color": "#860000" 16 | } -------------------------------------------------------------------------------- /ui-mockup.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csharpfritz/blazor-workshop/c177b2efb9f9ceb27d72afbef31b5d6453db12d0/ui-mockup.pptx --------------------------------------------------------------------------------