diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..41559b6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "dotnet.defaultSolution": "Aberwyn.sln" +} \ No newline at end of file diff --git a/Aberwyn/Controllers/AdminController.cs b/Aberwyn/Controllers/AdminController.cs index 3412677..0b8050d 100644 --- a/Aberwyn/Controllers/AdminController.cs +++ b/Aberwyn/Controllers/AdminController.cs @@ -2,20 +2,42 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Aberwyn.Models; +using Aberwyn.Data; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; + namespace Aberwyn.Controllers { + [Authorize(Roles = "Admin")] public class AdminController : Controller { private readonly UserManager _userManager; private readonly RoleManager _roleManager; + private readonly IConfiguration _configuration; + private readonly IHostEnvironment _env; + private readonly MenuService _menuService; + +private readonly ApplicationDbContext _context; + +public AdminController( + IConfiguration configuration, + IHostEnvironment env, + MenuService menuService, + ApplicationDbContext context, + UserManager userManager, + RoleManager roleManager) +{ + _configuration = configuration; + _env = env; + _menuService = menuService; + _context = context; + _userManager = userManager; + _roleManager = roleManager; +} + - public AdminController(UserManager userManager, RoleManager roleManager) - { - _userManager = userManager; - _roleManager = roleManager; - } public async Task Index() { @@ -86,6 +108,84 @@ namespace Aberwyn.Controllers return RedirectToAction("Index"); } + [HttpPost] +[Authorize(Roles = "Admin")] +public IActionResult ImportMealsFromProd() +{ + var prodService = MenuService.CreateWithConfig(_configuration, _env, useProdDb: true); + var devService = new MenuService(_context); // injicerad context används + + var prodMeals = prodService.GetMealsDetailed(); + + foreach (var meal in prodMeals) + { + // Kopiera utan ID (för att undvika konflikt) och spara + var newMeal = new Meal + { + Name = meal.Name, + Description = meal.Description, + ProteinType = meal.ProteinType, + Category = meal.Category, + CarbType = meal.CarbType, + RecipeUrl = meal.RecipeUrl, + ImageUrl = meal.ImageUrl, + IsAvailable = meal.IsAvailable, + CreatedAt = meal.CreatedAt, + Instructions = meal.Instructions, + ImageData = meal.ImageData, + ImageMimeType = meal.ImageMimeType, + Ingredients = meal.Ingredients.Select(i => new Ingredient + { + Quantity = i.Quantity, + Item = i.Item + }).ToList() + }; + + devService.SaveOrUpdateMealWithIngredients(newMeal); + } + + return Content("Import klar!"); +} +[HttpPost] +[Authorize(Roles = "Admin")] +[HttpPost] +[Authorize(Roles = "Admin")] +public IActionResult ImportMenusFromProd() +{ + var prodService = MenuService.CreateWithConfig(_configuration, _env, useProdDb: true); + var devService = new MenuService(_context); + + var allProdMenus = prodService.GetAllWeeklyMenus(); + var allMeals = devService.GetMeals(); + + foreach (var menu in allProdMenus) + { + var newMenu = new WeeklyMenu + { + DayOfWeek = menu.DayOfWeek, + BreakfastMealId = menu.BreakfastMealName != null + ? allMeals.FirstOrDefault(m => m.Name == menu.BreakfastMealName)?.Id + : null, + LunchMealId = menu.LunchMealName != null + ? allMeals.FirstOrDefault(m => m.Name == menu.LunchMealName)?.Id + : null, + DinnerMealId = menu.DinnerMealName != null + ? allMeals.FirstOrDefault(m => m.Name == menu.DinnerMealName)?.Id + : null, + WeekNumber = menu.WeekNumber, + Year = menu.Year, + Cook = menu.Cook + }; + + _context.WeeklyMenus.Add(newMenu); + } + + _context.SaveChanges(); + TempData["Message"] = "Import av veckomenyer klar."; + return RedirectToAction("Index"); +} + + } public class AdminUserViewModel diff --git a/Aberwyn/Controllers/FoodMenuController.cs b/Aberwyn/Controllers/FoodMenuController.cs index 429c84a..f0143d2 100644 --- a/Aberwyn/Controllers/FoodMenuController.cs +++ b/Aberwyn/Controllers/FoodMenuController.cs @@ -23,6 +23,7 @@ namespace Aberwyn.Controllers public FoodMenuController(MenuService menuService, IConfiguration configuration, IHostEnvironment env, ApplicationDbContext context) { _menuService = menuService; + _configuration = configuration; _env = env; _context = context; @@ -61,10 +62,10 @@ namespace Aberwyn.Controllers return RedirectToAction("PizzaOrder"); } - // Stt session s vi vet att det r en uppdatering + // S�tt session s� vi vet att det �r en uppdatering HttpContext.Session.SetInt32("LastPizzaOrderId", order.Id); - // Visa formulret + // Visa formul�ret TempData["ForceShowForm"] = "true"; return RedirectToAction("PizzaOrder"); @@ -85,7 +86,7 @@ namespace Aberwyn.Controllers { if (string.IsNullOrWhiteSpace(customerName) || string.IsNullOrWhiteSpace(pizzaName)) { - TempData["Error"] = "Fyll i bde namn och pizza!"; + TempData["Error"] = "Fyll i b�de namn och pizza!"; return RedirectToAction("PizzaOrder"); } @@ -101,10 +102,10 @@ namespace Aberwyn.Controllers order.CustomerName = customerName.Trim(); order.PizzaName = pizzaName.Trim(); order.IngredientsJson = ingredients; - order.Status = "Unconfirmed";// terstll status om du vill + order.Status = "Unconfirmed";// �terst�ll status om du vill _context.SaveChanges(); - TempData["Success"] = $"Din bestllning har uppdaterats!"; + TempData["Success"] = $"Din best�llning har uppdaterats!"; return RedirectToAction("PizzaOrder"); } } @@ -126,7 +127,7 @@ namespace Aberwyn.Controllers HttpContext.Session.SetInt32("LastPizzaOrderId", order.Id); - TempData["Success"] = $"Tack {order.CustomerName}! Din pizza r bestlld!"; + TempData["Success"] = $"Tack {order.CustomerName}! Din pizza �r best�lld!"; return RedirectToAction("PizzaOrder"); } @@ -182,7 +183,7 @@ namespace Aberwyn.Controllers [Authorize(Roles = "Chef")] public IActionResult Veckomeny(int? week, int? year) { - var menuService = new MenuService(_configuration, _env); + var menuService = _menuService; var today = DateTime.Today; int resolvedWeek = week ?? ISOWeek.GetWeekOfYear(today); @@ -195,7 +196,6 @@ namespace Aberwyn.Controllers WeekNumber = resolvedWeek, Year = resolvedYear, WeeklyMenus = menus, - AvailableCooks = menuService.GetUsers() }; var recent = menuService @@ -219,24 +219,24 @@ namespace Aberwyn.Controllers public IActionResult AddMealAjax([FromBody] Meal meal) { if (meal == null || string.IsNullOrWhiteSpace(meal.Name)) - return BadRequest("Ogiltigt mltidsobjekt."); + return BadRequest("Ogiltigt m�ltidsobjekt."); - var service = new MenuService(_configuration, _env); + var service = _menuService; - // Kontrollera om en mltid med samma namn redan finns + // Kontrollera om en m�ltid med samma namn redan finns var existing = service.GetMeals() .FirstOrDefault(m => m.Name.Equals(meal.Name, StringComparison.OrdinalIgnoreCase)); if (existing == null) { - // Fyll i CreatedAt om det inte stts automatiskt i databasen + // Fyll i CreatedAt om det inte s�tts automatiskt i databasen meal.CreatedAt = DateTime.Now; service.SaveOrUpdateMeal(meal); existing = meal; } else { - // Om mltiden finns men saknar data (t.ex. r bara ett namn) kan vi uppdatera den + // Om m�ltiden finns men saknar data (t.ex. �r bara ett namn) kan vi uppdatera den existing.Description = meal.Description; existing.ProteinType = meal.ProteinType; existing.CarbType = meal.CarbType; @@ -258,7 +258,7 @@ namespace Aberwyn.Controllers public IActionResult MealAdmin() { - var service = new MenuService(_configuration, _env); + var service = _menuService; var meals = service.GetMealsDetailed(); return View("MealAdmin", meals); } @@ -269,7 +269,7 @@ namespace Aberwyn.Controllers if (string.IsNullOrWhiteSpace(term)) return Json(new List()); - var menuService = new MenuService(_configuration, _env); + var menuService = _menuService; var meals = menuService.GetMeals(); var result = meals @@ -285,7 +285,7 @@ namespace Aberwyn.Controllers [HttpPost] public IActionResult SaveVeckomeny(IFormCollection form, int week, int year) { - var menuService = new MenuService(_configuration, _env); + var menuService = _menuService; var allMeals = menuService.GetMeals(); var model = new MenuViewModel @@ -368,6 +368,7 @@ namespace Aberwyn.Controllers return RedirectToAction("Veckomeny", new { week, year }); } + private bool GetRestaurantStatus() { var value = _context.AppSettings.FirstOrDefault(s => s.Key == "RestaurantIsOpen")?.Value; @@ -436,7 +437,7 @@ namespace Aberwyn.Controllers [Authorize(Roles = "Chef")] public IActionResult UpdatePizzaAvailability(List availableIds) { - availableIds ??= new List(); // Om null, erstt med tom lista + availableIds ??= new List(); // Om null, ers�tt med tom lista var allPizzas = _menuService.GetMealsByCategory("Pizza"); diff --git a/Aberwyn/Controllers/MealController.cs b/Aberwyn/Controllers/MealController.cs index 75df2a5..5e7b194 100644 --- a/Aberwyn/Controllers/MealController.cs +++ b/Aberwyn/Controllers/MealController.cs @@ -9,6 +9,7 @@ namespace Aberwyn.Controllers { private readonly IConfiguration _configuration; private readonly IHostEnvironment _env; + private readonly MenuService _menuService; public MealController(IConfiguration configuration, IHostEnvironment env) { @@ -18,7 +19,7 @@ namespace Aberwyn.Controllers [HttpGet] public IActionResult View(int id, bool edit = false) { - var service = new MenuService(_configuration, _env); + var service = _menuService; var meal = service.GetMealById(id); ViewData["IsEditing"] = edit; // → här @@ -37,7 +38,7 @@ namespace Aberwyn.Controllers { try { - var service = new MenuService(_configuration, _env); + var service = _menuService; var meal = service.GetMealById(id); if (meal == null) @@ -75,7 +76,7 @@ namespace Aberwyn.Controllers [HttpGet] public IActionResult Edit(int? id) { - var service = new MenuService(_configuration, _env); + var service = _menuService; var meal = id.HasValue ? service.GetMealById(id.Value) : new Meal(); return View("Meal", meal); } @@ -83,7 +84,7 @@ namespace Aberwyn.Controllers [HttpPost] public IActionResult SaveMeal(Meal meal, IFormFile ImageFile, string ExistingImageUrl) { - var service = new MenuService(_configuration, _env); + var service = _menuService; if (ImageFile != null && ImageFile.Length > 0) { @@ -116,7 +117,7 @@ namespace Aberwyn.Controllers [HttpPost] public IActionResult DeleteMeal(int id) { - var service = new MenuService(_configuration, _env); + var service = _menuService; //service.DeleteMeal(id); return RedirectToAction("Edit"); // eller tillbaka till lista } diff --git a/Aberwyn/Controllers/MealMenuApiController.cs b/Aberwyn/Controllers/MealMenuApiController.cs index 20bf044..840e42e 100644 --- a/Aberwyn/Controllers/MealMenuApiController.cs +++ b/Aberwyn/Controllers/MealMenuApiController.cs @@ -13,9 +13,9 @@ namespace Aberwyn.Controllers { private readonly MenuService _menuService; - public MealMenuApiController(IConfiguration configuration, IHostEnvironment env) + public MealMenuApiController(MenuService menuService, IConfiguration configuration, IHostEnvironment env) { - _menuService = new MenuService(configuration, env); + _menuService = menuService; } [HttpGet("menu")] diff --git a/Aberwyn/Data/ApplicationDbContext.cs b/Aberwyn/Data/ApplicationDbContext.cs index 79d7bcb..8e1845b 100644 --- a/Aberwyn/Data/ApplicationDbContext.cs +++ b/Aberwyn/Data/ApplicationDbContext.cs @@ -11,6 +11,14 @@ namespace Aberwyn.Data { } + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + builder.Entity().ToTable("WeeklyMenu"); + } + + public DbSet BudgetPeriods { get; set; } public DbSet BudgetCategories { get; set; } public DbSet BudgetItems { get; set; } @@ -19,6 +27,10 @@ namespace Aberwyn.Data public DbSet AppSettings { get; set; } public DbSet BudgetItemDefinitions { get; set; } public DbSet BudgetCategoryDefinitions { get; set; } + public DbSet Meals { get; set; } + public DbSet Ingredients { get; set; } + public DbSet WeeklyMenus { get; set; } + } diff --git a/Aberwyn/Data/MenuService.cs b/Aberwyn/Data/MenuService.cs index ee9f72f..2027ead 100644 --- a/Aberwyn/Data/MenuService.cs +++ b/Aberwyn/Data/MenuService.cs @@ -1,591 +1,192 @@ -using MySql.Data.MySqlClient; -using System.Collections.Generic; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Hosting; +// Nya versionen av MenuService med Entity Framework using Aberwyn.Models; +using Microsoft.EntityFrameworkCore; using System.Globalization; + namespace Aberwyn.Data { - public class MenuService +public class MenuService +{ + private readonly ApplicationDbContext _context; + + // Detta är DI-konstruktorn – används som vanligt i controllers + public MenuService(ApplicationDbContext context) { - private readonly IConfiguration _configuration; - private readonly IHostEnvironment _env; + _context = context; + } - public MenuService(IConfiguration configuration, IHostEnvironment env) + // Detta är en alternativ konstruktör – används manuellt vid t.ex. import + public static MenuService CreateWithConfig(IConfiguration config, IHostEnvironment env, bool useProdDb = false) + { + var builder = new DbContextOptionsBuilder(); + + var connStr = useProdDb + ? config.GetConnectionString("ProdConnection") + : config.GetConnectionString("DefaultConnection"); + + builder.UseMySql(connStr, ServerVersion.AutoDetect(connStr)); + var context = new ApplicationDbContext(builder.Options); + + return new MenuService(context); + } + public void UpdateWeeklyMenu(MenuViewModel model) { - _configuration = configuration; - _env = env; + var existing = _context.WeeklyMenus + .Where(w => w.WeekNumber == model.WeekNumber && w.Year == model.Year) + .ToList(); + + _context.WeeklyMenus.RemoveRange(existing); + _context.WeeklyMenus.AddRange(model.WeeklyMenus); + _context.SaveChanges(); + } + public int AddMeal(Meal meal) + { + SaveMeal(meal); + return meal.Id; } - private MySqlConnection GetConnection() - { - var connectionString = _env.IsDevelopment() - ? _configuration.GetConnectionString("DefaultConnection") - : _configuration.GetConnectionString("ProductionConnection"); - return new MySqlConnection(connectionString); - } - public List GetUsers() - { - var users = new List(); - using (var connection = GetConnection()) - { - connection.Open(); - string query = @"SELECT userID, Username, Name FROM Nevyn.tblUsers WHERE Chef = 1"; - using (var cmd = new MySqlCommand(query, connection)) - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - users.Add(new User - { - UserID = reader.GetInt32("userID"), - Username = reader.GetString("Username"), - Name = reader.GetString("Name") - }); - } - } - } - return users; - } public void SaveMeal(Meal meal) { - if (string.IsNullOrWhiteSpace(meal?.Name)) - return; + if (string.IsNullOrWhiteSpace(meal?.Name)) return; meal.Name = meal.Name.Trim(); + meal.CreatedAt = meal.CreatedAt == default ? DateTime.Now : meal.CreatedAt; - using var connection = GetConnection(); - connection.Open(); + if (meal.Id == 0) + _context.Meals.Add(meal); + else + _context.Meals.Update(meal); - var query = @" - INSERT INTO Meals - (Name, Description, RecipeUrl, CreatedAt) - VALUES (@name, @desc, @url, CURRENT_TIMESTAMP);"; - - using var cmd = new MySqlCommand(query, connection); - cmd.Parameters.AddWithValue("@name", meal.Name); - cmd.Parameters.AddWithValue("@desc", meal.Description ?? ""); - cmd.Parameters.AddWithValue("@url", meal.RecipeUrl ?? ""); - - try - { - cmd.ExecuteNonQuery(); - meal.Id = (int)cmd.LastInsertedId; - } - catch (MySqlException ex) when (ex.Number == 1062) - { - Console.WriteLine($"⚠️ Måltiden '{meal.Name}' finns redan i databasen."); - } - catch (Exception ex) - { - Console.WriteLine($"❌ Fel vid sparning av måltid '{meal.Name}': {ex.Message}"); - } + _context.SaveChanges(); } - public List GetWeeklyMenu(int weekNumber, int year) - { - var weeklyMenu = new List(); - using (var connection = GetConnection()) - { - connection.Open(); - string query = @" - SELECT wm.Id, wm.DayOfWeek, wm.DinnerMealId, wm.LunchMealId, wm.BreakfastMealId, - wm.WeekNumber, wm.Year, wm.Cook, - dm.Name AS DinnerMealName, - lm.Name AS LunchMealName, - bm.Name AS BreakfastMealName - FROM WeeklyMenu wm - LEFT JOIN Meals dm ON wm.DinnerMealId = dm.Id - LEFT JOIN Meals lm ON wm.LunchMealId = lm.Id - LEFT JOIN Meals bm ON wm.BreakfastMealId = bm.Id - WHERE wm.WeekNumber = @weekNumber AND wm.Year = @year"; +public List GetAllWeeklyMenus() +{ + var menus = _context.WeeklyMenus.ToList(); - using (var cmd = new MySqlCommand(query, connection)) - { - cmd.Parameters.AddWithValue("@weekNumber", weekNumber); - cmd.Parameters.AddWithValue("@year", year); + var allMeals = _context.Meals.ToDictionary(m => m.Id, m => m.Name); + + foreach (var wm in menus) + { + wm.BreakfastMealName = wm.BreakfastMealId.HasValue && allMeals.TryGetValue(wm.BreakfastMealId.Value, out var breakfast) + ? breakfast + : null; + + wm.LunchMealName = wm.LunchMealId.HasValue && allMeals.TryGetValue(wm.LunchMealId.Value, out var lunch) + ? lunch + : null; + + wm.DinnerMealName = wm.DinnerMealId.HasValue && allMeals.TryGetValue(wm.DinnerMealId.Value, out var dinner) + ? dinner + : null; + } + + return menus; +} - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - weeklyMenu.Add(new WeeklyMenu - { - Id = reader.GetInt32("Id"), - DayOfWeek = reader.GetInt32("DayOfWeek"), - DinnerMealId = reader.IsDBNull(reader.GetOrdinal("DinnerMealId")) ? (int?)null : reader.GetInt32(reader.GetOrdinal("DinnerMealId")), - LunchMealId = reader.IsDBNull(reader.GetOrdinal("LunchMealId")) ? (int?)null : reader.GetInt32(reader.GetOrdinal("LunchMealId")), - BreakfastMealId = reader.IsDBNull(reader.GetOrdinal("BreakfastMealId")) ? (int?)null : reader.GetInt32(reader.GetOrdinal("BreakfastMealId")), - WeekNumber = reader.GetInt32("WeekNumber"), - Year = reader.GetInt32("Year"), - Cook = reader.IsDBNull(reader.GetOrdinal("Cook")) ? null : reader.GetString(reader.GetOrdinal("Cook")), - DinnerMealName = reader.IsDBNull(reader.GetOrdinal("DinnerMealName")) ? null : reader.GetString(reader.GetOrdinal("DinnerMealName")), - LunchMealName = reader.IsDBNull(reader.GetOrdinal("LunchMealName")) ? null : reader.GetString(reader.GetOrdinal("LunchMealName")), - BreakfastMealName = reader.IsDBNull(reader.GetOrdinal("BreakfastMealName")) ? null : reader.GetString(reader.GetOrdinal("BreakfastMealName")) - }); - } - } - } - } - return weeklyMenu; - } public List GetIngredientsForMeal(int mealId) { - var ingredients = new List(); - using var conn = GetConnection(); - conn.Open(); - string query = "SELECT Id, MealId, Quantity, Item FROM Ingredients WHERE MealId = @mealId"; - - using var cmd = new MySqlCommand(query, conn); - cmd.Parameters.AddWithValue("@mealId", mealId); - - using var reader = cmd.ExecuteReader(); - while (reader.Read()) - { - ingredients.Add(new Ingredient - { - Id = reader.GetInt32("Id"), - MealId = reader.GetInt32("MealId"), - Quantity = reader.GetString("Quantity"), - Item = reader.GetString("Item") - }); - } - return ingredients; + return _context.Ingredients + .Where(i => i.MealId == mealId) + .ToList(); } + public void SaveIngredients(int mealId, List ingredients) { - using var conn = GetConnection(); - conn.Open(); - - using var tx = conn.BeginTransaction(); - - // Ta bort gamla - var deleteCmd = new MySqlCommand("DELETE FROM Ingredients WHERE MealId = @mealId", conn, tx); - deleteCmd.Parameters.AddWithValue("@mealId", mealId); - deleteCmd.ExecuteNonQuery(); - - foreach (var ingredient in ingredients) - { - var insertCmd = new MySqlCommand( - "INSERT INTO Ingredients (MealId, Quantity, Item) VALUES (@mealId, @quantity, @item)", - conn, tx); - - insertCmd.Parameters.AddWithValue("@mealId", mealId); - insertCmd.Parameters.AddWithValue("@quantity", ingredient.Quantity ?? ""); - insertCmd.Parameters.AddWithValue("@item", ingredient.Item ?? ""); - insertCmd.ExecuteNonQuery(); - } - - tx.Commit(); + var existing = _context.Ingredients.Where(i => i.MealId == mealId); + _context.Ingredients.RemoveRange(existing); + _context.Ingredients.AddRange(ingredients); + _context.SaveChanges(); } public List GetMeals() { - var meals = new List(); - using (var connection = GetConnection()) - { - connection.Open(); - string query = @" - SELECT Id, Name, ImageUrl, ImageData, ImageMimeType, Category, IsAvailable - FROM Meals"; - - using (var cmd = new MySqlCommand(query, connection)) - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - meals.Add(new Meal - { - Id = reader.GetInt32("Id"), - Name = reader.GetString("Name"), - ImageData = reader.IsDBNull(reader.GetOrdinal("ImageData")) ? null : (byte[])reader["ImageData"], - ImageMimeType = reader.IsDBNull(reader.GetOrdinal("ImageMimeType")) ? null : reader.GetString(reader.GetOrdinal("ImageMimeType")), - ImageUrl = reader.IsDBNull(reader.GetOrdinal("ImageUrl")) ? null : reader.GetString(reader.GetOrdinal("ImageUrl")), - Category = reader.IsDBNull(reader.GetOrdinal("Category")) ? null : reader.GetString(reader.GetOrdinal("Category")), - IsAvailable = reader.IsDBNull(reader.GetOrdinal("IsAvailable")) ? true : reader.GetBoolean(reader.GetOrdinal("IsAvailable")) - }); - } - } - } - return meals; + return _context.Meals.ToList(); } public List GetMealsDetailed() { - var meals = new List(); - - using (var connection = GetConnection()) - { - connection.Open(); - string query = @" - SELECT Id, Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt, ImageUrl, ImageData, ImageMimeType - FROM Meals - ORDER BY CreatedAt DESC"; - - using (var cmd = new MySqlCommand(query, connection)) - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - meals.Add(new Meal - { - Id = reader.GetInt32(reader.GetOrdinal("Id")), - Name = reader.GetString(reader.GetOrdinal("Name")), - Description = reader.IsDBNull(reader.GetOrdinal("Description")) ? null : reader.GetString(reader.GetOrdinal("Description")), - ProteinType = reader.IsDBNull(reader.GetOrdinal("ProteinType")) ? null : reader.GetString(reader.GetOrdinal("ProteinType")), - CarbType = reader.IsDBNull(reader.GetOrdinal("CarbType")) ? null : reader.GetString(reader.GetOrdinal("CarbType")), - RecipeUrl = reader.IsDBNull(reader.GetOrdinal("RecipeUrl")) ? null : reader.GetString(reader.GetOrdinal("RecipeUrl")), - ImageUrl = reader.IsDBNull(reader.GetOrdinal("ImageUrl")) ? null : reader.GetString(reader.GetOrdinal("ImageUrl")), - CreatedAt = reader.GetDateTime(reader.GetOrdinal("CreatedAt")), - ImageData = reader.IsDBNull(reader.GetOrdinal("ImageData")) ? null : (byte[])reader["ImageData"], - ImageMimeType = reader.IsDBNull(reader.GetOrdinal("ImageMimeType")) ? null : reader.GetString(reader.GetOrdinal("ImageMimeType")) - - }); - } - } - } - - return meals; + return _context.Meals + .OrderByDescending(m => m.CreatedAt) + .ToList(); } public Meal GetMealById(int id) { - using var connection = GetConnection(); - connection.Open(); - - string query = @"SELECT Id, Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt, ImageUrl, ImageData, ImageMimeType, Instructions FROM Meals WHERE Id = @id"; - - using var cmd = new MySqlCommand(query, connection); - cmd.Parameters.AddWithValue("@id", id); - - using var reader = cmd.ExecuteReader(); - if (reader.Read()) - { - return new Meal - { - Id = reader.GetInt32(reader.GetOrdinal("Id")), - Name = reader.GetString(reader.GetOrdinal("Name")), - Description = reader.IsDBNull(reader.GetOrdinal("Description")) ? null : reader.GetString(reader.GetOrdinal("Description")), - ProteinType = reader.IsDBNull(reader.GetOrdinal("ProteinType")) ? null : reader.GetString(reader.GetOrdinal("ProteinType")), - CarbType = reader.IsDBNull(reader.GetOrdinal("CarbType")) ? null : reader.GetString(reader.GetOrdinal("CarbType")), - RecipeUrl = reader.IsDBNull(reader.GetOrdinal("RecipeUrl")) ? null : reader.GetString(reader.GetOrdinal("RecipeUrl")), - ImageUrl = reader.IsDBNull(reader.GetOrdinal("ImageUrl")) ? null : reader.GetString(reader.GetOrdinal("ImageUrl")), - CreatedAt = reader.GetDateTime(reader.GetOrdinal("CreatedAt")), - ImageData = reader.IsDBNull(reader.GetOrdinal("ImageData")) ? null : (byte[])reader["ImageData"], - ImageMimeType = reader.IsDBNull(reader.GetOrdinal("ImageMimeType")) ? null : reader.GetString(reader.GetOrdinal("ImageMimeType")), - Instructions = reader.IsDBNull(reader.GetOrdinal("Instructions")) ? null : reader.GetString(reader.GetOrdinal("Instructions")), - Ingredients = GetIngredientsForMeal(id) - - }; - - } - - return null; + var meal = _context.Meals + .Include(m => m.Ingredients) + .FirstOrDefault(m => m.Id == id); + return meal; } public void DeleteMeal(int id) { - using var connection = GetConnection(); - connection.Open(); - string query = "DELETE FROM Meals WHERE Id = @id"; - using var cmd = new MySqlCommand(query, connection); - cmd.Parameters.AddWithValue("@id", id); - cmd.ExecuteNonQuery(); + var meal = _context.Meals.Find(id); + if (meal != null) + { + _context.Meals.Remove(meal); + _context.SaveChanges(); + } } public void SaveOrUpdateMeal(Meal meal) { - using var conn = new MySqlConnection(_configuration.GetConnectionString("DefaultConnection")); - conn.Open(); - - using var cmd = conn.CreateCommand(); - if (meal.Id == 0) - { - cmd.CommandText = @" - INSERT INTO Meals - (Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt, ImageUrl, ImageData, ImageMimeType, Instructions, Category, IsAvailable) - VALUES - (@Name, @Description, @ProteinType, @CarbType, @RecipeUrl, @CreatedAt, @ImageUrl, @ImageData, @ImageMimeType, @Instructions, @Category, @IsAvailable); - SELECT LAST_INSERT_ID();"; - } - else - { - cmd.CommandText = @" - UPDATE Meals - SET Name = @Name, - Description = @Description, - ProteinType = @ProteinType, - CarbType = @CarbType, - RecipeUrl = @RecipeUrl, - ImageUrl = @ImageUrl, - ImageData = @ImageData, - ImageMimeType = @ImageMimeType, - Instructions = @Instructions, - Category = @Category, - IsAvailable = @IsAvailable - WHERE Id = @Id"; - cmd.Parameters.AddWithValue("@Id", meal.Id); - } - - cmd.Parameters.AddWithValue("@Name", meal.Name ?? ""); - cmd.Parameters.AddWithValue("@Description", meal.Description ?? ""); - cmd.Parameters.AddWithValue("@ProteinType", meal.ProteinType ?? ""); - cmd.Parameters.AddWithValue("@CarbType", meal.CarbType ?? ""); - cmd.Parameters.AddWithValue("@RecipeUrl", meal.RecipeUrl ?? ""); - cmd.Parameters.AddWithValue("@CreatedAt", meal.CreatedAt == default ? DateTime.Now : meal.CreatedAt); - cmd.Parameters.AddWithValue("@ImageUrl", meal.ImageUrl ?? ""); - cmd.Parameters.AddWithValue("@ImageData", (object?)meal.ImageData ?? DBNull.Value); - cmd.Parameters.AddWithValue("@ImageMimeType", meal.ImageMimeType ?? (object)DBNull.Value); - cmd.Parameters.AddWithValue("@Instructions", meal.Instructions ?? ""); - cmd.Parameters.AddWithValue("@Category", meal.Category ?? ""); - cmd.Parameters.AddWithValue("@IsAvailable", meal.IsAvailable ? 1 : 0); - - if (meal.Id == 0) - { - var insertedId = Convert.ToInt32(cmd.ExecuteScalar()); - meal.Id = insertedId; - } - else - { - cmd.ExecuteNonQuery(); - } + SaveMeal(meal); } - - public void UpdateWeeklyMenu(MenuViewModel menuData) - { - if (menuData == null || menuData.WeeklyMenus == null) - throw new ArgumentNullException(nameof(menuData), "Menu data or weekly menus cannot be null."); - - using (var connection = GetConnection()) - { - connection.Open(); - using (var transaction = connection.BeginTransaction()) - { - try - { - foreach (var menu in menuData.WeeklyMenus) - { - int dayOfWeek = menu.DayOfWeek; - - string updateQuery = @" - UPDATE WeeklyMenu - SET - BreakfastMealId = @breakfastMealId, - LunchMealId = @lunchMealId, - DinnerMealId = @dinnerMealId, - Cook = @cook - WHERE DayOfWeek = @dayOfWeek - AND WeekNumber = @weekNumber - AND Year = @year;"; - - using (var cmd = new MySqlCommand(updateQuery, connection, transaction)) - { - cmd.Parameters.AddWithValue("@dayOfWeek", dayOfWeek); - cmd.Parameters.AddWithValue("@breakfastMealId", menu.BreakfastMealId ?? (object)DBNull.Value); - cmd.Parameters.AddWithValue("@lunchMealId", menu.LunchMealId ?? (object)DBNull.Value); - cmd.Parameters.AddWithValue("@dinnerMealId", menu.DinnerMealId ?? (object)DBNull.Value); - cmd.Parameters.AddWithValue("@weekNumber", menu.WeekNumber); - cmd.Parameters.AddWithValue("@year", menu.Year); - cmd.Parameters.AddWithValue("@cook", menu.Cook ?? (object)DBNull.Value); - - int rowsAffected = cmd.ExecuteNonQuery(); - - if (rowsAffected == 0) - { - string insertQuery = @" - INSERT INTO WeeklyMenu - (DayOfWeek, WeekNumber, Year, BreakfastMealId, LunchMealId, DinnerMealId, Cook) - VALUES (@dayOfWeek, @weekNumber, @year, @breakfastMealId, @lunchMealId, @dinnerMealId, @cook);"; - - using var insertCmd = new MySqlCommand(insertQuery, connection, transaction); - insertCmd.Parameters.AddWithValue("@dayOfWeek", dayOfWeek); - insertCmd.Parameters.AddWithValue("@breakfastMealId", menu.BreakfastMealId ?? (object)DBNull.Value); - insertCmd.Parameters.AddWithValue("@lunchMealId", menu.LunchMealId ?? (object)DBNull.Value); - insertCmd.Parameters.AddWithValue("@dinnerMealId", menu.DinnerMealId ?? (object)DBNull.Value); - insertCmd.Parameters.AddWithValue("@weekNumber", menu.WeekNumber); - insertCmd.Parameters.AddWithValue("@year", menu.Year); - insertCmd.Parameters.AddWithValue("@cook", menu.Cook ?? (object)DBNull.Value); - insertCmd.ExecuteNonQuery(); - } - } - } - - transaction.Commit(); - } - catch (Exception ex) - { - transaction.Rollback(); - Console.WriteLine($"Error updating weekly menu: {ex.Message}"); - throw; - } - } - } - } - - - public int AddMeal(Meal meal) - { - using (var connection = GetConnection()) - { - connection.Open(); - string query = @" - INSERT INTO Meals (Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt) - VALUES (@name, @description, @proteinType, @carbType, @recipeUrl, NOW()); - SELECT LAST_INSERT_ID();"; - - using (var cmd = new MySqlCommand(query, connection)) - { - cmd.Parameters.AddWithValue("@name", meal.Name); - cmd.Parameters.AddWithValue("@description", string.IsNullOrWhiteSpace(meal.Description) ? (object)DBNull.Value : meal.Description); - cmd.Parameters.AddWithValue("@proteinType", string.IsNullOrWhiteSpace(meal.ProteinType) ? (object)DBNull.Value : meal.ProteinType); - cmd.Parameters.AddWithValue("@carbType", string.IsNullOrWhiteSpace(meal.CarbType) ? (object)DBNull.Value : meal.CarbType); - cmd.Parameters.AddWithValue("@recipeUrl", string.IsNullOrWhiteSpace(meal.RecipeUrl) ? (object)DBNull.Value : meal.RecipeUrl); - - var result = cmd.ExecuteScalar(); - return result != null ? Convert.ToInt32(result) : 0; - } - } - } - - - - private int GetDayOfWeek(string day) - { - return day switch - { - "Monday" => 1, - "Tuesday" => 2, - "Wednesday" => 3, - "Thursday" => 4, - "Friday" => 5, - "Saturday" => 6, - "Sunday" => 7, - _ => throw new System.ArgumentException("Invalid day name") - }; - } public void SaveOrUpdateMealWithIngredients(Meal meal) { - // Spara/uppdatera måltid - SaveOrUpdateMeal(meal); + SaveMeal(meal); - // Om måltiden har ingredienser – spara dem if (meal.Ingredients != null && meal.Ingredients.Count > 0) { SaveIngredients(meal.Id, meal.Ingredients); } } + public List GetMealsByCategory(string category) { - var meals = new List(); - - using var connection = GetConnection(); - connection.Open(); - - string query = @" - SELECT m.Id, m.Name, m.Category, m.Description, m.ImageUrl, m.ImageData, m.ImageMimeType, m.IsAvailable, - i.Id AS IngredientId, i.Quantity, i.Item -FROM Meals m -LEFT JOIN Ingredients i ON m.Id = i.MealId -WHERE m.Category = @category -ORDER BY m.Name, i.Id"; - - using var cmd = new MySqlCommand(query, connection); - cmd.Parameters.AddWithValue("@category", category); - - using var reader = cmd.ExecuteReader(); - Dictionary mealMap = new(); - - while (reader.Read()) - { - int mealId = reader.GetInt32("Id"); - - if (!mealMap.ContainsKey(mealId)) - { - mealMap[mealId] = new Meal - { - Id = mealId, - Name = reader.GetString("Name"), - Category = reader.IsDBNull(reader.GetOrdinal("Category")) ? null : reader.GetString("Category"), - Description = reader.IsDBNull(reader.GetOrdinal("Description")) ? null : reader.GetString("Description"), - ImageUrl = reader.IsDBNull(reader.GetOrdinal("ImageUrl")) ? null : reader.GetString("ImageUrl"), - ImageData = reader.IsDBNull(reader.GetOrdinal("ImageData")) ? null : (byte[])reader["ImageData"], - ImageMimeType = reader.IsDBNull(reader.GetOrdinal("ImageMimeType")) ? null : reader.GetString("ImageMimeType"), - Ingredients = new List(), - IsAvailable = reader.IsDBNull(reader.GetOrdinal("IsAvailable")) ? true : reader.GetBoolean(reader.GetOrdinal("IsAvailable")), - - }; - } - - if (!reader.IsDBNull(reader.GetOrdinal("IngredientId"))) - { - mealMap[mealId].Ingredients.Add(new Ingredient - { - Id = reader.GetInt32("IngredientId"), - MealId = mealId, - Quantity = reader.IsDBNull(reader.GetOrdinal("Quantity")) ? "" : reader.GetString("Quantity"), - Item = reader.IsDBNull(reader.GetOrdinal("Item")) ? "" : reader.GetString("Item") - }); - } - } - - return mealMap.Values.ToList(); + return _context.Meals + .Where(m => m.Category == category) + .Include(m => m.Ingredients) + .OrderBy(m => m.Name) + .ToList(); } public List GetMenuEntriesByDateRange(DateTime startDate, DateTime endDate) { var results = new List(); - - // Hitta start- och slut-år/veckonummer int startWeek = ISOWeek.GetWeekOfYear(startDate); - int startYear = startDate.Year; int endWeek = ISOWeek.GetWeekOfYear(endDate); + int startYear = startDate.Year; int endYear = endDate.Year; - // Loopar över alla veckor från start → slut - var allMenus = new List(); - int w = startWeek, y = startYear; - while (y < endYear || (y == endYear && w <= endWeek)) + for (int y = startYear; y <= endYear; y++) { - allMenus.AddRange(GetWeeklyMenu(w, y)); + int fromWeek = y == startYear ? startWeek : 1; + int toWeek = y == endYear ? endWeek : ISOWeek.GetWeeksInYear(y); - // öka vecka, hantera årsskifte - int weeksInYear = ISOWeek.GetWeeksInYear(y); - if (w == weeksInYear) + for (int w = fromWeek; w <= toWeek; w++) { - w = 1; - y++; - } - else - { - w++; + var menus = GetWeeklyMenu(w, y); + foreach (var menu in menus) + { + var dow = (DayOfWeek)(menu.DayOfWeek % 7); + var date = ISOWeek.ToDateTime(menu.Year, menu.WeekNumber, dow); + if (date.Date >= startDate.Date && date.Date <= endDate.Date) + { + menu.Date = date; + results.Add(menu); + } + } } } - - // Filtrera på datumintervall - foreach (var menu in allMenus) - { - // Konvertera DayOfWeek (1=Mon…7=Sun) till System.DayOfWeek - var dow = (DayOfWeek)(menu.DayOfWeek % 7); - var date = ISOWeek.ToDateTime(menu.Year, menu.WeekNumber, dow); - - if (date.Date >= startDate.Date && date.Date <= endDate.Date) - { - menu.Date = date; // Se till att WeeklyMenu har en Date-property - results.Add(menu); - } - } - return results; } - - } } - -// Models for Meals and WeeklyMenu diff --git a/Aberwyn/Dockerfile b/Aberwyn/Dockerfile index defcf32..59f5135 100644 --- a/Aberwyn/Dockerfile +++ b/Aberwyn/Dockerfile @@ -19,4 +19,22 @@ RUN dotnet publish "Aberwyn.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "Aberwyn.dll"] \ No newline at end of file +ENTRYPOINT ["dotnet", "Aberwyn.dll"] + +version: '3.8' +services: + db: + image: mysql:8 + container_name: dev-mysql + ports: + - "3306:3306" + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: aberwyn + MYSQL_USER: aberwyn + MYSQL_PASSWORD: devpass + volumes: + - mysql-data:/var/lib/mysql + +volumes: + mysql-data: diff --git a/Aberwyn/Infrastructure/docker-compose.yml b/Aberwyn/Infrastructure/docker-compose.yml new file mode 100644 index 0000000..54caf67 --- /dev/null +++ b/Aberwyn/Infrastructure/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3.8' +services: + dev-db: + image: mysql:8 + container_name: aberwyn-dev-db + ports: + - "3306:3306" + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: aberwyn + MYSQL_USER: aberwyn + MYSQL_PASSWORD: devpass + volumes: + - dev-mysql-data:/var/lib/mysql + +volumes: + dev-mysql-data: diff --git a/Aberwyn/Migrations/20250531220325_AddMealsToEf.Designer.cs b/Aberwyn/Migrations/20250531220325_AddMealsToEf.Designer.cs new file mode 100644 index 0000000..50f9484 --- /dev/null +++ b/Aberwyn/Migrations/20250531220325_AddMealsToEf.Designer.cs @@ -0,0 +1,659 @@ +// +using System; +using Aberwyn.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Aberwyn.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250531220325_AddMealsToEf")] + partial class AddMealsToEf + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.36") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Aberwyn.Models.AppSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("AppSettings"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BudgetCategoryDefinitionId") + .HasColumnType("int"); + + b.Property("BudgetPeriodId") + .HasColumnType("int"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BudgetCategoryDefinitionId"); + + b.HasIndex("BudgetPeriodId"); + + b.ToTable("BudgetCategories"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategoryDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("BudgetCategoryDefinitions"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("BudgetCategoryId") + .HasColumnType("int"); + + b.Property("BudgetItemDefinitionId") + .HasColumnType("int"); + + b.Property("IncludeInSummary") + .HasColumnType("tinyint(1)"); + + b.Property("IsExpense") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BudgetCategoryId"); + + b.HasIndex("BudgetItemDefinitionId"); + + b.ToTable("BudgetItems"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItemDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("DefaultCategory") + .HasColumnType("longtext"); + + b.Property("IncludeInSummary") + .HasColumnType("tinyint(1)"); + + b.Property("IsExpense") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("BudgetItemDefinitions"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Month") + .HasColumnType("int"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("BudgetPeriods"); + }); + + modelBuilder.Entity("Aberwyn.Models.Ingredient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Item") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MealId") + .HasColumnType("int"); + + b.Property("Quantity") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("MealId"); + + b.ToTable("Ingredients"); + }); + + modelBuilder.Entity("Aberwyn.Models.Meal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CarbType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Category") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ImageData") + .IsRequired() + .HasColumnType("longblob"); + + b.Property("ImageMimeType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Instructions") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsAvailable") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProteinType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipeUrl") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Meals"); + }); + + modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CustomerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IngredientsJson") + .HasColumnType("longtext"); + + b.Property("OrderedAt") + .HasColumnType("datetime(6)"); + + b.Property("PizzaName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Status") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PizzaOrders"); + }); + + modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Auth") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Endpoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("P256DH") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PushSubscribers"); + }); + + modelBuilder.Entity("Aberwyn.Models.WeeklyMenu", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BreakfastMealId") + .HasColumnType("int"); + + b.Property("BreakfastMealName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Cook") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("DinnerMealId") + .HasColumnType("int"); + + b.Property("DinnerMealName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LunchMealId") + .HasColumnType("int"); + + b.Property("LunchMealName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("WeekNumber") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("WeeklyMenus"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + 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("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "Definition") + .WithMany() + .HasForeignKey("BudgetCategoryDefinitionId"); + + b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod") + .WithMany("Categories") + .HasForeignKey("BudgetPeriodId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BudgetPeriod"); + + b.Navigation("Definition"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItem", b => + { + b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory") + .WithMany("Items") + .HasForeignKey("BudgetCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aberwyn.Models.BudgetItemDefinition", "BudgetItemDefinition") + .WithMany() + .HasForeignKey("BudgetItemDefinitionId"); + + b.Navigation("BudgetCategory"); + + b.Navigation("BudgetItemDefinition"); + }); + + modelBuilder.Entity("Aberwyn.Models.Ingredient", b => + { + b.HasOne("Aberwyn.Models.Meal", null) + .WithMany("Ingredients") + .HasForeignKey("MealId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + 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("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Aberwyn.Models.ApplicationUser", 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("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b => + { + b.Navigation("Categories"); + }); + + modelBuilder.Entity("Aberwyn.Models.Meal", b => + { + b.Navigation("Ingredients"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Aberwyn/Migrations/20250531220325_AddMealsToEf.cs b/Aberwyn/Migrations/20250531220325_AddMealsToEf.cs new file mode 100644 index 0000000..5b0694a --- /dev/null +++ b/Aberwyn/Migrations/20250531220325_AddMealsToEf.cs @@ -0,0 +1,117 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Aberwyn.Migrations +{ + public partial class AddMealsToEf : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Meals", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Name = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ProteinType = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Category = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CarbType = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + RecipeUrl = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ImageUrl = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + IsAvailable = table.Column(type: "tinyint(1)", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + ImageData = table.Column(type: "longblob", nullable: false), + ImageMimeType = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Instructions = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_Meals", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "WeeklyMenus", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + DayOfWeek = table.Column(type: "int", nullable: false), + BreakfastMealId = table.Column(type: "int", nullable: true), + LunchMealId = table.Column(type: "int", nullable: true), + DinnerMealId = table.Column(type: "int", nullable: true), + Cook = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + WeekNumber = table.Column(type: "int", nullable: false), + Year = table.Column(type: "int", nullable: false), + BreakfastMealName = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + LunchMealName = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + DinnerMealName = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Date = table.Column(type: "datetime(6)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_WeeklyMenus", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Ingredients", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + MealId = table.Column(type: "int", nullable: false), + Quantity = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Item = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_Ingredients", x => x.Id); + table.ForeignKey( + name: "FK_Ingredients_Meals_MealId", + column: x => x.MealId, + principalTable: "Meals", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_Ingredients_MealId", + table: "Ingredients", + column: "MealId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Ingredients"); + + migrationBuilder.DropTable( + name: "WeeklyMenus"); + + migrationBuilder.DropTable( + name: "Meals"); + } + } +} diff --git a/Aberwyn/Migrations/20250601201238_MakeCategoryNullable.Designer.cs b/Aberwyn/Migrations/20250601201238_MakeCategoryNullable.Designer.cs new file mode 100644 index 0000000..eeeb7b3 --- /dev/null +++ b/Aberwyn/Migrations/20250601201238_MakeCategoryNullable.Designer.cs @@ -0,0 +1,650 @@ +// +using System; +using Aberwyn.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Aberwyn.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250601201238_MakeCategoryNullable")] + partial class MakeCategoryNullable + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.36") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Aberwyn.Models.AppSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("AppSettings"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BudgetCategoryDefinitionId") + .HasColumnType("int"); + + b.Property("BudgetPeriodId") + .HasColumnType("int"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BudgetCategoryDefinitionId"); + + b.HasIndex("BudgetPeriodId"); + + b.ToTable("BudgetCategories"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategoryDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("BudgetCategoryDefinitions"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("BudgetCategoryId") + .HasColumnType("int"); + + b.Property("BudgetItemDefinitionId") + .HasColumnType("int"); + + b.Property("IncludeInSummary") + .HasColumnType("tinyint(1)"); + + b.Property("IsExpense") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BudgetCategoryId"); + + b.HasIndex("BudgetItemDefinitionId"); + + b.ToTable("BudgetItems"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItemDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("DefaultCategory") + .HasColumnType("longtext"); + + b.Property("IncludeInSummary") + .HasColumnType("tinyint(1)"); + + b.Property("IsExpense") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("BudgetItemDefinitions"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Month") + .HasColumnType("int"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("BudgetPeriods"); + }); + + modelBuilder.Entity("Aberwyn.Models.Ingredient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Item") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MealId") + .HasColumnType("int"); + + b.Property("Quantity") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("MealId"); + + b.ToTable("Ingredients"); + }); + + modelBuilder.Entity("Aberwyn.Models.Meal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CarbType") + .HasColumnType("longtext"); + + b.Property("Category") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ImageData") + .HasColumnType("longblob"); + + b.Property("ImageMimeType") + .HasColumnType("longtext"); + + b.Property("ImageUrl") + .HasColumnType("longtext"); + + b.Property("Instructions") + .HasColumnType("longtext"); + + b.Property("IsAvailable") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProteinType") + .HasColumnType("longtext"); + + b.Property("RecipeUrl") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Meals"); + }); + + modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CustomerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IngredientsJson") + .HasColumnType("longtext"); + + b.Property("OrderedAt") + .HasColumnType("datetime(6)"); + + b.Property("PizzaName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Status") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PizzaOrders"); + }); + + modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Auth") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Endpoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("P256DH") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PushSubscribers"); + }); + + modelBuilder.Entity("Aberwyn.Models.WeeklyMenu", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BreakfastMealId") + .HasColumnType("int"); + + b.Property("BreakfastMealName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Cook") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("DinnerMealId") + .HasColumnType("int"); + + b.Property("DinnerMealName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LunchMealId") + .HasColumnType("int"); + + b.Property("LunchMealName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("WeekNumber") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("WeeklyMenus"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + 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("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "Definition") + .WithMany() + .HasForeignKey("BudgetCategoryDefinitionId"); + + b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod") + .WithMany("Categories") + .HasForeignKey("BudgetPeriodId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BudgetPeriod"); + + b.Navigation("Definition"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItem", b => + { + b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory") + .WithMany("Items") + .HasForeignKey("BudgetCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aberwyn.Models.BudgetItemDefinition", "BudgetItemDefinition") + .WithMany() + .HasForeignKey("BudgetItemDefinitionId"); + + b.Navigation("BudgetCategory"); + + b.Navigation("BudgetItemDefinition"); + }); + + modelBuilder.Entity("Aberwyn.Models.Ingredient", b => + { + b.HasOne("Aberwyn.Models.Meal", null) + .WithMany("Ingredients") + .HasForeignKey("MealId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + 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("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Aberwyn.Models.ApplicationUser", 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("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b => + { + b.Navigation("Categories"); + }); + + modelBuilder.Entity("Aberwyn.Models.Meal", b => + { + b.Navigation("Ingredients"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Aberwyn/Migrations/20250601201238_MakeCategoryNullable.cs b/Aberwyn/Migrations/20250601201238_MakeCategoryNullable.cs new file mode 100644 index 0000000..550626b --- /dev/null +++ b/Aberwyn/Migrations/20250601201238_MakeCategoryNullable.cs @@ -0,0 +1,258 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Aberwyn.Migrations +{ + public partial class MakeCategoryNullable : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "RecipeUrl", + table: "Meals", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ProteinType", + table: "Meals", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Instructions", + table: "Meals", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ImageUrl", + table: "Meals", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ImageMimeType", + table: "Meals", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ImageData", + table: "Meals", + type: "longblob", + nullable: true, + oldClrType: typeof(byte[]), + oldType: "longblob"); + + migrationBuilder.AlterColumn( + name: "Description", + table: "Meals", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Category", + table: "Meals", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "CarbType", + table: "Meals", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "Meals", + keyColumn: "RecipeUrl", + keyValue: null, + column: "RecipeUrl", + value: ""); + + migrationBuilder.AlterColumn( + name: "RecipeUrl", + table: "Meals", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "Meals", + keyColumn: "ProteinType", + keyValue: null, + column: "ProteinType", + value: ""); + + migrationBuilder.AlterColumn( + name: "ProteinType", + table: "Meals", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "Meals", + keyColumn: "Instructions", + keyValue: null, + column: "Instructions", + value: ""); + + migrationBuilder.AlterColumn( + name: "Instructions", + table: "Meals", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "Meals", + keyColumn: "ImageUrl", + keyValue: null, + column: "ImageUrl", + value: ""); + + migrationBuilder.AlterColumn( + name: "ImageUrl", + table: "Meals", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "Meals", + keyColumn: "ImageMimeType", + keyValue: null, + column: "ImageMimeType", + value: ""); + + migrationBuilder.AlterColumn( + name: "ImageMimeType", + table: "Meals", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ImageData", + table: "Meals", + type: "longblob", + nullable: false, + defaultValue: new byte[0], + oldClrType: typeof(byte[]), + oldType: "longblob", + oldNullable: true); + + migrationBuilder.UpdateData( + table: "Meals", + keyColumn: "Description", + keyValue: null, + column: "Description", + value: ""); + + migrationBuilder.AlterColumn( + name: "Description", + table: "Meals", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "Meals", + keyColumn: "Category", + keyValue: null, + column: "Category", + value: ""); + + migrationBuilder.AlterColumn( + name: "Category", + table: "Meals", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "Meals", + keyColumn: "CarbType", + keyValue: null, + column: "CarbType", + value: ""); + + migrationBuilder.AlterColumn( + name: "CarbType", + table: "Meals", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + } + } +} diff --git a/Aberwyn/Migrations/20250601201642_CreateWeeklyMenus.Designer.cs b/Aberwyn/Migrations/20250601201642_CreateWeeklyMenus.Designer.cs new file mode 100644 index 0000000..661c9c5 --- /dev/null +++ b/Aberwyn/Migrations/20250601201642_CreateWeeklyMenus.Designer.cs @@ -0,0 +1,650 @@ +// +using System; +using Aberwyn.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Aberwyn.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250601201642_CreateWeeklyMenus")] + partial class CreateWeeklyMenus + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.36") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Aberwyn.Models.AppSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("AppSettings"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BudgetCategoryDefinitionId") + .HasColumnType("int"); + + b.Property("BudgetPeriodId") + .HasColumnType("int"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BudgetCategoryDefinitionId"); + + b.HasIndex("BudgetPeriodId"); + + b.ToTable("BudgetCategories"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategoryDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("BudgetCategoryDefinitions"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("BudgetCategoryId") + .HasColumnType("int"); + + b.Property("BudgetItemDefinitionId") + .HasColumnType("int"); + + b.Property("IncludeInSummary") + .HasColumnType("tinyint(1)"); + + b.Property("IsExpense") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BudgetCategoryId"); + + b.HasIndex("BudgetItemDefinitionId"); + + b.ToTable("BudgetItems"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItemDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("DefaultCategory") + .HasColumnType("longtext"); + + b.Property("IncludeInSummary") + .HasColumnType("tinyint(1)"); + + b.Property("IsExpense") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("BudgetItemDefinitions"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Month") + .HasColumnType("int"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("BudgetPeriods"); + }); + + modelBuilder.Entity("Aberwyn.Models.Ingredient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Item") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MealId") + .HasColumnType("int"); + + b.Property("Quantity") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("MealId"); + + b.ToTable("Ingredients"); + }); + + modelBuilder.Entity("Aberwyn.Models.Meal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CarbType") + .HasColumnType("longtext"); + + b.Property("Category") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ImageData") + .HasColumnType("longblob"); + + b.Property("ImageMimeType") + .HasColumnType("longtext"); + + b.Property("ImageUrl") + .HasColumnType("longtext"); + + b.Property("Instructions") + .HasColumnType("longtext"); + + b.Property("IsAvailable") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProteinType") + .HasColumnType("longtext"); + + b.Property("RecipeUrl") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Meals"); + }); + + modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CustomerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IngredientsJson") + .HasColumnType("longtext"); + + b.Property("OrderedAt") + .HasColumnType("datetime(6)"); + + b.Property("PizzaName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Status") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PizzaOrders"); + }); + + modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Auth") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Endpoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("P256DH") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PushSubscribers"); + }); + + modelBuilder.Entity("Aberwyn.Models.WeeklyMenu", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BreakfastMealId") + .HasColumnType("int"); + + b.Property("BreakfastMealName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Cook") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("DinnerMealId") + .HasColumnType("int"); + + b.Property("DinnerMealName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LunchMealId") + .HasColumnType("int"); + + b.Property("LunchMealName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("WeekNumber") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("WeeklyMenus"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + 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("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "Definition") + .WithMany() + .HasForeignKey("BudgetCategoryDefinitionId"); + + b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod") + .WithMany("Categories") + .HasForeignKey("BudgetPeriodId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BudgetPeriod"); + + b.Navigation("Definition"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItem", b => + { + b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory") + .WithMany("Items") + .HasForeignKey("BudgetCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aberwyn.Models.BudgetItemDefinition", "BudgetItemDefinition") + .WithMany() + .HasForeignKey("BudgetItemDefinitionId"); + + b.Navigation("BudgetCategory"); + + b.Navigation("BudgetItemDefinition"); + }); + + modelBuilder.Entity("Aberwyn.Models.Ingredient", b => + { + b.HasOne("Aberwyn.Models.Meal", null) + .WithMany("Ingredients") + .HasForeignKey("MealId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + 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("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Aberwyn.Models.ApplicationUser", 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("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b => + { + b.Navigation("Categories"); + }); + + modelBuilder.Entity("Aberwyn.Models.Meal", b => + { + b.Navigation("Ingredients"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Aberwyn/Migrations/20250601201642_CreateWeeklyMenus.cs b/Aberwyn/Migrations/20250601201642_CreateWeeklyMenus.cs new file mode 100644 index 0000000..8bb909c --- /dev/null +++ b/Aberwyn/Migrations/20250601201642_CreateWeeklyMenus.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Aberwyn.Migrations +{ + public partial class CreateWeeklyMenus : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/Aberwyn/Migrations/20250601204720_RenameWeeklyMenusToWeeklyMenu.Designer.cs b/Aberwyn/Migrations/20250601204720_RenameWeeklyMenusToWeeklyMenu.Designer.cs new file mode 100644 index 0000000..93538d5 --- /dev/null +++ b/Aberwyn/Migrations/20250601204720_RenameWeeklyMenusToWeeklyMenu.Designer.cs @@ -0,0 +1,650 @@ +// +using System; +using Aberwyn.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Aberwyn.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250601204720_RenameWeeklyMenusToWeeklyMenu")] + partial class RenameWeeklyMenusToWeeklyMenu + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.36") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Aberwyn.Models.AppSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("AppSettings"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BudgetCategoryDefinitionId") + .HasColumnType("int"); + + b.Property("BudgetPeriodId") + .HasColumnType("int"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BudgetCategoryDefinitionId"); + + b.HasIndex("BudgetPeriodId"); + + b.ToTable("BudgetCategories"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategoryDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("BudgetCategoryDefinitions"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("BudgetCategoryId") + .HasColumnType("int"); + + b.Property("BudgetItemDefinitionId") + .HasColumnType("int"); + + b.Property("IncludeInSummary") + .HasColumnType("tinyint(1)"); + + b.Property("IsExpense") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BudgetCategoryId"); + + b.HasIndex("BudgetItemDefinitionId"); + + b.ToTable("BudgetItems"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItemDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("DefaultCategory") + .HasColumnType("longtext"); + + b.Property("IncludeInSummary") + .HasColumnType("tinyint(1)"); + + b.Property("IsExpense") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("BudgetItemDefinitions"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Month") + .HasColumnType("int"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("BudgetPeriods"); + }); + + modelBuilder.Entity("Aberwyn.Models.Ingredient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Item") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MealId") + .HasColumnType("int"); + + b.Property("Quantity") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("MealId"); + + b.ToTable("Ingredients"); + }); + + modelBuilder.Entity("Aberwyn.Models.Meal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CarbType") + .HasColumnType("longtext"); + + b.Property("Category") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ImageData") + .HasColumnType("longblob"); + + b.Property("ImageMimeType") + .HasColumnType("longtext"); + + b.Property("ImageUrl") + .HasColumnType("longtext"); + + b.Property("Instructions") + .HasColumnType("longtext"); + + b.Property("IsAvailable") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProteinType") + .HasColumnType("longtext"); + + b.Property("RecipeUrl") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Meals"); + }); + + modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CustomerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IngredientsJson") + .HasColumnType("longtext"); + + b.Property("OrderedAt") + .HasColumnType("datetime(6)"); + + b.Property("PizzaName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Status") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PizzaOrders"); + }); + + modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Auth") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Endpoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("P256DH") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PushSubscribers"); + }); + + modelBuilder.Entity("Aberwyn.Models.WeeklyMenu", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BreakfastMealId") + .HasColumnType("int"); + + b.Property("BreakfastMealName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Cook") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("DinnerMealId") + .HasColumnType("int"); + + b.Property("DinnerMealName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LunchMealId") + .HasColumnType("int"); + + b.Property("LunchMealName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("WeekNumber") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("WeeklyMenus"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + 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("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "Definition") + .WithMany() + .HasForeignKey("BudgetCategoryDefinitionId"); + + b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod") + .WithMany("Categories") + .HasForeignKey("BudgetPeriodId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BudgetPeriod"); + + b.Navigation("Definition"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItem", b => + { + b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory") + .WithMany("Items") + .HasForeignKey("BudgetCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aberwyn.Models.BudgetItemDefinition", "BudgetItemDefinition") + .WithMany() + .HasForeignKey("BudgetItemDefinitionId"); + + b.Navigation("BudgetCategory"); + + b.Navigation("BudgetItemDefinition"); + }); + + modelBuilder.Entity("Aberwyn.Models.Ingredient", b => + { + b.HasOne("Aberwyn.Models.Meal", null) + .WithMany("Ingredients") + .HasForeignKey("MealId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + 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("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Aberwyn.Models.ApplicationUser", 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("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b => + { + b.Navigation("Categories"); + }); + + modelBuilder.Entity("Aberwyn.Models.Meal", b => + { + b.Navigation("Ingredients"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Aberwyn/Migrations/20250601204720_RenameWeeklyMenusToWeeklyMenu.cs b/Aberwyn/Migrations/20250601204720_RenameWeeklyMenusToWeeklyMenu.cs new file mode 100644 index 0000000..d6a0438 --- /dev/null +++ b/Aberwyn/Migrations/20250601204720_RenameWeeklyMenusToWeeklyMenu.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Aberwyn.Migrations +{ + public partial class RenameWeeklyMenusToWeeklyMenu : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/Aberwyn/Migrations/20250601210321_AddMealNamesToWeeklyMenu.Designer.cs b/Aberwyn/Migrations/20250601210321_AddMealNamesToWeeklyMenu.Designer.cs new file mode 100644 index 0000000..5c8c31e --- /dev/null +++ b/Aberwyn/Migrations/20250601210321_AddMealNamesToWeeklyMenu.Designer.cs @@ -0,0 +1,646 @@ +// +using System; +using Aberwyn.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Aberwyn.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250601210321_AddMealNamesToWeeklyMenu")] + partial class AddMealNamesToWeeklyMenu + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.36") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Aberwyn.Models.AppSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("AppSettings"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BudgetCategoryDefinitionId") + .HasColumnType("int"); + + b.Property("BudgetPeriodId") + .HasColumnType("int"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BudgetCategoryDefinitionId"); + + b.HasIndex("BudgetPeriodId"); + + b.ToTable("BudgetCategories"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategoryDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Color") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("BudgetCategoryDefinitions"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("BudgetCategoryId") + .HasColumnType("int"); + + b.Property("BudgetItemDefinitionId") + .HasColumnType("int"); + + b.Property("IncludeInSummary") + .HasColumnType("tinyint(1)"); + + b.Property("IsExpense") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BudgetCategoryId"); + + b.HasIndex("BudgetItemDefinitionId"); + + b.ToTable("BudgetItems"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItemDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("DefaultCategory") + .HasColumnType("longtext"); + + b.Property("IncludeInSummary") + .HasColumnType("tinyint(1)"); + + b.Property("IsExpense") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("BudgetItemDefinitions"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Month") + .HasColumnType("int"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("BudgetPeriods"); + }); + + modelBuilder.Entity("Aberwyn.Models.Ingredient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Item") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MealId") + .HasColumnType("int"); + + b.Property("Quantity") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("MealId"); + + b.ToTable("Ingredients"); + }); + + modelBuilder.Entity("Aberwyn.Models.Meal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CarbType") + .HasColumnType("longtext"); + + b.Property("Category") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ImageData") + .HasColumnType("longblob"); + + b.Property("ImageMimeType") + .HasColumnType("longtext"); + + b.Property("ImageUrl") + .HasColumnType("longtext"); + + b.Property("Instructions") + .HasColumnType("longtext"); + + b.Property("IsAvailable") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProteinType") + .HasColumnType("longtext"); + + b.Property("RecipeUrl") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Meals"); + }); + + modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CustomerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IngredientsJson") + .HasColumnType("longtext"); + + b.Property("OrderedAt") + .HasColumnType("datetime(6)"); + + b.Property("PizzaName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Status") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PizzaOrders"); + }); + + modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Auth") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Endpoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("P256DH") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PushSubscribers"); + }); + + modelBuilder.Entity("Aberwyn.Models.WeeklyMenu", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BreakfastMealId") + .HasColumnType("int"); + + b.Property("BreakfastMealName") + .HasColumnType("longtext"); + + b.Property("Cook") + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("DinnerMealId") + .HasColumnType("int"); + + b.Property("DinnerMealName") + .HasColumnType("longtext"); + + b.Property("LunchMealId") + .HasColumnType("int"); + + b.Property("LunchMealName") + .HasColumnType("longtext"); + + b.Property("WeekNumber") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("WeeklyMenu", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + 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("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "Definition") + .WithMany() + .HasForeignKey("BudgetCategoryDefinitionId"); + + b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod") + .WithMany("Categories") + .HasForeignKey("BudgetPeriodId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BudgetPeriod"); + + b.Navigation("Definition"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetItem", b => + { + b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory") + .WithMany("Items") + .HasForeignKey("BudgetCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aberwyn.Models.BudgetItemDefinition", "BudgetItemDefinition") + .WithMany() + .HasForeignKey("BudgetItemDefinitionId"); + + b.Navigation("BudgetCategory"); + + b.Navigation("BudgetItemDefinition"); + }); + + modelBuilder.Entity("Aberwyn.Models.Ingredient", b => + { + b.HasOne("Aberwyn.Models.Meal", null) + .WithMany("Ingredients") + .HasForeignKey("MealId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + 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("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Aberwyn.Models.ApplicationUser", 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("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Aberwyn.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b => + { + b.Navigation("Categories"); + }); + + modelBuilder.Entity("Aberwyn.Models.Meal", b => + { + b.Navigation("Ingredients"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Aberwyn/Migrations/20250601210321_AddMealNamesToWeeklyMenu.cs b/Aberwyn/Migrations/20250601210321_AddMealNamesToWeeklyMenu.cs new file mode 100644 index 0000000..0944b37 --- /dev/null +++ b/Aberwyn/Migrations/20250601210321_AddMealNamesToWeeklyMenu.cs @@ -0,0 +1,153 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Aberwyn.Migrations +{ + public partial class AddMealNamesToWeeklyMenu : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_WeeklyMenus", + table: "WeeklyMenus"); + + migrationBuilder.RenameTable( + name: "WeeklyMenus", + newName: "WeeklyMenu"); + + migrationBuilder.AlterColumn( + name: "LunchMealName", + table: "WeeklyMenu", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "DinnerMealName", + table: "WeeklyMenu", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Cook", + table: "WeeklyMenu", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "BreakfastMealName", + table: "WeeklyMenu", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddPrimaryKey( + name: "PK_WeeklyMenu", + table: "WeeklyMenu", + column: "Id"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_WeeklyMenu", + table: "WeeklyMenu"); + + migrationBuilder.RenameTable( + name: "WeeklyMenu", + newName: "WeeklyMenus"); + + migrationBuilder.UpdateData( + table: "WeeklyMenus", + keyColumn: "LunchMealName", + keyValue: null, + column: "LunchMealName", + value: ""); + + migrationBuilder.AlterColumn( + name: "LunchMealName", + table: "WeeklyMenus", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "WeeklyMenus", + keyColumn: "DinnerMealName", + keyValue: null, + column: "DinnerMealName", + value: ""); + + migrationBuilder.AlterColumn( + name: "DinnerMealName", + table: "WeeklyMenus", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "WeeklyMenus", + keyColumn: "Cook", + keyValue: null, + column: "Cook", + value: ""); + + migrationBuilder.AlterColumn( + name: "Cook", + table: "WeeklyMenus", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "WeeklyMenus", + keyColumn: "BreakfastMealName", + keyValue: null, + column: "BreakfastMealName", + value: ""); + + migrationBuilder.AlterColumn( + name: "BreakfastMealName", + table: "WeeklyMenus", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddPrimaryKey( + name: "PK_WeeklyMenus", + table: "WeeklyMenus", + column: "Id"); + } + } +} diff --git a/Aberwyn/Migrations/ApplicationDbContextModelSnapshot.cs b/Aberwyn/Migrations/ApplicationDbContextModelSnapshot.cs index 4366b85..6ba5595 100644 --- a/Aberwyn/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Aberwyn/Migrations/ApplicationDbContextModelSnapshot.cs @@ -234,6 +234,78 @@ namespace Aberwyn.Migrations b.ToTable("BudgetPeriods"); }); + modelBuilder.Entity("Aberwyn.Models.Ingredient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Item") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MealId") + .HasColumnType("int"); + + b.Property("Quantity") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("MealId"); + + b.ToTable("Ingredients"); + }); + + modelBuilder.Entity("Aberwyn.Models.Meal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CarbType") + .HasColumnType("longtext"); + + b.Property("Category") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ImageData") + .HasColumnType("longblob"); + + b.Property("ImageMimeType") + .HasColumnType("longtext"); + + b.Property("ImageUrl") + .HasColumnType("longtext"); + + b.Property("Instructions") + .HasColumnType("longtext"); + + b.Property("IsAvailable") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProteinType") + .HasColumnType("longtext"); + + b.Property("RecipeUrl") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Meals"); + }); + modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b => { b.Property("Id") @@ -286,6 +358,50 @@ namespace Aberwyn.Migrations b.ToTable("PushSubscribers"); }); + modelBuilder.Entity("Aberwyn.Models.WeeklyMenu", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BreakfastMealId") + .HasColumnType("int"); + + b.Property("BreakfastMealName") + .HasColumnType("longtext"); + + b.Property("Cook") + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("DinnerMealId") + .HasColumnType("int"); + + b.Property("DinnerMealName") + .HasColumnType("longtext"); + + b.Property("LunchMealId") + .HasColumnType("int"); + + b.Property("LunchMealName") + .HasColumnType("longtext"); + + b.Property("WeekNumber") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("WeeklyMenu", (string)null); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") @@ -416,7 +532,7 @@ namespace Aberwyn.Migrations modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b => { - b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "BudgetItemDefinition") + b.HasOne("Aberwyn.Models.BudgetCategoryDefinition", "Definition") .WithMany() .HasForeignKey("BudgetCategoryDefinitionId"); @@ -428,7 +544,7 @@ namespace Aberwyn.Migrations b.Navigation("BudgetPeriod"); - b.Navigation("BudgetItemDefinition"); + b.Navigation("Definition"); }); modelBuilder.Entity("Aberwyn.Models.BudgetItem", b => @@ -448,6 +564,15 @@ namespace Aberwyn.Migrations b.Navigation("BudgetItemDefinition"); }); + modelBuilder.Entity("Aberwyn.Models.Ingredient", b => + { + b.HasOne("Aberwyn.Models.Meal", null) + .WithMany("Ingredients") + .HasForeignKey("MealId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -508,6 +633,11 @@ namespace Aberwyn.Migrations { b.Navigation("Categories"); }); + + modelBuilder.Entity("Aberwyn.Models.Meal", b => + { + b.Navigation("Ingredients"); + }); #pragma warning restore 612, 618 } } diff --git a/Aberwyn/Models/MenuViewModel.cs b/Aberwyn/Models/MenuViewModel.cs index 90ea593..b73721b 100644 --- a/Aberwyn/Models/MenuViewModel.cs +++ b/Aberwyn/Models/MenuViewModel.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; using Aberwyn.Data; using Aberwyn.Models; @@ -11,21 +12,25 @@ namespace Aberwyn.Models public int WeekNumber { get; set; } // Week number for the menu public int Year { get; set; } // Year for the menu } - public class WeeklyMenu - { - public int Id { get; set; } - public int DayOfWeek { get; set; } - public int? BreakfastMealId { get; set; } // 👈 Lägg till denna - public int? LunchMealId { get; set; } - public int? DinnerMealId { get; set; } - public string Cook { get; set; } - public int WeekNumber { get; set; } - public int Year { get; set; } - public string BreakfastMealName { get; set; } // 👈 Och denna - public string LunchMealName { get; set; } - public string DinnerMealName { get; set; } - public DateTime Date { get; set; } - } +public class WeeklyMenu +{ + public int Id { get; set; } + public int DayOfWeek { get; set; } + public int? BreakfastMealId { get; set; } + public int? LunchMealId { get; set; } + public int? DinnerMealId { get; set; } + public string? Cook { get; set; } + public int WeekNumber { get; set; } + public int Year { get; set; } + + [NotMapped] public string? BreakfastMealName { get; set; } + [NotMapped] public string? LunchMealName { get; set; } + [NotMapped] public string? DinnerMealName { get; set; } + + [NotMapped] public DateTime Date { get; set; } +} + + public class RecentMenuEntry { @@ -34,23 +39,27 @@ namespace Aberwyn.Models public string LunchMealName { get; set; } public string DinnerMealName { get; set; } } - public class Meal - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string ProteinType { get; set; } - public string Category { get; set; } - public string CarbType { get; set; } - public string RecipeUrl { get; set; } - public string ImageUrl { get; set; } - public bool IsAvailable { get; set; } - public DateTime CreatedAt { get; set; } - public byte[] ImageData { get; set; } - public string ImageMimeType { get; set; } // t.ex. "image/jpeg" - public string Instructions { get; set; } // 👈 Tillagningstext - public List Ingredients { get; set; } = new(); - } +public class Meal +{ + public int Id { get; set; } + public string Name { get; set; } // Behåll som obligatorisk + + public string? Description { get; set; } + public string? ProteinType { get; set; } + public string? Category { get; set; } + public string? CarbType { get; set; } + public string? RecipeUrl { get; set; } + public string? ImageUrl { get; set; } + public bool IsAvailable { get; set; } + public DateTime CreatedAt { get; set; } + + public byte[]? ImageData { get; set; } // 👈 Viktigt! + public string? ImageMimeType { get; set; } // 👈 Viktigt! + public string? Instructions { get; set; } // 👈 Viktigt! + + public List Ingredients { get; set; } = new(); +} + public class Ingredient { public int Id { get; set; } diff --git a/Aberwyn/Views/Admin/Index.cshtml b/Aberwyn/Views/Admin/Index.cshtml index a89423f..3c7bc5c 100644 --- a/Aberwyn/Views/Admin/Index.cshtml +++ b/Aberwyn/Views/Admin/Index.cshtml @@ -84,6 +84,16 @@ +
+

Importera måltider från produktion

+
+ +
+
+ +
+ +