From ffd96132800dd1837aee7a60553b6d7277962ef9 Mon Sep 17 00:00:00 2001 From: Isaiah Clifford Opoku Date: Wed, 5 Feb 2025 15:14:01 +0000 Subject: [PATCH] Adding of new video project --- BlazorCRUD/BlazorCrudApp.sln | 22 +++ BlazorCRUD/BlazorCrudApp/BlazorCrudApp.csproj | 19 ++ BlazorCRUD/BlazorCrudApp/Components/App.razor | 21 ++ .../Components/Layout/MainLayout.razor | 104 ++++++++++ .../Components/Layout/NavMenu.razor | 10 + .../Components/Pages/Counter.razor | 18 ++ .../Components/Pages/CreateEmployee.razor | 58 ++++++ .../Components/Pages/DeleteConfirmation.razor | 35 ++++ .../Components/Pages/EditEmployee.razor | 72 +++++++ .../Components/Pages/Employees.razor | 180 ++++++++++++++++++ .../Components/Pages/Error.razor | 36 ++++ .../BlazorCrudApp/Components/Pages/Home.razor | 58 ++++++ .../BlazorCrudApp/Components/Pages/Test.razor | 3 + .../BlazorCrudApp/Components/Routes.razor | 6 + .../BlazorCrudApp/Components/_Imports.razor | 12 ++ BlazorCRUD/BlazorCrudApp/Data/AppDbContext.cs | 12 ++ BlazorCRUD/BlazorCrudApp/Domain/Contracts.cs | 37 ++++ BlazorCRUD/BlazorCrudApp/Domain/Employee.cs | 15 ++ .../20250126104549_InitialCreate.Designer.cs | 59 ++++++ .../20250126104549_InitialCreate.cs | 38 ++++ .../Migrations/AppDbContextModelSnapshot.cs | 56 ++++++ BlazorCRUD/BlazorCrudApp/Program.cs | 46 +++++ .../Properties/launchSettings.json | 23 +++ .../BlazorCrudApp/Service/EmployeeService.cs | 95 +++++++++ .../BlazorCrudApp/Service/IEmployeeService.cs | 13 ++ .../appsettings.Development.json | 13 ++ BlazorCRUD/BlazorCrudApp/appsettings.json | 9 + BlazorCRUD/BlazorCrudApp/wwwroot/favicon.ico | Bin 0 -> 15086 bytes 28 files changed, 1070 insertions(+) create mode 100644 BlazorCRUD/BlazorCrudApp.sln create mode 100644 BlazorCRUD/BlazorCrudApp/BlazorCrudApp.csproj create mode 100644 BlazorCRUD/BlazorCrudApp/Components/App.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Components/Layout/MainLayout.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Components/Layout/NavMenu.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Components/Pages/Counter.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Components/Pages/CreateEmployee.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Components/Pages/DeleteConfirmation.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Components/Pages/EditEmployee.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Components/Pages/Employees.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Components/Pages/Error.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Components/Pages/Home.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Components/Pages/Test.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Components/Routes.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Components/_Imports.razor create mode 100644 BlazorCRUD/BlazorCrudApp/Data/AppDbContext.cs create mode 100644 BlazorCRUD/BlazorCrudApp/Domain/Contracts.cs create mode 100644 BlazorCRUD/BlazorCrudApp/Domain/Employee.cs create mode 100644 BlazorCRUD/BlazorCrudApp/Migrations/20250126104549_InitialCreate.Designer.cs create mode 100644 BlazorCRUD/BlazorCrudApp/Migrations/20250126104549_InitialCreate.cs create mode 100644 BlazorCRUD/BlazorCrudApp/Migrations/AppDbContextModelSnapshot.cs create mode 100644 BlazorCRUD/BlazorCrudApp/Program.cs create mode 100644 BlazorCRUD/BlazorCrudApp/Properties/launchSettings.json create mode 100644 BlazorCRUD/BlazorCrudApp/Service/EmployeeService.cs create mode 100644 BlazorCRUD/BlazorCrudApp/Service/IEmployeeService.cs create mode 100644 BlazorCRUD/BlazorCrudApp/appsettings.Development.json create mode 100644 BlazorCRUD/BlazorCrudApp/appsettings.json create mode 100644 BlazorCRUD/BlazorCrudApp/wwwroot/favicon.ico diff --git a/BlazorCRUD/BlazorCrudApp.sln b/BlazorCRUD/BlazorCrudApp.sln new file mode 100644 index 0000000..7c643dd --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35506.116 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorCrudApp", "BlazorCrudApp\BlazorCrudApp.csproj", "{FDA7E2F7-A15D-4464-8171-381DAFFCED43}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FDA7E2F7-A15D-4464-8171-381DAFFCED43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDA7E2F7-A15D-4464-8171-381DAFFCED43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDA7E2F7-A15D-4464-8171-381DAFFCED43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDA7E2F7-A15D-4464-8171-381DAFFCED43}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/BlazorCRUD/BlazorCrudApp/BlazorCrudApp.csproj b/BlazorCRUD/BlazorCrudApp/BlazorCrudApp.csproj new file mode 100644 index 0000000..e3dfc76 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/BlazorCrudApp.csproj @@ -0,0 +1,19 @@ + + + + net9.0 + enable + enable + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + \ No newline at end of file diff --git a/BlazorCRUD/BlazorCrudApp/Components/App.razor b/BlazorCRUD/BlazorCrudApp/Components/App.razor new file mode 100644 index 0000000..3e291fc --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/App.razor @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BlazorCRUD/BlazorCrudApp/Components/Layout/MainLayout.razor b/BlazorCRUD/BlazorCrudApp/Components/Layout/MainLayout.razor new file mode 100644 index 0000000..b43ff14 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/Layout/MainLayout.razor @@ -0,0 +1,104 @@ +@inherits LayoutComponentBase + + + + + + + + + Application + + + + + + + + + @Body + + + + +
+ An unhandled error has occurred. + Reload + 🗙 +
+ +@code { + private bool _drawerOpen = true; + private bool _isDarkMode = true; + private MudTheme? _theme = null; + + protected override void OnInitialized() + { + base.OnInitialized(); + + _theme = new() + { + PaletteLight = _lightPalette, + PaletteDark = _darkPalette, + LayoutProperties = new LayoutProperties() + }; + } + + + private void DrawerToggle() + { + _drawerOpen = !_drawerOpen; + } + + private void DarkModeToggle() + { + _isDarkMode = !_isDarkMode; + } + + private readonly PaletteLight _lightPalette = new() + { + Black = "#110e2d", + AppbarText = "#424242", + AppbarBackground = "rgba(255,255,255,0.8)", + DrawerBackground = "#ffffff", + GrayLight = "#e8e8e8", + GrayLighter = "#f9f9f9", + }; + + private readonly PaletteDark _darkPalette = new() + { + Primary = "#7e6fff", + Surface = "#1e1e2d", + Background = "#1a1a27", + BackgroundGray = "#151521", + AppbarText = "#92929f", + AppbarBackground = "rgba(26,26,39,0.8)", + DrawerBackground = "#1a1a27", + ActionDefault = "#74718e", + ActionDisabled = "#9999994d", + ActionDisabledBackground = "#605f6d4d", + TextPrimary = "#b2b0bf", + TextSecondary = "#92929f", + TextDisabled = "#ffffff33", + DrawerIcon = "#92929f", + DrawerText = "#92929f", + GrayLight = "#2a2833", + GrayLighter = "#1e1e2d", + Info = "#4a86ff", + Success = "#3dcb6c", + Warning = "#ffb545", + Error = "#ff3f5f", + LinesDefault = "#33323e", + TableLines = "#33323e", + Divider = "#292838", + OverlayLight = "#1e1e2d80", + }; + + public string DarkLightModeButtonIcon => _isDarkMode switch + { + true => Icons.Material.Rounded.AutoMode, + false => Icons.Material.Outlined.DarkMode, + }; +} + + diff --git a/BlazorCRUD/BlazorCrudApp/Components/Layout/NavMenu.razor b/BlazorCRUD/BlazorCrudApp/Components/Layout/NavMenu.razor new file mode 100644 index 0000000..3f08809 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/Layout/NavMenu.razor @@ -0,0 +1,10 @@ + + + Home + Counter + + Weather + + + + diff --git a/BlazorCRUD/BlazorCrudApp/Components/Pages/Counter.razor b/BlazorCRUD/BlazorCrudApp/Components/Pages/Counter.razor new file mode 100644 index 0000000..db95bf3 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/Pages/Counter.razor @@ -0,0 +1,18 @@ +@page "/counter" + +Counter + +Counter + +Current count: @currentCount + +Click me + +@code { + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } +} diff --git a/BlazorCRUD/BlazorCrudApp/Components/Pages/CreateEmployee.razor b/BlazorCRUD/BlazorCrudApp/Components/Pages/CreateEmployee.razor new file mode 100644 index 0000000..8f9bb57 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/Pages/CreateEmployee.razor @@ -0,0 +1,58 @@ +@using BlazorCrudApp.Domain +@using BlazorCrudApp.Service +@inject IEmployeeService EmployeeService +@inject ISnackbar Snackbar +@inject IDialogService DialogService + + + + + + + + Male + Female + Other + + + + + + + + Cancel + Create + + + +@code { + [CascadingParameter] IMudDialogInstance MudDialog { get; set; } = default!; + private MudForm form = default!; + private CreateEmployeeDto model = new(); + + private void Cancel() + { + MudDialog.Cancel(); + } + + private async Task Submit() + { + await form.Validate(); + if (form.IsValid) + { + try + { + await EmployeeService.CreateEmployeeAsync(model); + Snackbar.Add("Employee created successfully", Severity.Success); + MudDialog.Close(DialogResult.Ok(true)); + } + catch (Exception) + { + Snackbar.Add("Error creating employee", Severity.Error); + } + } + } +} diff --git a/BlazorCRUD/BlazorCrudApp/Components/Pages/DeleteConfirmation.razor b/BlazorCRUD/BlazorCrudApp/Components/Pages/DeleteConfirmation.razor new file mode 100644 index 0000000..1765f44 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/Pages/DeleteConfirmation.razor @@ -0,0 +1,35 @@ +@using MudBlazor +@inject IDialogService DialogService +@inject ISnackbar Snackbar + + + + + + Confirm Deletion + + + + + Are you sure you want to delete this employee? + This action cannot be undone. + + + + Cancel + Delete + + + +@code { + [CascadingParameter] IMudDialogInstance MudDialog { get; set; } + [Parameter] public Guid EmployeeId { get; set; } + [Parameter] public string Message { get; set; } + + + private void Cancel() => MudDialog.Cancel(); + + private void Submit() => MudDialog.Close(DialogResult.Ok(true)); +} diff --git a/BlazorCRUD/BlazorCrudApp/Components/Pages/EditEmployee.razor b/BlazorCRUD/BlazorCrudApp/Components/Pages/EditEmployee.razor new file mode 100644 index 0000000..f8a807f --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/Pages/EditEmployee.razor @@ -0,0 +1,72 @@ +@using BlazorCrudApp.Domain +@using BlazorCrudApp.Service +@using MudBlazor +@inject IEmployeeService EmployeeService +@inject ISnackbar Snackbar + + + + + + + Edit Employee + + + + + + + Male + Female + + + + + + + Cancel + Update + + + +@code { + [CascadingParameter] IMudDialogInstance Dialog { get; set; } + + [Parameter] public EmployeeDetailsDto Employee { get; set; } + [Parameter] public string Title { get; set; } + + + private MudForm form; + private UpdateEmployeeDto model = new(); + + protected override void OnInitialized() + { + model.Id = Employee.Id; + model.EmployeName = Employee.EmployeName; + model.Gender = Employee.Gender; + model.City = Employee.City; + } + + private void Cancel() => Dialog.Cancel(); + + private async Task Submit() + { + await form.Validate(); + if (form.IsValid) + { + try + { + await EmployeeService.UpdateEmployeeAsync(model); + Snackbar.Add("Employee updated successfully", Severity.Success); + Dialog.Close(DialogResult.Ok(true)); + } + catch (Exception) + { + Snackbar.Add("Error updating employee", Severity.Error); + } + } + } +} diff --git a/BlazorCRUD/BlazorCrudApp/Components/Pages/Employees.razor b/BlazorCRUD/BlazorCrudApp/Components/Pages/Employees.razor new file mode 100644 index 0000000..e7942ee --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/Pages/Employees.razor @@ -0,0 +1,180 @@ +@page "/" +@using BlazorCrudApp.Domain +@using BlazorCrudApp.Service +@inject IEmployeeService EmployeeService +@inject IDialogService DialogService +@inject ISnackbar Snackbar + + + + + + Employee Directory + + New Employee + + + + + @if (_loading) + { + + } + + + + Team Members (@_employees.Count) + + + + + + @(context.Item.EmployeName[0]) + + @context.Item.EmployeName + + + + + + @context.Item.Gender + + + + + + + @context.Item.City + + + + + + + +
+ +
+
+ +
+
+
+ +
+
+ + + +
+
+
+
+
+ + +@code { + private List _employees = new(); + private bool _loading = true; + private string _searchString = string.Empty; + + protected override async Task OnInitializedAsync() + { + await LoadEmployees(); + + } + + private async Task LoadEmployees() + { + try + { + _loading = true; + StateHasChanged(); + + _employees = (await EmployeeService.GetAllEmployeesAsync()).ToList(); + } + catch (Exception ex) + { + Snackbar.Add("Failed to load employees", Severity.Error); + // Consider logging the exception here + } + finally + { + _loading = false; + StateHasChanged(); + } + } + + + @* Delete Dialog *@ + + private async Task OpenEditDialog(EmployeeDetailsDto employee) + { + var parameters = new DialogParameters + { + ["Employee"] = employee, + ["Title"] = $"Edit Employee: {employee.EmployeName}" + }; + + var dialog = await DialogService.ShowAsync("Edit Employee", parameters); + var result = await dialog.Result; + + if (!result.Canceled) + { + await LoadEmployees(); + Snackbar.Add("Employee updated successfully", Severity.Success); + } + } + + + + @* Delete Dialog *@ + private async Task OpenDeleteDialog(Guid employeeId) + { + var parameters = new DialogParameters + { + ["EmployeeId"] = employeeId, + ["Message"] = "Are you sure you want to delete this employee? This action cannot be undone." + }; + + var dialog = await DialogService.ShowAsync("Confirm Deletion", parameters); + var result = await dialog.Result; + + if (!result.Canceled) + { + try + { + await EmployeeService.DeleteEmployeeAsync(employeeId); + await LoadEmployees(); + Snackbar.Add("Employee deleted successfully", Severity.Success); + } + catch (Exception) + { + Snackbar.Add("Failed to delete employee", Severity.Error); + } + } + } + + + + @* Create Dialog *@ + + private async Task OpenCreateDialog() + { + var dialog = await DialogService.ShowAsync("Add New Employee"); + var result = await dialog.Result; + + if (!result.Canceled) + { + await LoadEmployees(); + Snackbar.Add("Employee created successfully", Severity.Success); + } + } +} diff --git a/BlazorCRUD/BlazorCrudApp/Components/Pages/Error.razor b/BlazorCRUD/BlazorCrudApp/Components/Pages/Error.razor new file mode 100644 index 0000000..576cc2d --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/Pages/Error.razor @@ -0,0 +1,36 @@ +@page "/Error" +@using System.Diagnostics + +Error + +

Error.

+

An error occurred while processing your request.

+ +@if (ShowRequestId) +{ +

+ Request ID: @RequestId +

+} + +

Development Mode

+

+ Swapping to Development environment will display more detailed information about the error that occurred. +

+

+ The Development environment shouldn't be enabled for deployed applications. + It can result in displaying sensitive information from exceptions to end users. + For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development + and restarting the app. +

+ +@code{ + [CascadingParameter] + private HttpContext? HttpContext { get; set; } + + private string? RequestId { get; set; } + private bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + + protected override void OnInitialized() => + RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier; +} diff --git a/BlazorCRUD/BlazorCrudApp/Components/Pages/Home.razor b/BlazorCRUD/BlazorCrudApp/Components/Pages/Home.razor new file mode 100644 index 0000000..e6fb5ba --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/Pages/Home.razor @@ -0,0 +1,58 @@ + +Home + +Hello, world! +Welcome to your new app, powered by MudBlazor and the .NET 9 Template! + + + You can find documentation and examples on our website here: + + www.mudblazor.com + + + +
+Interactivity in this Template +
+ + When you opt for the "Global" Interactivity Location,
+ the render modes are defined in App.razor and consequently apply to all child components.
+ In this case, providers are globally set in the MainLayout.
+
+ On the other hand, if you choose the "Per page/component" Interactivity Location,
+ it is necessary to include the
+
+ <MudPopoverProvider />
+ <MudDialogProvider />
+ <MudSnackbarProvider />
+
+ components on every interactive page.
+
+ If a render mode is not specified for a page, it defaults to Server-Side Rendering (SSR),
+ similar to this page. While MudBlazor allows pages to be rendered in SSR,
+ please note that interactive features, such as buttons and dropdown menus, will not be functional. +
+ +
+What's New in Blazor with the Release of .NET 9 +
+ +Prerendering + + If you're exploring the features of .NET 9 Blazor,
you might be pleasantly surprised to learn that each page is prerendered on the server,
regardless of the selected render mode.

+ This means that you'll need to inject all necessary services on the server,
even when opting for the wasm (WebAssembly) render mode.

+ This prerendering functionality is crucial to ensuring that WebAssembly mode feels fast and responsive,
especially when it comes to initial page load times.

+ For more information on how to detect prerendering and leverage the RenderContext, you can refer to the following link: + + More details + +
+ +
+InteractiveAuto + + A discussion on how to achieve this can be found here: + + More details + + diff --git a/BlazorCRUD/BlazorCrudApp/Components/Pages/Test.razor b/BlazorCRUD/BlazorCrudApp/Components/Pages/Test.razor new file mode 100644 index 0000000..144faf5 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/Pages/Test.razor @@ -0,0 +1,3 @@ +@page "/test" + +Basic Test Page diff --git a/BlazorCRUD/BlazorCrudApp/Components/Routes.razor b/BlazorCRUD/BlazorCrudApp/Components/Routes.razor new file mode 100644 index 0000000..3572203 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/Routes.razor @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/BlazorCRUD/BlazorCrudApp/Components/_Imports.razor b/BlazorCRUD/BlazorCrudApp/Components/_Imports.razor new file mode 100644 index 0000000..e39f84a --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Components/_Imports.razor @@ -0,0 +1,12 @@ +@using System.Net.Http +@using System.Net.Http.Json +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using static Microsoft.AspNetCore.Components.Web.RenderMode +@using Microsoft.AspNetCore.Components.Web.Virtualization +@using Microsoft.JSInterop +@using MudBlazor +@using MudBlazor.Services +@using BlazorCrudApp +@using BlazorCrudApp.Components diff --git a/BlazorCRUD/BlazorCrudApp/Data/AppDbContext.cs b/BlazorCRUD/BlazorCrudApp/Data/AppDbContext.cs new file mode 100644 index 0000000..d8924b4 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Data/AppDbContext.cs @@ -0,0 +1,12 @@ +using BlazorCrudApp.Domain; +using Microsoft.EntityFrameworkCore; + +namespace BlazorCrudApp.Data +{ + public class AppDbContext : DbContext + { + public AppDbContext(DbContextOptions options) : base(options) { } + + public DbSet Employees { get; set; } + } +} diff --git a/BlazorCRUD/BlazorCrudApp/Domain/Contracts.cs b/BlazorCRUD/BlazorCrudApp/Domain/Contracts.cs new file mode 100644 index 0000000..769825c --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Domain/Contracts.cs @@ -0,0 +1,37 @@ +using System.ComponentModel.DataAnnotations; + +namespace BlazorCrudApp.Domain +{ + public class CreateEmployeeDto + { + [Required] + public string EmployeName { get; set; } + [Required] + public string Gender { get; set; } + [Required] + public string City { get; set; } + } + + public class UpdateEmployeeDto + { + [Required] + public Guid Id { get; set; } + [Required] + public string EmployeName { get; set; } + [Required] + public string Gender { get; set; } + [Required] + public string City { get; set; } + public DateTime LastUpdatedAt { get; set; } + } + + public class EmployeeDetailsDto + { + public Guid Id { get; set; } + public string EmployeName { get; set; } + public string Gender { get; set; } + public string City { get; set; } + public DateTime CreatedAt { get; set; } + public DateTime LastUpdatedAt { get; set; } + } +} diff --git a/BlazorCRUD/BlazorCrudApp/Domain/Employee.cs b/BlazorCRUD/BlazorCrudApp/Domain/Employee.cs new file mode 100644 index 0000000..53a4b94 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Domain/Employee.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace BlazorCrudApp.Domain +{ + public class Employee + { + [Key] + public Guid Id { get; set; } + public string EmployeName { get; set; } + public string Gender { get; set; } + public string City { get; set; } + public DateTime CreatedAt { get; set; } + public DateTime LastUpdatedAt { get; set; } + } +} diff --git a/BlazorCRUD/BlazorCrudApp/Migrations/20250126104549_InitialCreate.Designer.cs b/BlazorCRUD/BlazorCrudApp/Migrations/20250126104549_InitialCreate.Designer.cs new file mode 100644 index 0000000..cdb0355 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Migrations/20250126104549_InitialCreate.Designer.cs @@ -0,0 +1,59 @@ +// +using System; +using BlazorCrudApp.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace BlazorCrudApp.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20250126104549_InitialCreate")] + partial class InitialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("BlazorCrudApp.Domain.Employee", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("EmployeName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Employees"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BlazorCRUD/BlazorCrudApp/Migrations/20250126104549_InitialCreate.cs b/BlazorCRUD/BlazorCrudApp/Migrations/20250126104549_InitialCreate.cs new file mode 100644 index 0000000..10f3041 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Migrations/20250126104549_InitialCreate.cs @@ -0,0 +1,38 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BlazorCrudApp.Migrations +{ + /// + public partial class InitialCreate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Employees", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + EmployeName = table.Column(type: "nvarchar(max)", nullable: false), + Gender = table.Column(type: "nvarchar(max)", nullable: false), + City = table.Column(type: "nvarchar(max)", nullable: false), + CreatedAt = table.Column(type: "datetime2", nullable: false), + LastUpdatedAt = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Employees", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Employees"); + } + } +} diff --git a/BlazorCRUD/BlazorCrudApp/Migrations/AppDbContextModelSnapshot.cs b/BlazorCRUD/BlazorCrudApp/Migrations/AppDbContextModelSnapshot.cs new file mode 100644 index 0000000..2903436 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Migrations/AppDbContextModelSnapshot.cs @@ -0,0 +1,56 @@ +// +using System; +using BlazorCrudApp.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace BlazorCrudApp.Migrations +{ + [DbContext(typeof(AppDbContext))] + partial class AppDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("BlazorCrudApp.Domain.Employee", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("EmployeName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Employees"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BlazorCRUD/BlazorCrudApp/Program.cs b/BlazorCRUD/BlazorCrudApp/Program.cs new file mode 100644 index 0000000..28db926 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Program.cs @@ -0,0 +1,46 @@ +using BlazorCrudApp.Components; +using BlazorCrudApp.Data; +using BlazorCrudApp.Service; +using Microsoft.EntityFrameworkCore; +using MudBlazor.Services; + +var builder = WebApplication.CreateBuilder(args); + + + +// Add MudBlazor services +builder.Services.AddMudServices(); + + + +builder.Services.AddDbContext(options => +{ + options.UseSqlServer(builder.Configuration.GetConnectionString("sqlConnection")); +}); + +builder.Services.AddScoped(); + +// Add services to the container. +builder.Services.AddRazorComponents() + .AddInteractiveServerComponents(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (!app.Environment.IsDevelopment()) +{ + app.UseExceptionHandler("/Error", createScopeForErrors: true); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); +} + +app.UseHttpsRedirection(); + + +app.UseAntiforgery(); + +app.MapStaticAssets(); +app.MapRazorComponents() + .AddInteractiveServerRenderMode(); + +app.Run(); diff --git a/BlazorCRUD/BlazorCrudApp/Properties/launchSettings.json b/BlazorCRUD/BlazorCrudApp/Properties/launchSettings.json new file mode 100644 index 0000000..b88471f --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5079", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:7036;http://localhost:5079", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } + } diff --git a/BlazorCRUD/BlazorCrudApp/Service/EmployeeService.cs b/BlazorCRUD/BlazorCrudApp/Service/EmployeeService.cs new file mode 100644 index 0000000..2e94c0c --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Service/EmployeeService.cs @@ -0,0 +1,95 @@ +using BlazorCrudApp.Data; +using BlazorCrudApp.Domain; +using Microsoft.EntityFrameworkCore; + +namespace BlazorCrudApp.Service +{ + public class EmployeeService : IEmployeeService + { + private readonly AppDbContext _appDbContext; + + public EmployeeService(AppDbContext appDbContext) + { + _appDbContext = appDbContext; + } + + public async Task> GetAllEmployeesAsync() + { + return await _appDbContext.Employees + .Select(e => new EmployeeDetailsDto + { + Id = e.Id, + EmployeName = e.EmployeName, + Gender = e.Gender, + City = e.City, + CreatedAt = e.CreatedAt, + LastUpdatedAt = e.LastUpdatedAt + }) + .ToListAsync(); + } + + public async Task GetEmployeeByIdAsync(Guid id) + { + var employee = await _appDbContext.Employees.FindAsync(id); + if (employee == null) + { + throw new KeyNotFoundException("Employee not found"); + } + + return new EmployeeDetailsDto + { + Id = employee.Id, + EmployeName = employee.EmployeName, + Gender = employee.Gender, + City = employee.City, + CreatedAt = employee.CreatedAt, + LastUpdatedAt = employee.LastUpdatedAt + }; + } + + public async Task CreateEmployeeAsync(CreateEmployeeDto createEmployeeDto) + { + var employee = new Employee + { + Id = Guid.NewGuid(), + EmployeName = createEmployeeDto.EmployeName, + Gender = createEmployeeDto.Gender, + City = createEmployeeDto.City, + CreatedAt = DateTime.UtcNow, + LastUpdatedAt = DateTime.UtcNow + }; + + _appDbContext.Employees.Add(employee); + await _appDbContext.SaveChangesAsync(); + } + + public async Task UpdateEmployeeAsync(UpdateEmployeeDto updateEmployeeDto) + { + var employee = await _appDbContext.Employees.FindAsync(updateEmployeeDto.Id); + if (employee == null) + { + throw new KeyNotFoundException("Employee not found"); + } + + employee.EmployeName = updateEmployeeDto.EmployeName; + employee.Gender = updateEmployeeDto.Gender; + employee.City = updateEmployeeDto.City; + employee.LastUpdatedAt = DateTime.UtcNow; + + _appDbContext.Employees.Update(employee); + await _appDbContext.SaveChangesAsync(); + } + + public async Task DeleteEmployeeAsync(Guid id) + { + var employee = await _appDbContext.Employees.FindAsync(id); + if (employee == null) + { + throw new KeyNotFoundException("Employee not found"); + } + + _appDbContext.Employees.Remove(employee); + await _appDbContext.SaveChangesAsync(); + } + } +} diff --git a/BlazorCRUD/BlazorCrudApp/Service/IEmployeeService.cs b/BlazorCRUD/BlazorCrudApp/Service/IEmployeeService.cs new file mode 100644 index 0000000..420b976 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/Service/IEmployeeService.cs @@ -0,0 +1,13 @@ +using BlazorCrudApp.Domain; + +namespace BlazorCrudApp.Service +{ + public interface IEmployeeService + { + Task> GetAllEmployeesAsync(); + Task GetEmployeeByIdAsync(Guid id); + Task CreateEmployeeAsync(CreateEmployeeDto createEmployeeDto); + Task UpdateEmployeeAsync(UpdateEmployeeDto updateEmployeeDto); + Task DeleteEmployeeAsync(Guid id); + } +} diff --git a/BlazorCRUD/BlazorCrudApp/appsettings.Development.json b/BlazorCRUD/BlazorCrudApp/appsettings.Development.json new file mode 100644 index 0000000..74c37ef --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/appsettings.Development.json @@ -0,0 +1,13 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "DetailedErrors": true, + "ConnectionStrings": { + "sqlConnection": "Server=localhost;Database=blazor_app_db;Integrated Security=true;TrustServerCertificate=true;" + }, + "AllowedHosts": "*" +} diff --git a/BlazorCRUD/BlazorCrudApp/appsettings.json b/BlazorCRUD/BlazorCrudApp/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/BlazorCRUD/BlazorCrudApp/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/BlazorCRUD/BlazorCrudApp/wwwroot/favicon.ico b/BlazorCRUD/BlazorCrudApp/wwwroot/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..12392236657563eb8cc764f235e66d568b3a0fbb GIT binary patch literal 15086 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