diff --git a/.gitignore b/.gitignore index 9074a90..0b0ccae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ bin obj *.db* +wwwroot/uploads diff --git a/Controllers/OrderController.cs b/Controllers/OrderController.cs index a98f514..412bcf3 100644 --- a/Controllers/OrderController.cs +++ b/Controllers/OrderController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using OneForMe.Data; using OneForMe.Models; +using System.IO; namespace OneForMe.Controllers; @@ -24,7 +25,7 @@ public class OrderController : Controller // POST: Order/Create [HttpPost] - public async Task Create(Order order, string[] itemNames, string[] itemPrices) + public async Task Create(Order order, string[] itemNames, string[] itemPrices, IFormFile? ImageFile) { if (!ModelState.IsValid) return View(); @@ -32,6 +33,34 @@ public class OrderController : Controller order.OrderCode = GenerateOrderCode(); order.CreatorName = User.Identity?.Name ?? "Unknown"; + // Handle image upload + if (ImageFile != null && ImageFile.Length > 0) + { + try + { + var uploadsFolder = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "uploads", "orders"); + if (!Directory.Exists(uploadsFolder)) + { + Directory.CreateDirectory(uploadsFolder); + } + + var uniqueFileName = $"{order.OrderCode}_{Guid.NewGuid()}_{Path.GetFileName(ImageFile.FileName)}"; + var filePath = Path.Combine(uploadsFolder, uniqueFileName); + + using (var fileStream = new FileStream(filePath, FileMode.Create)) + { + await ImageFile.CopyToAsync(fileStream); + } + + order.ImagePath = $"/uploads/orders/{uniqueFileName}"; + } + catch (Exception ex) + { + ModelState.AddModelError("ImageFile", $"Error uploading file: {ex.Message}"); + return View(); + } + } + _context.Orders.Add(order); await _context.SaveChangesAsync(); diff --git a/Migrations/20251130093329_AddAdditionalInfoAndImagePath.Designer.cs b/Migrations/20251130093329_AddAdditionalInfoAndImagePath.Designer.cs new file mode 100644 index 0000000..105f370 --- /dev/null +++ b/Migrations/20251130093329_AddAdditionalInfoAndImagePath.Designer.cs @@ -0,0 +1,408 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using OneForMe.Data; + +#nullable disable + +namespace OneForMe.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20251130093329_AddAdditionalInfoAndImagePath")] + partial class AddAdditionalInfoAndImagePath + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.0-rc.2.25502.107"); + + 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("OneForMe.Models.MenuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("OrderId") + .HasColumnType("INTEGER"); + + b.Property("Price") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.ToTable("MenuItems"); + }); + + modelBuilder.Entity("OneForMe.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AdditionalInfo") + .HasColumnType("TEXT"); + + b.Property("ClosedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatorName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ImagePath") + .HasColumnType("TEXT"); + + b.Property("IsClosed") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("OrderCode") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrderCode") + .IsUnique(); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("OneForMe.Models.OrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("MenuItemId") + .HasColumnType("INTEGER"); + + b.Property("OrderId") + .HasColumnType("INTEGER"); + + b.Property("OrderedAt") + .HasColumnType("TEXT"); + + b.Property("ParticipantEmail") + .HasColumnType("TEXT"); + + b.Property("ParticipantName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("MenuItemId"); + + b.HasIndex("OrderId"); + + b.ToTable("OrderItems"); + }); + + 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(); + }); + + modelBuilder.Entity("OneForMe.Models.MenuItem", b => + { + b.HasOne("OneForMe.Models.Order", "Order") + .WithMany("MenuItems") + .HasForeignKey("OrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Order"); + }); + + modelBuilder.Entity("OneForMe.Models.OrderItem", b => + { + b.HasOne("OneForMe.Models.MenuItem", "MenuItem") + .WithMany("OrderItems") + .HasForeignKey("MenuItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OneForMe.Models.Order", "Order") + .WithMany("OrderItems") + .HasForeignKey("OrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MenuItem"); + + b.Navigation("Order"); + }); + + modelBuilder.Entity("OneForMe.Models.MenuItem", b => + { + b.Navigation("OrderItems"); + }); + + modelBuilder.Entity("OneForMe.Models.Order", b => + { + b.Navigation("MenuItems"); + + b.Navigation("OrderItems"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20251130093329_AddAdditionalInfoAndImagePath.cs b/Migrations/20251130093329_AddAdditionalInfoAndImagePath.cs new file mode 100644 index 0000000..10f0fa5 --- /dev/null +++ b/Migrations/20251130093329_AddAdditionalInfoAndImagePath.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace OneForMe.Migrations +{ + /// + public partial class AddAdditionalInfoAndImagePath : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AdditionalInfo", + table: "Orders", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "ImagePath", + table: "Orders", + type: "TEXT", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "AdditionalInfo", + table: "Orders"); + + migrationBuilder.DropColumn( + name: "ImagePath", + table: "Orders"); + } + } +} diff --git a/Migrations/20251130093404_AddAdditionalInfoAndImageToOrder.Designer.cs b/Migrations/20251130093404_AddAdditionalInfoAndImageToOrder.Designer.cs new file mode 100644 index 0000000..a376f7b --- /dev/null +++ b/Migrations/20251130093404_AddAdditionalInfoAndImageToOrder.Designer.cs @@ -0,0 +1,408 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using OneForMe.Data; + +#nullable disable + +namespace OneForMe.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20251130093404_AddAdditionalInfoAndImageToOrder")] + partial class AddAdditionalInfoAndImageToOrder + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.0-rc.2.25502.107"); + + 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("OneForMe.Models.MenuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("OrderId") + .HasColumnType("INTEGER"); + + b.Property("Price") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.ToTable("MenuItems"); + }); + + modelBuilder.Entity("OneForMe.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AdditionalInfo") + .HasColumnType("TEXT"); + + b.Property("ClosedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatorName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ImagePath") + .HasColumnType("TEXT"); + + b.Property("IsClosed") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("OrderCode") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrderCode") + .IsUnique(); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("OneForMe.Models.OrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("MenuItemId") + .HasColumnType("INTEGER"); + + b.Property("OrderId") + .HasColumnType("INTEGER"); + + b.Property("OrderedAt") + .HasColumnType("TEXT"); + + b.Property("ParticipantEmail") + .HasColumnType("TEXT"); + + b.Property("ParticipantName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Quantity") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("MenuItemId"); + + b.HasIndex("OrderId"); + + b.ToTable("OrderItems"); + }); + + 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(); + }); + + modelBuilder.Entity("OneForMe.Models.MenuItem", b => + { + b.HasOne("OneForMe.Models.Order", "Order") + .WithMany("MenuItems") + .HasForeignKey("OrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Order"); + }); + + modelBuilder.Entity("OneForMe.Models.OrderItem", b => + { + b.HasOne("OneForMe.Models.MenuItem", "MenuItem") + .WithMany("OrderItems") + .HasForeignKey("MenuItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("OneForMe.Models.Order", "Order") + .WithMany("OrderItems") + .HasForeignKey("OrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MenuItem"); + + b.Navigation("Order"); + }); + + modelBuilder.Entity("OneForMe.Models.MenuItem", b => + { + b.Navigation("OrderItems"); + }); + + modelBuilder.Entity("OneForMe.Models.Order", b => + { + b.Navigation("MenuItems"); + + b.Navigation("OrderItems"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20251130093404_AddAdditionalInfoAndImageToOrder.cs b/Migrations/20251130093404_AddAdditionalInfoAndImageToOrder.cs new file mode 100644 index 0000000..8d43238 --- /dev/null +++ b/Migrations/20251130093404_AddAdditionalInfoAndImageToOrder.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace OneForMe.Migrations +{ + /// + public partial class AddAdditionalInfoAndImageToOrder : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/Migrations/ApplicationDbContextModelSnapshot.cs b/Migrations/ApplicationDbContextModelSnapshot.cs index 6a1ff83..a02e928 100644 --- a/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Migrations/ApplicationDbContextModelSnapshot.cs @@ -238,6 +238,9 @@ namespace OneForMe.Migrations .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); + b.Property("AdditionalInfo") + .HasColumnType("TEXT"); + b.Property("ClosedAt") .HasColumnType("TEXT"); @@ -248,6 +251,9 @@ namespace OneForMe.Migrations .IsRequired() .HasColumnType("TEXT"); + b.Property("ImagePath") + .HasColumnType("TEXT"); + b.Property("IsClosed") .HasColumnType("INTEGER"); diff --git a/Models/Order.cs b/Models/Order.cs index 017a415..67fd1b4 100644 --- a/Models/Order.cs +++ b/Models/Order.cs @@ -6,6 +6,8 @@ public class Order public string OrderCode { get; set; } = string.Empty; public string CreatorName { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; + public string? AdditionalInfo { get; set; } + public string? ImagePath { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? ClosedAt { get; set; } public bool IsClosed { get; set; } = false; diff --git a/Resources/SharedResources.de.resx b/Resources/SharedResources.de.resx index 6fef943..fd217a3 100644 --- a/Resources/SharedResources.de.resx +++ b/Resources/SharedResources.de.resx @@ -279,4 +279,19 @@ {0} € + + Zusätzliche Informationen + + + Zusätzliche Informationen eingeben (optional) + + + Bild hochladen + + + Erstellt von + + + Erstellt am + \ No newline at end of file diff --git a/Resources/SharedResources.en.resx b/Resources/SharedResources.en.resx index 45c2430..a3c2e07 100644 --- a/Resources/SharedResources.en.resx +++ b/Resources/SharedResources.en.resx @@ -279,4 +279,16 @@ ${0} + + Additional Information + + + Enter additional information (optional) + + + Upload Image + + + Created on + \ No newline at end of file diff --git a/Views/Order/Create.cshtml b/Views/Order/Create.cshtml index 35748b5..75ba423 100644 --- a/Views/Order/Create.cshtml +++ b/Views/Order/Create.cshtml @@ -12,13 +12,25 @@

