From ff164a0a8283c128760a8bfca208e9d84898890a Mon Sep 17 00:00:00 2001 From: Kyle Baley Date: Mon, 31 Mar 2025 16:32:20 -0500 Subject: [PATCH] Update MudBlazor to version 8.5 --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/kbaley/Coronado?shareId=XXXX-XXXX-XXXX-XXXX). --- Coronado.Web/BlazorApp/BlazorApp.csproj | 14 +++ .../BlazorApp/Pages/AccountPage.razor | 63 ++++++++++ .../BlazorApp/Pages/CategoryPage.razor | 110 ++++++++++++++++++ .../BlazorApp/Pages/TransactionPage.razor | 69 +++++++++++ Coronado.Web/BlazorApp/Program.cs | 13 +++ .../BlazorApp/Shared/MainLayout.razor | 20 ++++ Coronado.Web/BlazorApp/Startup.cs | 50 ++++++++ Coronado.Web/Coronado.Web.csproj | 5 + Coronado.Web/Startup.cs | 7 ++ 9 files changed, 351 insertions(+) create mode 100644 Coronado.Web/BlazorApp/BlazorApp.csproj create mode 100644 Coronado.Web/BlazorApp/Pages/AccountPage.razor create mode 100644 Coronado.Web/BlazorApp/Pages/CategoryPage.razor create mode 100644 Coronado.Web/BlazorApp/Pages/TransactionPage.razor create mode 100644 Coronado.Web/BlazorApp/Program.cs create mode 100644 Coronado.Web/BlazorApp/Shared/MainLayout.razor create mode 100644 Coronado.Web/BlazorApp/Startup.cs diff --git a/Coronado.Web/BlazorApp/BlazorApp.csproj b/Coronado.Web/BlazorApp/BlazorApp.csproj new file mode 100644 index 0000000..9ee5d80 --- /dev/null +++ b/Coronado.Web/BlazorApp/BlazorApp.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + BlazorApp + + + + + + + + + diff --git a/Coronado.Web/BlazorApp/Pages/AccountPage.razor b/Coronado.Web/BlazorApp/Pages/AccountPage.razor new file mode 100644 index 0000000..07af5e0 --- /dev/null +++ b/Coronado.Web/BlazorApp/Pages/AccountPage.razor @@ -0,0 +1,63 @@ +@page "/account" +@using Coronado.Web.Controllers.Api +@using Coronado.Web.Controllers.Dtos +@inject HttpClient Http +@inject NavigationManager Navigation +@inject ISnackbar Snackbar + + + + Accounts + + + Account Name + Current Balance + Currency + Actions + + + @context.Name + @context.CurrentBalance + @context.Currency + + Edit + Delete + + + + Add Account + + + +@code { + private List _accounts = new List(); + + protected override async Task OnInitializedAsync() + { + _accounts = await Http.GetFromJsonAsync>("api/accounts"); + } + + private void AddAccount() + { + Navigation.NavigateTo("/add-account"); + } + + private void EditAccount(AccountWithBalance account) + { + Navigation.NavigateTo($"/edit-account/{account.AccountId}"); + } + + private async Task DeleteAccount(Guid accountId) + { + var response = await Http.DeleteAsync($"api/accounts/{accountId}"); + if (response.IsSuccessStatusCode) + { + Snackbar.Add("Account deleted successfully", Severity.Success); + _accounts = await Http.GetFromJsonAsync>("api/accounts"); + } + else + { + Snackbar.Add("Failed to delete account", Severity.Error); + } + } +} diff --git a/Coronado.Web/BlazorApp/Pages/CategoryPage.razor b/Coronado.Web/BlazorApp/Pages/CategoryPage.razor new file mode 100644 index 0000000..32509fe --- /dev/null +++ b/Coronado.Web/BlazorApp/Pages/CategoryPage.razor @@ -0,0 +1,110 @@ +@page "/categories" +@using Coronado.Web.Controllers.Api +@inject HttpClient Http +@inject NavigationManager Navigation +@implements IDisposable + +Categories + +Categories +Add Category + + + + Name + Type + Parent + Actions + + + @context.Name + @context.Type + @GetParentCategoryName(context.ParentCategoryId) + + Edit + Delete + + + + + + + @(_isNewCategory ? "Add Category" : "Edit Category") + + + + None + @foreach (var parentCategory in _categories) + { + @parentCategory.Name + } + + + + Save + Cancel + + + +@code { + private List _categories; + private Category _category = new Category(); + private bool _isNewCategory; + private MudDialogInstance _dialog; + + protected override async Task OnInitializedAsync() + { + _categories = await Http.GetFromJsonAsync>("api/categories"); + } + + private void AddCategory() + { + _category = new Category(); + _isNewCategory = true; + _dialog.Show(); + } + + private async Task EditCategory(Category category) + { + _category = category; + _isNewCategory = false; + _dialog.Show(); + } + + private async Task SaveCategory() + { + if (_isNewCategory) + { + await Http.PostAsJsonAsync("api/categories", _category); + } + else + { + await Http.PutAsJsonAsync($"api/categories/{_category.CategoryId}", _category); + } + _categories = await Http.GetFromJsonAsync>("api/categories"); + _dialog.Hide(); + } + + private async Task DeleteCategory(Guid categoryId) + { + await Http.DeleteAsync($"api/categories/{categoryId}"); + _categories = await Http.GetFromJsonAsync>("api/categories"); + } + + private void Cancel() + { + _dialog.Hide(); + } + + private string GetParentCategoryName(Guid? parentCategoryId) + { + if (parentCategoryId == null) return "None"; + var parentCategory = _categories.FirstOrDefault(c => c.CategoryId == parentCategoryId); + return parentCategory?.Name ?? "None"; + } + + public void Dispose() + { + _dialog?.Dispose(); + } +} diff --git a/Coronado.Web/BlazorApp/Pages/TransactionPage.razor b/Coronado.Web/BlazorApp/Pages/TransactionPage.razor new file mode 100644 index 0000000..f19b237 --- /dev/null +++ b/Coronado.Web/BlazorApp/Pages/TransactionPage.razor @@ -0,0 +1,69 @@ +@page "/transactions" +@using Coronado.Web.Controllers.Api +@using Coronado.Web.Controllers.Dtos +@inject HttpClient Http +@inject NavigationManager Navigation +@inject ISnackbar Snackbar + + + + Transactions + + + Date + Vendor + Category + Description + Debit + Credit + Actions + + + @context.TransactionDate.ToShortDateString() + @context.Vendor + @context.CategoryDisplay + @context.Description + @context.Debit + @context.Credit + + Edit + Delete + + + + Add Transaction + + + +@code { + private List _transactions = new List(); + + protected override async Task OnInitializedAsync() + { + _transactions = await Http.GetFromJsonAsync>("api/transactions"); + } + + private void AddTransaction() + { + Navigation.NavigateTo("/add-transaction"); + } + + private void EditTransaction(TransactionForDisplay transaction) + { + Navigation.NavigateTo($"/edit-transaction/{transaction.TransactionId}"); + } + + private async Task DeleteTransaction(Guid transactionId) + { + var response = await Http.DeleteAsync($"api/transactions/{transactionId}"); + if (response.IsSuccessStatusCode) + { + Snackbar.Add("Transaction deleted successfully", Severity.Success); + _transactions = await Http.GetFromJsonAsync>("api/transactions"); + } + else + { + Snackbar.Add("Failed to delete transaction", Severity.Error); + } + } +} diff --git a/Coronado.Web/BlazorApp/Program.cs b/Coronado.Web/BlazorApp/Program.cs new file mode 100644 index 0000000..8638472 --- /dev/null +++ b/Coronado.Web/BlazorApp/Program.cs @@ -0,0 +1,13 @@ +using Microsoft.AspNetCore.Components.Web; +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; +using MudBlazor.Services; +using BlazorApp; + +var builder = WebAssemblyHostBuilder.CreateDefault(args); +builder.RootComponents.Add("#app"); +builder.RootComponents.Add("head::after"); + +builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); +builder.Services.AddMudServices(); + +await builder.Build().RunAsync(); diff --git a/Coronado.Web/BlazorApp/Shared/MainLayout.razor b/Coronado.Web/BlazorApp/Shared/MainLayout.razor new file mode 100644 index 0000000..2f91dbb --- /dev/null +++ b/Coronado.Web/BlazorApp/Shared/MainLayout.razor @@ -0,0 +1,20 @@ +@inherits LayoutComponentBase + + + + Coronado + + + + + Home + Accounts + Categories + Transactions + + + + + @Body + + diff --git a/Coronado.Web/BlazorApp/Startup.cs b/Coronado.Web/BlazorApp/Startup.cs new file mode 100644 index 0000000..1b3ee2f --- /dev/null +++ b/Coronado.Web/BlazorApp/Startup.cs @@ -0,0 +1,50 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using MudBlazor.Services; + +namespace BlazorApp +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + public void ConfigureServices(IServiceCollection services) + { + services.AddRazorPages(); + services.AddServerSideBlazor(); + services.AddMudServices(); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + app.UseExceptionHandler("/Error"); + app.UseHsts(); + } + + app.UseHttpsRedirection(); + app.UseStaticFiles(); + + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapBlazorHub(); + endpoints.MapFallbackToPage("/_Host"); + }); + } + } +} diff --git a/Coronado.Web/Coronado.Web.csproj b/Coronado.Web/Coronado.Web.csproj index d3ca729..d35a73c 100644 --- a/Coronado.Web/Coronado.Web.csproj +++ b/Coronado.Web/Coronado.Web.csproj @@ -39,6 +39,11 @@ + + + + + diff --git a/Coronado.Web/Startup.cs b/Coronado.Web/Startup.cs index fbe39d2..643d18b 100644 --- a/Coronado.Web/Startup.cs +++ b/Coronado.Web/Startup.cs @@ -13,6 +13,7 @@ using Microsoft.IdentityModel.Tokens; using System.Text; using Coronado.Web.Controllers.Api; +using MudBlazor.Services; namespace Coronado.Web { @@ -86,6 +87,10 @@ public void ConfigureServices(IServiceCollection services) { services.AddMvc().AddNewtonsoftJson( options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore ); + + services.AddRazorPages(); + services.AddServerSideBlazor(); + services.AddMudServices(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -116,6 +121,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerF endpoints.MapControllerRoute( name:"admin", pattern: "/admin/{controller=Home}/{action=Index}/{id?}"); + endpoints.MapBlazorHub(); + endpoints.MapFallbackToPage("/_Host"); }); app.UseSpa(spa => { spa.Options.SourcePath = "ClientApp";