diff --git a/ApplianceRepair.csproj b/ApplianceRepair.csproj index 18175c8..6326251 100644 --- a/ApplianceRepair.csproj +++ b/ApplianceRepair.csproj @@ -22,4 +22,8 @@ + + + + diff --git a/Components/Pages/Home.razor.css b/Components/Pages/Home.razor.css index fee8b4d..71142d2 100644 --- a/Components/Pages/Home.razor.css +++ b/Components/Pages/Home.razor.css @@ -4,6 +4,7 @@ margin: 0; padding: 0; box-sizing: border-box; + font-family: 'StencilBold', sans-serif; } .container { @@ -31,7 +32,7 @@ .logo { font-size: 1.5rem; font-weight: bold; - color: #0056b3; + color: black; } .logo span { @@ -40,13 +41,13 @@ .nav-phone { text-decoration: none; - color: #0056b3; + color: black; font-weight: bold; } /* Hero Section */ .hero { - background: linear-gradient(rgba(0,0,0,0.6), rgba(0,0,0,0.6)), url('https://images.unsplash.com/photo-1581092918056-0c4c3acd3789?auto=format&fit=crop&w=1200&q=80'); + background: linear-gradient(rgba(0,0,0,0.6), rgba(0,0,0,0.6)), url('https://images.unsplash.com/photo-1588854337115-1c67d9247e4d?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'); background-size: cover; background-position: center; color: #fff; @@ -60,7 +61,7 @@ } .hero h1 span { - color: #4cc9f0; + color: #D2B48C; } /* Buttons */ @@ -111,22 +112,22 @@ padding: 30px; border-radius: 8px; text-align: center; - border-bottom: 4px solid #0056b3; + border-bottom: 4px solid #D2B48C; box-shadow: 0 4px 6px rgba(0,0,0,0.05); } /* Trust Section */ .trust { - background: #0056b3; + background: #D2B48C; color: #fff; padding: 40px 0; text-align: center; } .trust .container { -display: flex; -justify-content: space-around; -flex-wrap: wrap; + display: flex; + justify-content: space-around; + flex-wrap: wrap; } .trust-item { diff --git a/Components/Pages/admin/Admin.razor b/Components/Pages/admin/Admin.razor index fa664b1..5472383 100644 --- a/Components/Pages/admin/Admin.razor +++ b/Components/Pages/admin/Admin.razor @@ -2,6 +2,37 @@ @using Microsoft.AspNetCore.Authorization @attribute [Authorize(Roles = "Admin")] @rendermode InteractiveServer +@inject IJSRuntime JS + + + @if (SelectedRequestMedia?.Any() == true) + { +
+ Request: @SelectedRequestMedia[0].RequestNumber + +
+ } + + +
@@ -72,6 +103,7 @@ @foreach (var card in HomePageModel.ServicesCards) {
+
@@ -93,6 +125,7 @@ @foreach (var card in HomePageModel.TrustCards) {
+
@@ -146,6 +179,8 @@ } else if (CurrentTab == AdminTab.Requests) { + +

📋 Service Requests

@@ -187,7 +222,7 @@
- +
} diff --git a/Components/Pages/admin/Admin.razor.cs b/Components/Pages/admin/Admin.razor.cs index d21b581..1be3ab1 100644 --- a/Components/Pages/admin/Admin.razor.cs +++ b/Components/Pages/admin/Admin.razor.cs @@ -1,13 +1,17 @@ using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; namespace ApplianceRepair.Components.Pages.admin { - public partial class Admin(HomePageReader homePageReader, ContentCardReader contentCardReader, BusinessConfigReader businessConfigReader, RepairRequestReader repairRequestReader) : ComponentBase + public partial class Admin(HomePageReader homePageReader, ContentCardReader contentCardReader, BusinessConfigReader businessConfigReader, RepairRequestReader repairRequestReader, RepairRequestMediaReader repairRequestMediaReader) : ComponentBase { public HomePageModel? HomePageModel; public BusinessInfoModel? BusinessInfo; public List? RepairRequests; + public List? SelectedRequestMedia; + public int SelectedRequestMediaImageIndex = 0; + private enum AdminTab { Home, Requests, BusinessInfo } private AdminTab CurrentTab = AdminTab.Home; @@ -28,6 +32,29 @@ namespace ApplianceRepair.Components.Pages.admin }); } + private async void RefreshContentCards() + { + if (HomePageModel == null) + { + return; + } + + var servicesList = await contentCardReader.ReadAllByPageAndGroup(HomePageModel.PageName, nameof(HomePageModel.ContentCardTypes.Services)) ?? []; + var trustList = await contentCardReader.ReadAllByPageAndGroup(HomePageModel.PageName, nameof(HomePageModel.ContentCardTypes.Trust)) ?? []; + + HomePageModel.ServicesCards.Clear(); + foreach (var card in servicesList) + { + HomePageModel.ServicesCards.Add(new ContentCardModel(card)); + } + + HomePageModel.TrustCards.Clear(); + foreach (var card in trustList) + { + HomePageModel.TrustCards.Add(new ContentCardModel(card)); + } + } + private async void RevertHomePageModel() { var businessConfig = await businessConfigReader.ReadLatestRecord() ?? Defaults.DefaultBusinessConfig; @@ -69,6 +96,12 @@ namespace ApplianceRepair.Components.Pages.admin await businessConfigReader.UpdateRecord(BusinessInfo); } + private async Task DeleteContentCard(ContentCardModel card) + { + await contentCardReader.DeleteRecord(card); + RefreshContentCards(); + } + private void AddServiceCard() { HomePageModel?.ServicesCards.Add(new ContentCardModel() { @@ -93,5 +126,58 @@ namespace ApplianceRepair.Components.Pages.admin Text = "Short Description" }); } + + private async Task ViewRequestImages(RepairRequestModel request) + { + if (!string.IsNullOrEmpty(request.RequestNumber)) + { + SelectedRequestMedia = await repairRequestMediaReader.ReadAllByRequestNumber(request.RequestNumber); + SelectedRequestMediaImageIndex = 0; + await JS.InvokeVoidAsync("eval", $"document.getElementById('imageViewerModal').showModal()"); + } + } + + private async Task CloseImageViewer() + { + await JS.InvokeVoidAsync("eval", $"document.getElementById('imageViewerModal').close()"); + SelectedRequestMedia = []; + } + + private async Task ImageViewerModal_PrevImage() + { + if (SelectedRequestMedia == null) return; + + SelectedRequestMediaImageIndex++; + if (SelectedRequestMediaImageIndex >= SelectedRequestMedia.Count()) + { + SelectedRequestMediaImageIndex = 0; + } + } + + private async Task ImageViewerModal_NextImage() + { + if (SelectedRequestMedia == null) return; + SelectedRequestMediaImageIndex--; + if (SelectedRequestMediaImageIndex < 0) + { + SelectedRequestMediaImageIndex = SelectedRequestMedia.Count() - 1; + } + } + + private string GetWebPath(string fullPath = "") + { + if (string.IsNullOrEmpty(fullPath)) return ""; + + var marker = "wwwroot"; + var index = fullPath.IndexOf(marker); + + if (index != -1) + { + // Returns "/uploads/filename.jpg" + return fullPath.Substring(index + marker.Length).Replace('\\', '/'); + } + + return fullPath; + } } } diff --git a/Components/Pages/admin/Admin.razor.css b/Components/Pages/admin/Admin.razor.css index eddde49..486c4d0 100644 --- a/Components/Pages/admin/Admin.razor.css +++ b/Components/Pages/admin/Admin.razor.css @@ -5,6 +5,107 @@ font-family: 'Open Sans', sans-serif; } +/* Image Viewer Modal */ +.image-viewer-modal[open] { + border: none; + border-radius: 12px; + padding: 0; + max-width: 90vw; + width: 1000px; + box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); + background-color: #fff; + overflow: hidden; +} + +.image-viewer-modal::backdrop { + background-color: rgba(0, 0, 0, 0.75); + backdrop-filter: blur(4px); +} + +.image-viewer-modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 1.5rem; + background-color: #f8f9fa; + border-bottom: 1px solid #e9ecef; + font-weight: 600; +} + +.image-viewer-image-stage { + flex-grow: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 400px; + max-height: 70vh; + background-color: #000; + border-radius: 8px; + position: relative; + overflow: hidden; +} + +.image-viewer-image-stage img { + max-width: 100%; + max-height: 100%; + object-fit: contain; + display: block; +} + +.image-viewer-carousel-container { + display: flex; + align-items: center; + padding: 1.5rem; + gap: 1rem; + background-color: #f1f3f5; +} + +.image-viewer-nav-btn { + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: 50%; + width: 45px; + height: 45px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + font-size: 1.2rem; + transition: all 0.2s ease; + box-shadow: 0 4px 6px rgba(0,0,0,0.1); + z-index: 10; +} + +.image-viewer-nav-btn:hover { + background-color: #007bff; + color: white; + transform: scale(1.1); +} + +.image-viewer-nav-btn:active { + transform: scale(0.95); +} + +.image-viewer-image-counter { + position: absolute; + bottom: 10px; + background: rgba(0, 0, 0, 0.6); + color: white; + padding: 4px 12px; + border-radius: 20px; + font-size: 0.85rem; +} + +.image-viewer-no-images { + width: 100%; + text-align: center; + padding: 3rem; + color: #6c757d; + font-style: italic; +} +/* Image viewer modal */ + .admin-header { text-align: center; margin-bottom: 40px; @@ -109,12 +210,12 @@ label { border: 1px solid #e0e6ed; border-radius: 12px; padding: 20px; - transition: transform 0.2s ease; - display: flex; flex-direction: column; align-content: center; + + position: relative; } .content-card:hover { @@ -294,6 +395,17 @@ label { animation: fadeIn 0.5s ease; } +.close-btn { + position: absolute; + top: 5px; + right: 5px; + background: none; + border: none; + font-size: 20px; + cursor: pointer; + line-height: 1; +} + @keyframes fadeIn { from { opacity: 0; diff --git a/wwwroot/uploads/exvwoomm.qgm.jpg b/Components/Pages/admin/Modal.razor similarity index 100% rename from wwwroot/uploads/exvwoomm.qgm.jpg rename to Components/Pages/admin/Modal.razor diff --git a/Migrations/20260424050555_InitialCreate.Designer.cs b/Migrations/20260424050555_InitialCreate.Designer.cs deleted file mode 100644 index 7baa601..0000000 --- a/Migrations/20260424050555_InitialCreate.Designer.cs +++ /dev/null @@ -1,173 +0,0 @@ -// -using System; -using ApplianceRepair; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace ApplianceRepair.Migrations -{ - [DbContext(typeof(DatabaseContext))] - [Migration("20260424050555_InitialCreate")] - partial class InitialCreate - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.12"); - - modelBuilder.Entity("ApplianceRepair.BusinessConfigRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("PhoneNumber") - .HasColumnType("TEXT"); - - b.Property("SupportEmail") - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("BusinessConfig"); - }); - - modelBuilder.Entity("ApplianceRepair.ContentCardRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("BelongsToPage") - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Group") - .HasColumnType("TEXT"); - - b.Property("Header") - .HasColumnType("TEXT"); - - b.Property("Text") - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("ContentCards"); - }); - - modelBuilder.Entity("ApplianceRepair.HomePageRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("BookHeaderText") - .HasColumnType("TEXT"); - - b.Property("CallHeaderText") - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("HeaderLine1") - .HasColumnType("TEXT"); - - b.Property("HeaderLine2") - .HasColumnType("TEXT"); - - b.Property("HeaderText") - .HasColumnType("TEXT"); - - b.Property("SecondaryHeaderText") - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("HomePage"); - }); - - modelBuilder.Entity("ApplianceRepair.RepairRequestMediaRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("MediaPath") - .HasColumnType("TEXT"); - - b.Property("RequestNumber") - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("RepairRequestMedia"); - }); - - modelBuilder.Entity("ApplianceRepair.RepairRequestRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Brand") - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("Notes") - .HasColumnType("TEXT"); - - b.Property("Phone") - .HasColumnType("TEXT"); - - b.Property("RequestNumber") - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("RepairRequests"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Migrations/20260424050555_InitialCreate.cs b/Migrations/20260424050555_InitialCreate.cs deleted file mode 100644 index 40d9bb7..0000000 --- a/Migrations/20260424050555_InitialCreate.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace ApplianceRepair.Migrations -{ - /// - public partial class InitialCreate : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "BusinessConfig", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - CreatedAt = table.Column(type: "TEXT", nullable: false), - UpdatedAt = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", nullable: true), - PhoneNumber = table.Column(type: "TEXT", nullable: true), - SupportEmail = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_BusinessConfig", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "ContentCards", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - CreatedAt = table.Column(type: "TEXT", nullable: false), - UpdatedAt = table.Column(type: "TEXT", nullable: false), - BelongsToPage = table.Column(type: "TEXT", nullable: true), - Group = table.Column(type: "TEXT", nullable: true), - Header = table.Column(type: "TEXT", nullable: true), - Text = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_ContentCards", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "HomePage", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - CreatedAt = table.Column(type: "TEXT", nullable: false), - UpdatedAt = table.Column(type: "TEXT", nullable: false), - HeaderLine1 = table.Column(type: "TEXT", nullable: true), - HeaderLine2 = table.Column(type: "TEXT", nullable: true), - HeaderText = table.Column(type: "TEXT", nullable: true), - CallHeaderText = table.Column(type: "TEXT", nullable: true), - BookHeaderText = table.Column(type: "TEXT", nullable: true), - SecondaryHeaderText = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_HomePage", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "RepairRequestMedia", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - CreatedAt = table.Column(type: "TEXT", nullable: false), - UpdatedAt = table.Column(type: "TEXT", nullable: false), - RequestNumber = table.Column(type: "TEXT", nullable: true), - MediaPath = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_RepairRequestMedia", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "RepairRequests", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - CreatedAt = table.Column(type: "TEXT", nullable: false), - UpdatedAt = table.Column(type: "TEXT", nullable: false), - RequestNumber = table.Column(type: "TEXT", nullable: true), - Type = table.Column(type: "TEXT", nullable: true), - Brand = table.Column(type: "TEXT", nullable: true), - Notes = table.Column(type: "TEXT", nullable: true), - Name = table.Column(type: "TEXT", nullable: true), - Phone = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_RepairRequests", x => x.Id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "BusinessConfig"); - - migrationBuilder.DropTable( - name: "ContentCards"); - - migrationBuilder.DropTable( - name: "HomePage"); - - migrationBuilder.DropTable( - name: "RepairRequestMedia"); - - migrationBuilder.DropTable( - name: "RepairRequests"); - } - } -} diff --git a/Migrations/20260502001727_InitialDeployment.Designer.cs b/Migrations/20260502001727_InitialDeployment.Designer.cs new file mode 100644 index 0000000..c15aec2 --- /dev/null +++ b/Migrations/20260502001727_InitialDeployment.Designer.cs @@ -0,0 +1,421 @@ +// +using System; +using ApplianceRepair; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace ApplianceRepair.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20260502001727_InitialDeployment")] + partial class InitialDeployment + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.12"); + + modelBuilder.Entity("ApplianceRepair.BusinessConfigRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("SupportEmail") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("BusinessConfig"); + }); + + modelBuilder.Entity("ApplianceRepair.ContentCardRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BelongsToPage") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Group") + .HasColumnType("TEXT"); + + b.Property("Header") + .HasColumnType("TEXT"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ContentCards"); + }); + + modelBuilder.Entity("ApplianceRepair.HomePageRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BookHeaderText") + .HasColumnType("TEXT"); + + b.Property("CallHeaderText") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("HeaderLine1") + .HasColumnType("TEXT"); + + b.Property("HeaderLine2") + .HasColumnType("TEXT"); + + b.Property("HeaderText") + .HasColumnType("TEXT"); + + b.Property("SecondaryHeaderText") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("HomePage"); + }); + + modelBuilder.Entity("ApplianceRepair.RepairRequestMediaRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("MediaPath") + .HasColumnType("TEXT"); + + b.Property("RequestNumber") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("RepairRequestMedia"); + }); + + modelBuilder.Entity("ApplianceRepair.RepairRequestRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Brand") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Notes") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Phone") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("RequestNumber") + .HasColumnType("TEXT"); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("RepairRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20260502001727_InitialDeployment.cs b/Migrations/20260502001727_InitialDeployment.cs new file mode 100644 index 0000000..3c10dda --- /dev/null +++ b/Migrations/20260502001727_InitialDeployment.cs @@ -0,0 +1,328 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ApplianceRepair.Migrations +{ + /// + public partial class InitialDeployment : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "TEXT", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + UserName = table.Column(type: "TEXT", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "TEXT", maxLength: 256, nullable: true), + Email = table.Column(type: "TEXT", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "TEXT", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "INTEGER", nullable: false), + PasswordHash = table.Column(type: "TEXT", nullable: true), + SecurityStamp = table.Column(type: "TEXT", nullable: true), + ConcurrencyStamp = table.Column(type: "TEXT", nullable: true), + PhoneNumber = table.Column(type: "TEXT", nullable: true), + PhoneNumberConfirmed = table.Column(type: "INTEGER", nullable: false), + TwoFactorEnabled = table.Column(type: "INTEGER", nullable: false), + LockoutEnd = table.Column(type: "TEXT", nullable: true), + LockoutEnabled = table.Column(type: "INTEGER", nullable: false), + AccessFailedCount = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "BusinessConfig", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedAt = table.Column(type: "TEXT", nullable: false), + UpdatedAt = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: true), + PhoneNumber = table.Column(type: "TEXT", nullable: true), + SupportEmail = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_BusinessConfig", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ContentCards", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedAt = table.Column(type: "TEXT", nullable: false), + UpdatedAt = table.Column(type: "TEXT", nullable: false), + BelongsToPage = table.Column(type: "TEXT", nullable: true), + Group = table.Column(type: "TEXT", nullable: true), + Header = table.Column(type: "TEXT", nullable: true), + Text = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ContentCards", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "HomePage", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedAt = table.Column(type: "TEXT", nullable: false), + UpdatedAt = table.Column(type: "TEXT", nullable: false), + HeaderLine1 = table.Column(type: "TEXT", nullable: true), + HeaderLine2 = table.Column(type: "TEXT", nullable: true), + HeaderText = table.Column(type: "TEXT", nullable: true), + CallHeaderText = table.Column(type: "TEXT", nullable: true), + BookHeaderText = table.Column(type: "TEXT", nullable: true), + SecondaryHeaderText = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_HomePage", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "RepairRequestMedia", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedAt = table.Column(type: "TEXT", nullable: false), + UpdatedAt = table.Column(type: "TEXT", nullable: false), + RequestNumber = table.Column(type: "TEXT", nullable: true), + MediaPath = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_RepairRequestMedia", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "RepairRequests", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedAt = table.Column(type: "TEXT", nullable: false), + UpdatedAt = table.Column(type: "TEXT", nullable: false), + RequestNumber = table.Column(type: "TEXT", nullable: true), + Type = table.Column(type: "TEXT", nullable: false), + Brand = table.Column(type: "TEXT", nullable: false), + Notes = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: false), + Phone = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RepairRequests", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RoleId = table.Column(type: "TEXT", nullable: false), + ClaimType = table.Column(type: "TEXT", nullable: true), + ClaimValue = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(type: "TEXT", nullable: false), + ClaimType = table.Column(type: "TEXT", nullable: true), + ClaimValue = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column(type: "TEXT", nullable: false), + ProviderKey = table.Column(type: "TEXT", nullable: false), + ProviderDisplayName = table.Column(type: "TEXT", nullable: true), + UserId = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column(type: "TEXT", nullable: false), + RoleId = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column(type: "TEXT", nullable: false), + LoginProvider = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: false), + Value = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "BusinessConfig"); + + migrationBuilder.DropTable( + name: "ContentCards"); + + migrationBuilder.DropTable( + name: "HomePage"); + + migrationBuilder.DropTable( + name: "RepairRequestMedia"); + + migrationBuilder.DropTable( + name: "RepairRequests"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + } + } +} diff --git a/Migrations/DatabaseContextModelSnapshot.cs b/Migrations/DatabaseContextModelSnapshot.cs index a642903..549d731 100644 --- a/Migrations/DatabaseContextModelSnapshot.cs +++ b/Migrations/DatabaseContextModelSnapshot.cs @@ -137,24 +137,29 @@ namespace ApplianceRepair.Migrations .HasColumnType("INTEGER"); b.Property("Brand") + .IsRequired() .HasColumnType("TEXT"); b.Property("CreatedAt") .HasColumnType("TEXT"); b.Property("Name") + .IsRequired() .HasColumnType("TEXT"); b.Property("Notes") + .IsRequired() .HasColumnType("TEXT"); b.Property("Phone") + .IsRequired() .HasColumnType("TEXT"); b.Property("RequestNumber") .HasColumnType("TEXT"); b.Property("Type") + .IsRequired() .HasColumnType("TEXT"); b.Property("UpdatedAt") @@ -164,6 +169,249 @@ namespace ApplianceRepair.Migrations b.ToTable("RepairRequests"); }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); #pragma warning restore 612, 618 } } diff --git a/Models.cs b/Models.cs index 1d67b32..ef4621f 100644 --- a/Models.cs +++ b/Models.cs @@ -12,6 +12,9 @@ public ContentCardModel(ContentCardRecord record) { + Id = record.Id; + CreatedAt = record.CreatedAt; + UpdatedAt = record.UpdatedAt; BelongsToPage = record.BelongsToPage; Group = record.Group; Header = record.Header; @@ -98,6 +101,9 @@ List serviceCards, List trustCards) { + Id = homePageRecord.Id; + CreatedAt = homePageRecord.CreatedAt; + UpdatedAt = homePageRecord.UpdatedAt; HeaderLine1 = homePageRecord.HeaderLine1; HeaderLine2 = homePageRecord.HeaderLine2; HeaderText = homePageRecord.HeaderText; @@ -155,6 +161,9 @@ public RepairRequestModel(RepairRequestRecord record) { + Id = record.Id; + CreatedAt = record.CreatedAt; + UpdatedAt = record.UpdatedAt; RequestNumber = record.RequestNumber; Type = record.Type; Brand = record.Brand; @@ -168,6 +177,9 @@ { public BusinessInfoModel(BusinessConfigRecord record) { + Id = record.Id; + CreatedAt = record.CreatedAt; + UpdatedAt = record.UpdatedAt; Name = record.Name; PhoneNumber = record.PhoneNumber; SupportEmail = record.SupportEmail; diff --git a/Program.cs b/Program.cs index 2077491..522f074 100644 --- a/Program.cs +++ b/Program.cs @@ -6,14 +6,14 @@ using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Identity; var builder = WebApplication.CreateBuilder(args); -var connectionString = builder.Configuration.GetConnectionString("DatabaseContextConnectionString") ?? throw new InvalidOperationException("Connection string 'DatabaseContextConnectionString' not found."); +var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); // Add services to the container. builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); builder.Services.AddDbContext(options => - options.UseSqlite("Data Source=site.db")); + options.UseSqlite(connectionString)); builder.Services.AddMemoryCache(); builder.Services.AddLogging(); @@ -45,6 +45,12 @@ builder.Services.AddIdentityCore(options => options.SignIn.Require .AddSignInManager() .AddDefaultTokenProviders(); +builder.Services.AddServerSideBlazor() + .AddHubOptions(options => + { + options.MaximumReceiveMessageSize = 10 * 1024 * 1024; // 10MB + }); + builder.Services.AddSingleton, IdentityNoOpEmailSender>(); var app = builder.Build(); diff --git a/Services.cs b/Services.cs index eb7bf8f..2f4b603 100644 --- a/Services.cs +++ b/Services.cs @@ -27,7 +27,7 @@ namespace ApplianceRepair } else { - db.HomePage.Update(record); + db.Entry(found).CurrentValues.SetValues(record); } await db.SaveChangesAsync(); } @@ -60,10 +60,20 @@ namespace ApplianceRepair } else { - db.ContentCards.Update(record); + db.Entry(found).CurrentValues.SetValues(record); } await db.SaveChangesAsync(); } + + public async Task DeleteRecord(ContentCardRecord record) + { + var found = db.ContentCards.Where((card) => card.Id == record.Id).FirstOrDefault(); + if (found != null) + { + db.ContentCards.Remove(found); + await db.SaveChangesAsync(); + } + } } public class BusinessConfigReader(DatabaseContext db) @@ -88,7 +98,7 @@ namespace ApplianceRepair } else { - db.BusinessConfig.Update(record); + db.Entry(found).CurrentValues.SetValues(record); } await db.SaveChangesAsync(); } @@ -121,7 +131,7 @@ namespace ApplianceRepair } else { - db.RepairRequests.Update(record); + db.Entry(found).CurrentValues.SetValues(record); } await db.SaveChangesAsync(); } diff --git a/appsettings.json b/appsettings.json index b7a4f8c..8abf816 100644 --- a/appsettings.json +++ b/appsettings.json @@ -7,7 +7,7 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - "DatabaseContextConnectionString": "Data Source=site.db" + "DefaultConnection": "Data Source=/var/www/site_data/site.db" }, - "SiteDomain": "titanappliancerepair.net" + "SiteDomain": "yoursitename.net" } \ No newline at end of file diff --git a/wwwroot/app.css b/wwwroot/app.css index f9c1cfc..3a3849c 100644 --- a/wwwroot/app.css +++ b/wwwroot/app.css @@ -1,5 +1,13 @@ @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@600;700&family=Open+Sans:wght@400;600&display=swap'); +@font-face { + font-family: 'StencilBold'; + src: url('fonts/Stencil Std Bold.ttf') format('truetype'); + font-weight: Bold; + font-style: normal; + font-display: swap; +} + h1:focus { outline: none; } diff --git a/wwwroot/fonts/Stencil Std Bold.ttf b/wwwroot/fonts/Stencil Std Bold.ttf new file mode 100644 index 0000000..3b7fb96 Binary files /dev/null and b/wwwroot/fonts/Stencil Std Bold.ttf differ diff --git a/wwwroot/uploads/uefue0ou.esy.png b/wwwroot/uploads/uefue0ou.esy.png deleted file mode 100644 index bfb0ff7..0000000 Binary files a/wwwroot/uploads/uefue0ou.esy.png and /dev/null differ