@Localizer["CreateNewOrder"]

-
+
@Localizer["GiveOrderName"]
+
+ + + Optional: Add notes, special instructions, or other details +
+ +
+ + + Optional: Upload an image for this order (JPG, PNG, etc.) +
+
@Localizer["MenuItems"]
diff --git a/Views/Order/Details.cshtml b/Views/Order/Details.cshtml index 81760bf..d945d67 100644 --- a/Views/Order/Details.cshtml +++ b/Views/Order/Details.cshtml @@ -15,6 +15,15 @@

@Model.Name

@Localizer.Get("Code"): @Model.OrderCode

@Localizer.Get("CreatedBy"): @Model.CreatorName

+

@Localizer.Get("CreatedOn"): @Model.CreatedAt.ToString("g")

+ @if (!string.IsNullOrEmpty(Model.ImagePath)) + { + Order Image + } + @if (!string.IsNullOrEmpty(Model.AdditionalInfo)) + { +

@Model.AdditionalInfo

+ }

@Localizer.Get("Status"): @(Model.IsClosed ? Localizer.Get("Closed") : Localizer.Get("Open"))

diff --git a/Views/Order/Join.cshtml b/Views/Order/Join.cshtml index 2457d75..a76fe27 100644 --- a/Views/Order/Join.cshtml +++ b/Views/Order/Join.cshtml @@ -15,6 +15,16 @@

@Model.Name

@Localizer["Code"]: @Model.OrderCode

@Localizer["CreatedBy"]: @Model.CreatorName

+ + @if (!string.IsNullOrEmpty(Model.ImagePath)) + { + Order Image + } + + @if (!string.IsNullOrEmpty(Model.AdditionalInfo)) + { +

@Model.AdditionalInfo

+ }