diff --git a/Aberwyn/Aberwyn.csproj b/Aberwyn/Aberwyn.csproj index 08e1112..6466970 100644 --- a/Aberwyn/Aberwyn.csproj +++ b/Aberwyn/Aberwyn.csproj @@ -31,7 +31,7 @@ - + diff --git a/Aberwyn/Controllers/FoodMenuController.cs b/Aberwyn/Controllers/FoodMenuController.cs index 663b057..ad23c37 100644 --- a/Aberwyn/Controllers/FoodMenuController.cs +++ b/Aberwyn/Controllers/FoodMenuController.cs @@ -1,7 +1,14 @@ using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using Aberwyn.Models; using Aberwyn.Data; +using System; using System.Globalization; +using System.Linq; +using System.Collections.Generic; +using System.Text.RegularExpressions; namespace Aberwyn.Controllers { @@ -16,35 +23,89 @@ namespace Aberwyn.Controllers _env = env; } - public IActionResult Veckomeny(int week = -1) + public IActionResult Veckomeny(int? week, int? year) { var menuService = new MenuService(_configuration, _env); - int currentWeek = week == -1 ? ISOWeek.GetWeekOfYear(DateTime.Now) : week; - int currentYear = DateTime.Now.Year; - // Hämta meny frćn DB - var menus = menuService.GetWeeklyMenu(currentWeek, currentYear); + var today = DateTime.Today; + int resolvedWeek = week ?? ISOWeek.GetWeekOfYear(today); + int resolvedYear = year ?? today.Year; - var model = new WeeklyMenuViewModel + var menus = menuService.GetWeeklyMenu(resolvedWeek, resolvedYear); + + var vm = new WeeklyMenuViewModel { - WeekNumber = currentWeek, - Year = currentYear, + WeekNumber = resolvedWeek, + Year = resolvedYear, WeeklyMenus = menus, AvailableCooks = menuService.GetUsers() }; - return View(model); + var recent = menuService + .GetMenuEntriesByDateRange(DateTime.Now.AddDays(-28), DateTime.Now) + .Select(x => new WeeklyMenuViewModel.RecentMenuEntry + { + Date = x.Date, + BreakfastMealName = x.BreakfastMealName, + LunchMealName = x.LunchMealName, + DinnerMealName = x.DinnerMealName + }) + .ToList(); + + vm.RecentEntries = recent; + ViewBag.AvailableMeals = menuService.GetMeals(); + + return View(vm); + } + + [HttpPost] + public IActionResult AddMealAjax([FromBody] Meal meal) + { + if (meal == null || string.IsNullOrWhiteSpace(meal.Name)) + return BadRequest("Ogiltigt mćltidsobjekt."); + + var service = new MenuService(_configuration, _env); + + // 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 sätts automatiskt i databasen + meal.CreatedAt = DateTime.Now; + service.SaveOrUpdateMeal(meal); + existing = meal; + } + else + { + // 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; + existing.RecipeUrl = meal.RecipeUrl; + existing.ImageUrl = meal.ImageUrl; + service.SaveOrUpdateMeal(existing); + } + + return Json(new + { + Id = existing.Id, + Name = existing.Name, + Description = existing.Description, + ProteinType = existing.ProteinType, + CarbType = existing.CarbType, + RecipeUrl = existing.RecipeUrl + }); } public IActionResult MealAdmin() { var service = new MenuService(_configuration, _env); - var meals = service.GetMealsDetailed(); // Se till att denna metod finns och returnerar fullständiga Meal-objekt + var meals = service.GetMealsDetailed(); return View("MealAdmin", meals); } - - [HttpGet] public JsonResult SearchMeals(string term) { @@ -64,17 +125,16 @@ namespace Aberwyn.Controllers return Json(result); } - [HttpPost] - public IActionResult SaveVeckomeny(IFormCollection form) + public IActionResult SaveVeckomeny(IFormCollection form, int week, int year) { var menuService = new MenuService(_configuration, _env); var allMeals = menuService.GetMeals(); var model = new MenuViewModel { - WeekNumber = ISOWeek.GetWeekOfYear(DateTime.Now), - Year = DateTime.Now.Year, + WeekNumber = week, + Year = year, WeeklyMenus = new List() }; @@ -82,62 +142,76 @@ namespace Aberwyn.Controllers foreach (var key in form.Keys.Where(k => k.StartsWith("Meal[", StringComparison.OrdinalIgnoreCase))) { - var match = System.Text.RegularExpressions.Regex.Match(key, @"Meal\[(\d+)\]\[(\w+)\]"); - if (match.Success) + var match = Regex.Match(key, @"Meal\[(\d+)\]\[(\w+)\]"); + if (!match.Success) continue; + + int day = int.Parse(match.Groups[1].Value); + string mealType = match.Groups[2].Value; + string mealName = form[key]; + string cook = form[$"Cook[{day}]"]; + + if (!entriesByDay.TryGetValue(day, out var entry)) { - int day = int.Parse(match.Groups[1].Value); - string mealType = match.Groups[2].Value; - - string mealName = form[key]; - string cook = form[$"Cook[{day}][{mealType}]"]; - - if (string.IsNullOrWhiteSpace(mealName)) continue; - - var meal = allMeals.FirstOrDefault(m => m.Name.Equals(mealName, StringComparison.OrdinalIgnoreCase)); - if (meal == null) + entry = new WeeklyMenu { - meal = new Meal { Name = mealName }; - menuService.SaveMeal(meal); + WeekNumber = week, + Year = year, + DayOfWeek = day + 1 + }; + entriesByDay[day] = entry; + } + + entry.Cook = cook; + + if (string.IsNullOrWhiteSpace(mealName)) + { + switch (mealType.ToLower()) + { + case "lunch": + entry.LunchMealId = null; + entry.LunchMealName = null; + break; + case "middag": + entry.DinnerMealId = null; + entry.DinnerMealName = null; + break; + case "frukost": + entry.BreakfastMealId = null; + entry.BreakfastMealName = null; + break; } + continue; + } - if (!entriesByDay.TryGetValue(day, out var entry)) - { - entry = new WeeklyMenu - { - WeekNumber = model.WeekNumber, - Year = model.Year - }; - entriesByDay[day] = entry; - } + var meal = allMeals.FirstOrDefault(m => m.Name.Equals(mealName, StringComparison.OrdinalIgnoreCase)) + ?? new Meal { Name = mealName }; - entry.DayOfWeek = day + 1; // se till att alltid sätta rätt dag - entry.Cook = cook; + if (meal.Id == 0) + menuService.SaveOrUpdateMeal(meal); - if (mealType.Equals("Lunch", StringComparison.OrdinalIgnoreCase)) - { + switch (mealType.ToLower()) + { + case "lunch": entry.LunchMealId = meal.Id; entry.LunchMealName = meal.Name; - } - else if (mealType.Equals("Middag", StringComparison.OrdinalIgnoreCase)) - { + break; + case "middag": entry.DinnerMealId = meal.Id; entry.DinnerMealName = meal.Name; - } - else if (mealType.Equals("Frukost", StringComparison.OrdinalIgnoreCase)) - { + break; + case "frukost": entry.BreakfastMealId = meal.Id; entry.BreakfastMealName = meal.Name; - } + break; } } model.WeeklyMenus = entriesByDay.Values.ToList(); menuService.UpdateWeeklyMenu(model); - return RedirectToAction("Veckomeny"); + return RedirectToAction("Veckomeny", new { week, year }); } + + } - - - - } \ No newline at end of file +} diff --git a/Aberwyn/Controllers/MealController.cs b/Aberwyn/Controllers/MealController.cs index 8007f35..3d3d35a 100644 --- a/Aberwyn/Controllers/MealController.cs +++ b/Aberwyn/Controllers/MealController.cs @@ -15,16 +15,62 @@ namespace Aberwyn.Controllers _env = env; } [HttpGet] - public IActionResult View(int id) + public IActionResult View(int id, bool edit = false) { var service = new MenuService(_configuration, _env); var meal = service.GetMealById(id); + + ViewData["IsEditing"] = edit; // → hĂ€r + if (meal == null) + { return NotFound(); + } return View("View", meal); } + [HttpGet] + [Route("Meal/Tooltip/{id}")] + public IActionResult Tooltip(int id) + { + try + { + var service = new MenuService(_configuration, _env); + var meal = service.GetMealById(id); + + if (meal == null) + return Content("
Hittade ingen rÀtt.
", "text/html"); + + // Se till att Description aldrig Ă€r null + var desc = meal.Description ?? ""; + + // Gör en kort beskrivning + var shortDesc = desc.Length > 100 + ? desc.Substring(0, 100) + "
" + : desc; + + // Bygg upp en enkel HTML-snutt + var html = + $"
" + + $" {meal.Name}
" + + (string.IsNullOrWhiteSpace(shortDesc) + ? "Ingen beskrivning tillgÀnglig." + : $"{shortDesc}") + + "
"; + + return Content(html, "text/html"); + } + catch (Exception ex) + { + // För felsökning kan du logga ex.Message, men för tillfÀllet returnera det sÄ vi ser det i devtools + return StatusCode(500, $"
{ex.Message}
"); + } + } + + + + [HttpGet] public IActionResult Edit(int? id) { @@ -34,30 +80,33 @@ namespace Aberwyn.Controllers } [HttpPost] - public async Task SaveMeal(Meal meal, IFormFile ImageFile) + public IActionResult SaveMeal(Meal meal, IFormFile ImageFile) { var service = new MenuService(_configuration, _env); if (ImageFile != null && ImageFile.Length > 0) { - var uploadsFolder = Path.Combine(_env.ContentRootPath, "wwwroot/uploads"); - Directory.CreateDirectory(uploadsFolder); // skapa om saknas - var uniqueFileName = Guid.NewGuid().ToString() + Path.GetExtension(ImageFile.FileName); - var filePath = Path.Combine(uploadsFolder, uniqueFileName); + var fileName = Path.GetFileNameWithoutExtension(ImageFile.FileName); + var extension = Path.GetExtension(ImageFile.FileName); + var uniqueName = $"{fileName}_{Guid.NewGuid()}{extension}"; + var imagePath = Path.Combine("wwwroot/images/meals", uniqueName); - using (var fileStream = new FileStream(filePath, FileMode.Create)) + using (var stream = new FileStream(imagePath, FileMode.Create)) { - await ImageFile.CopyToAsync(fileStream); + ImageFile.CopyTo(stream); } - meal.ImageUrl = "/uploads/" + uniqueFileName; + // Spara relativ sökvĂ€g för visning + meal.ImageUrl = $"/images/meals/{uniqueName}"; } service.SaveOrUpdateMeal(meal); - return RedirectToAction("Edit", new { id = meal.Id }); + + return RedirectToAction("View", new { id = meal.Id }); } + [HttpPost] public IActionResult DeleteMeal(int id) { diff --git a/Aberwyn/Controllers/MealMenuApiController.cs b/Aberwyn/Controllers/MealMenuApiController.cs index 5a503ab..6fd5a72 100644 --- a/Aberwyn/Controllers/MealMenuApiController.cs +++ b/Aberwyn/Controllers/MealMenuApiController.cs @@ -2,6 +2,8 @@ using Aberwyn.Models; using Aberwyn.Data; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; namespace Aberwyn.Controllers { @@ -11,71 +13,45 @@ namespace Aberwyn.Controllers { private readonly MenuService _menuService; - public MealMenuApiController(MenuService menuService) + public MealMenuApiController(IConfiguration configuration, IHostEnvironment env) { - _menuService = menuService; + _menuService = new MenuService(configuration, env); } - // API endpoint to fetch the weekly menu [HttpGet("menu")] public IActionResult GetMenu(int weekNumber, int year) { var menu = _menuService.GetWeeklyMenu(weekNumber, year); - - if (menu == null || !menu.Any()) - { - // Return an empty object or array instead of a 404 error - return Ok(new List()); // Return empty list if no menu is found - } - - return Ok(menu); // Return the menu as a JSON response + return Ok(menu ?? new List()); } - // API endpoint to fetch the weekly menu [HttpGet("getMeals")] public IActionResult GetMeals() { var meals = _menuService.GetMeals(); - - if (meals == null || !meals.Any()) - { - // Return an empty object or array instead of a 404 error - return Ok(new List()); // Return empty list if no menu is found - } - - return Ok(meals); // Return the menu as a JSON response + return Ok(meals ?? new List()); } - // API endpoint to save the updated menu (if you need this) [HttpPut("menu")] public IActionResult SaveMenu([FromBody] MenuViewModel weeklyMenu) { - // Process and save the menu (you may need to write this logic) _menuService.UpdateWeeklyMenu(weeklyMenu); - return Ok("Menu saved successfully"); } - [HttpPost("addMeal")] public IActionResult AddMeal([FromBody] Meal meal) { if (meal == null || string.IsNullOrWhiteSpace(meal.Name)) - { return BadRequest("Meal Name is required."); - } + // AnvĂ€nd AddMeal som returnerar det nya ID:t var mealId = _menuService.AddMeal(meal); if (mealId > 0) - { return Ok(new { Message = "Meal added successfully", MealId = mealId }); - } return StatusCode(500, "Failed to add meal."); } - - - } } diff --git a/Aberwyn/Data/MenuService.cs b/Aberwyn/Data/MenuService.cs index e3c923c..1fe5b7e 100644 --- a/Aberwyn/Data/MenuService.cs +++ b/Aberwyn/Data/MenuService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Aberwyn.Models; +using System.Globalization; namespace Aberwyn.Data { @@ -197,7 +198,7 @@ namespace Aberwyn.Data using var connection = GetConnection(); connection.Open(); - string query = @"SELECT Id, Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt + string query = @"SELECT Id, Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt, ImageUrl FROM Meals WHERE Id = @id"; using var cmd = new MySqlCommand(query, connection); @@ -214,6 +215,7 @@ namespace Aberwyn.Data 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")) }; @@ -234,44 +236,48 @@ namespace Aberwyn.Data public void SaveOrUpdateMeal(Meal meal) { - using var connection = GetConnection(); - connection.Open(); + using var conn = new MySqlConnection(_configuration.GetConnectionString("DefaultConnection")); + conn.Open(); - string query; - bool isNew = meal.Id == 0; - - if (isNew) + using var cmd = conn.CreateCommand(); + if (meal.Id == 0) { - query = @"INSERT INTO Meals (Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt) - VALUES (@name, @desc, @protein, @carb, @url, @created)"; + cmd.CommandText = @"INSERT INTO Meals + (Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt, ImageUrl) + VALUES (@Name, @Description, @ProteinType, @CarbType, @RecipeUrl, @CreatedAt, @ImageUrl); + SELECT LAST_INSERT_ID();"; } else { - query = @"UPDATE Meals - SET Name = @name, Description = @desc, ProteinType = @protein, CarbType = @carb, RecipeUrl = @url - WHERE Id = @id"; + cmd.CommandText = @"UPDATE Meals + SET Name = @Name, Description = @Description, ProteinType = @ProteinType, + CarbType = @CarbType, RecipeUrl = @RecipeUrl, ImageUrl = @ImageUrl + WHERE Id = @Id"; + cmd.Parameters.AddWithValue("@Id", meal.Id); } - using var cmd = new MySqlCommand(query, connection); - cmd.Parameters.AddWithValue("@name", meal.Name); - cmd.Parameters.AddWithValue("@desc", meal.Description ?? ""); - cmd.Parameters.AddWithValue("@protein", meal.ProteinType ?? ""); - cmd.Parameters.AddWithValue("@carb", meal.CarbType ?? ""); - cmd.Parameters.AddWithValue("@url", meal.RecipeUrl ?? ""); + 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 ?? ""); - if (isNew) + if (meal.Id == 0) { - cmd.Parameters.AddWithValue("@created", meal.CreatedAt == default ? DateTime.Now : meal.CreatedAt); + var insertedId = Convert.ToInt32(cmd.ExecuteScalar()); + meal.Id = insertedId; // ← SĂ€tt ID direkt pĂ„ objektet } else { - cmd.Parameters.AddWithValue("@id", meal.Id); + cmd.ExecuteNonQuery(); } - - cmd.ExecuteNonQuery(); } + + public void UpdateWeeklyMenu(MenuViewModel menuData) { if (menuData == null || menuData.WeeklyMenus == null) @@ -384,6 +390,54 @@ namespace Aberwyn.Data _ => throw new System.ArgumentException("Invalid day name") }; } + 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 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)) + { + allMenus.AddRange(GetWeeklyMenu(w, y)); + + // öka vecka, hantera Ă„rsskifte + int weeksInYear = ISOWeek.GetWeeksInYear(y); + if (w == weeksInYear) + { + w = 1; + y++; + } + else + { + w++; + } + } + + // 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; + } + + } } diff --git a/Aberwyn/Models/MenuViewModel.cs b/Aberwyn/Models/MenuViewModel.cs index 525edce..dba83cd 100644 --- a/Aberwyn/Models/MenuViewModel.cs +++ b/Aberwyn/Models/MenuViewModel.cs @@ -24,9 +24,16 @@ namespace Aberwyn.Models public string BreakfastMealName { get; set; } // 👈 Och denna public string LunchMealName { get; set; } public string DinnerMealName { get; set; } + public DateTime Date { get; set; } } - + public class RecentMenuEntry + { + public DateTime Date { get; set; } + public string BreakfastMealName { get; set; } + public string LunchMealName { get; set; } + public string DinnerMealName { get; set; } + } public class Meal { public int Id { get; set; } diff --git a/Aberwyn/Models/WeeklyMenuViewModel.cs b/Aberwyn/Models/WeeklyMenuViewModel.cs index 6f7b2d8..fdb7bb8 100644 --- a/Aberwyn/Models/WeeklyMenuViewModel.cs +++ b/Aberwyn/Models/WeeklyMenuViewModel.cs @@ -5,18 +5,30 @@ using System.Linq; namespace Aberwyn.Models { + public class WeeklyMenuViewModel { public int WeekNumber { get; set; } public int Year { get; set; } + public List RecentEntries { get; set; } = new(); public List WeeklyMenus { get; set; } = new(); public List AvailableCooks { get; set; } = new(); + // Ny lista för översikt + public List PreviousWeeks { get; set; } = new(); + public class RecentMenuEntry + { + public DateTime Date { get; set; } + public string BreakfastMealName { get; set; } + public string LunchMealName { get; set; } + public string DinnerMealName { get; set; } + } + + public WeeklyMenu GetMealEntry(int day, string type) { int dayOfWeek = day + 1; - return WeeklyMenus.FirstOrDefault(m => m.DayOfWeek == dayOfWeek && ( @@ -27,4 +39,6 @@ namespace Aberwyn.Models ); } } + + } diff --git a/Aberwyn/Program.cs b/Aberwyn/Program.cs index 82a20e6..115ec82 100644 --- a/Aberwyn/Program.cs +++ b/Aberwyn/Program.cs @@ -1,28 +1,36 @@ -using Microsoft.EntityFrameworkCore; // Add this for DbContext -using Aberwyn.Data; // Include your data namespace -using MySql.EntityFrameworkCore.Extensions; // For MySQL support +using Microsoft.EntityFrameworkCore; +using Aberwyn.Data; +using MySql.EntityFrameworkCore.Extensions; using System.Text; using System.Globalization; using Microsoft.AspNetCore.Localization; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; var builder = WebApplication.CreateBuilder(args); // Add services to the container. -builder.Services.AddControllersWithViews(); -builder.Services.AddRazorPages(); // Add this line to enable Razor Pages -builder.Services.AddHttpClient(); // Register HttpClient +builder.Services.AddControllersWithViews() + .AddJsonOptions(opts => + { + // Behćll propertynamn som i C#-klassen (PascalCase) + opts.JsonSerializerOptions.PropertyNamingPolicy = null; + // Ignorera null-värden vid serialisering + opts.JsonSerializerOptions.IgnoreNullValues = true; + }); +builder.Services.AddRazorPages(); +builder.Services.AddHttpClient(); // Configure your DbContext with MySQL builder.Services.AddDbContext(options => options.UseMySQL(builder.Configuration.GetConnectionString("BudgetDb"))); - -// Register your BudgetService with a scoped lifetime +// Register your services builder.Services.AddScoped(); builder.Services.AddScoped(); - Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); builder.Services.Configure(options => { @@ -31,6 +39,7 @@ builder.Services.Configure(options => options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; }); + var app = builder.Build(); // Configure the HTTP request pipeline. @@ -40,20 +49,19 @@ if (!app.Environment.IsDevelopment()) app.UseHsts(); } -//app.UseHttpsRedirection(); app.UseStaticFiles(); - app.UseRouting(); - app.UseAuthorization(); +// Map controller endpoints (including AJAX JSON actions) +app.MapControllers(); -// Map default controller route +// Conventional MVC route app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); // Map Razor Pages -app.MapRazorPages(); // Add this line to map Razor Pages +app.MapRazorPages(); app.Run(); diff --git a/Aberwyn/Views/FoodMenu/Veckomeny.cshtml b/Aberwyn/Views/FoodMenu/Veckomeny.cshtml index 975068a..d6306a9 100644 --- a/Aberwyn/Views/FoodMenu/Veckomeny.cshtml +++ b/Aberwyn/Views/FoodMenu/Veckomeny.cshtml @@ -1,93 +1,229 @@ -@model WeeklyMenuViewModel +@using System.Globalization +@model Aberwyn.Models.WeeklyMenuViewModel @{ ViewData["Title"] = "Veckomeny"; var days = new[] { "MĂ„ndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag", "Söndag" }; - var mealTypes = new[] { "Frukost", "Lunch", "Middag" }; + var allMeals = ViewBag.AvailableMeals as List; } -

Veckomeny - Vecka @Model.WeekNumber

+ -
- FöregÄende vecka - NÀsta vecka + + + + +
+ + + + +
+

Veckomeny - Vecka @Model.WeekNumber

+
+ ← FöregĂ„ende vecka + Vecka @Model.WeekNumber + NĂ€sta vecka → +
+ +
+ + + + + + + + + + + + @for (int i = 0; i < 7; i++) { + var dinnerEntry = Model.GetMealEntry(i, "Middag"); + var lunchEntry = Model.GetMealEntry(i, "Lunch"); + var breakfastEntry = Model.GetMealEntry(i, "Frukost"); + + + + + + + + + + + + } + +
DagMiddagKock
+ + @days[i] + +
+ + +
+
+ +
+
+
+ + + +
+
+ + + +
+
+
+ + +
+ +
+ + + @foreach(var m in ViewBag.AvailableMeals as List) { + + } + +
-
- - - - - @foreach (var mealType in mealTypes) - { - - } - - - - @for (int i = 0; i < 7; i++) - { - - - @foreach (var mealType in mealTypes) - { - var entry = Model.GetMealEntry(i, mealType); - var mealName = mealType switch - { - "Frukost" => entry?.BreakfastMealName, - "Lunch" => entry?.LunchMealName, - "Middag" => entry?.DinnerMealName, - _ => null - }; - - } - - } - - - -
- -@section Scripts { - - -} diff --git a/Aberwyn/Views/Home/Menu.cshtml b/Aberwyn/Views/Home/Menu.cshtml index ef2c6c1..1ef2936 100644 --- a/Aberwyn/Views/Home/Menu.cshtml +++ b/Aberwyn/Views/Home/Menu.cshtml @@ -1,54 +1,97 @@ ï»ż@model Aberwyn.Models.MenuViewModel @{ - // Define a flag to hide the sidebar if the URL path matches '/nosidebar' (relative part after the controller) - bool hideSidebar = Context.Request.Path.Value.EndsWith("/nosidebar", StringComparison.OrdinalIgnoreCase); - Layout = hideSidebar ? null : "_Layout"; // No layout if the path ends with '/nosidebar' + var hideSidebar = Context.Request.Path.Value.EndsWith("/nosidebar", StringComparison.OrdinalIgnoreCase); + Layout = hideSidebar ? null : "_Layout"; } - - + - - Meal Menu Overview + + Veckomeny + + + - + + + - + +
+

Veckomeny

-
-

Meal Menu Overview

- -
- - Vecka {{ selectedWeek }} - {{ selectedYear }} - -
- -
-
-
{{ day }}
- -
-
-
- Frukost: {{ menu[day].breakfastMealName }} -
-
- Lunch: {{ menu[day].lunchMealName }} -
-
- Middag: {{ menu[day].dinnerMealName }} -
-
-
- Inte bestÀmd -
-
-
-
+ +
+ + Vecka {{selectedWeek}} – {{selectedYear}} +
+ + +
+ + +
+ + +
+ + +
+
+
+
+
{{day}}
+
Frukost: {{menu[day].breakfastMealName}}
+
Lunch: {{menu[day].lunchMealName}}
+
Middag: {{menu[day].dinnerMealName}}
+
Inte bestÀmd
+
+
+
+
+
+
diff --git a/Aberwyn/Views/Meal/Meal.cshtml b/Aberwyn/Views/Meal/Meal.cshtml index 2dac870..e9560f1 100644 --- a/Aberwyn/Views/Meal/Meal.cshtml +++ b/Aberwyn/Views/Meal/Meal.cshtml @@ -40,7 +40,7 @@
- +
diff --git a/Aberwyn/Views/Meal/View.cshtml b/Aberwyn/Views/Meal/View.cshtml index a2230f5..f97fb44 100644 --- a/Aberwyn/Views/Meal/View.cshtml +++ b/Aberwyn/Views/Meal/View.cshtml @@ -1,90 +1,192 @@ ï»ż@model Aberwyn.Models.Meal @{ ViewData["Title"] = Model.Name; + bool isEditing = (bool)(ViewData["IsEditing"] ?? false); + var imageUrl = string.IsNullOrEmpty(Model.ImageUrl) ? "/images/placeholder-meal.jpg" : Model.ImageUrl; }
-

@Model.Name

- - @if (!string.IsNullOrEmpty(Model.ImageUrl)) - { - @Model.Name - } - - @if (!string.IsNullOrEmpty(Model.Description)) - { -

@Model.Description

- } - -
- - Redigera +
+ @Model.Name +
+

@Model.Name

+

@Model.Description

+
- diff --git a/Aberwyn/Views/Meal/_MealTooltip.cshtml b/Aberwyn/Views/Meal/_MealTooltip.cshtml new file mode 100644 index 0000000..d587e43 --- /dev/null +++ b/Aberwyn/Views/Meal/_MealTooltip.cshtml @@ -0,0 +1,8 @@ +ï»ż@model dynamic +
+ @Model.Name
+ @Model.ShortDescription
+ @if (Model.Ingredients != null) { +
Ingredienser: @String.Join(", ", Model.Ingredients)
+ } +
diff --git a/Aberwyn/wwwroot/css/meal-menu.css b/Aberwyn/wwwroot/css/meal-menu.css index d263455..eab75de 100644 --- a/Aberwyn/wwwroot/css/meal-menu.css +++ b/Aberwyn/wwwroot/css/meal-menu.css @@ -208,3 +208,7 @@ .new-meal-form button:hover { background-color: #F57C00; } + +.meal-hover { + cursor: pointer; +} diff --git a/Aberwyn/wwwroot/images/21f12523-36e9-451f-b120-d9cac21061fe.png b/Aberwyn/wwwroot/images/21f12523-36e9-451f-b120-d9cac21061fe.png new file mode 100644 index 0000000..116c3be Binary files /dev/null and b/Aberwyn/wwwroot/images/21f12523-36e9-451f-b120-d9cac21061fe.png differ diff --git a/Aberwyn/wwwroot/uploads/fc8aff8c-4bef-45a8-9e40-7b78f76f04e8.png b/Aberwyn/wwwroot/images/fc8aff8c-4bef-45a8-9e40-7b78f76f04e8.png similarity index 100% rename from Aberwyn/wwwroot/uploads/fc8aff8c-4bef-45a8-9e40-7b78f76f04e8.png rename to Aberwyn/wwwroot/images/fc8aff8c-4bef-45a8-9e40-7b78f76f04e8.png diff --git a/Aberwyn/wwwroot/images/meals/mcdonalds_75ac2dd7-1115-43c3-b5fd-2829bf2395de.png b/Aberwyn/wwwroot/images/meals/mcdonalds_75ac2dd7-1115-43c3-b5fd-2829bf2395de.png new file mode 100644 index 0000000..116c3be Binary files /dev/null and b/Aberwyn/wwwroot/images/meals/mcdonalds_75ac2dd7-1115-43c3-b5fd-2829bf2395de.png differ diff --git a/Aberwyn/wwwroot/images/meals/test_93c95185-81d2-4b9b-9286-39c7dcd0ddb1.png b/Aberwyn/wwwroot/images/meals/test_93c95185-81d2-4b9b-9286-39c7dcd0ddb1.png new file mode 100644 index 0000000..e39e4c9 Binary files /dev/null and b/Aberwyn/wwwroot/images/meals/test_93c95185-81d2-4b9b-9286-39c7dcd0ddb1.png differ diff --git a/Aberwyn/wwwroot/js/menu.js b/Aberwyn/wwwroot/js/menu.js index f355bb2..7b2a07a 100644 --- a/Aberwyn/wwwroot/js/menu.js +++ b/Aberwyn/wwwroot/js/menu.js @@ -1,99 +1,84 @@ -ï»żangular.module('mealMenuApp', []) - .controller('MealMenuController', function ($scope, $http) { - $scope.isEditing = false; - $scope.toggleEditMode = function () { - $scope.isEditing = !$scope.isEditing; - }; +ï»żangular.module('mealMenuApp', ['ngSanitize']) + .controller('MealMenuController', function ($scope, $http, $sce) { + console.log("Controller initierad"); + $scope.viewMode = 'list'; + $scope.tooltip = {}; $scope.meals = []; $scope.menu = {}; - $scope.showNewMealForm = false; - $scope.newMeal = {}; - $scope.selectedMealDay = null; - $scope.selectedMealType = null; - const today = new Date(); $scope.selectedWeek = getWeek(today); $scope.selectedYear = today.getFullYear(); $scope.daysOfWeek = ["MĂ„ndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag", "Söndag"]; $scope.loadMeals = function () { - $http.get('/api/mealMenuApi/getMeals') - .then(response => { - $scope.meals = response.data; + console.log("HĂ€mtar mĂ„ltider..."); + return $http.get('/api/mealMenuApi/getMeals') + .then(res => { + console.log("MĂ„ltider hĂ€mtade:", res.data); + $scope.meals = res.data; + return res; }) - .catch(error => console.error("Error fetching meals:", error)); + .catch(err => console.error("Fel vid hĂ€mtning av mĂ„ltider:", err)); }; $scope.loadMenu = function () { + console.log("HĂ€mtar meny för vecka:", $scope.selectedWeek, $scope.selectedYear); $http.get('/api/mealMenuApi/menu', { params: { weekNumber: $scope.selectedWeek, year: $scope.selectedYear } - }).then(response => { - console.log("Veckomenydata:", response.data); // ✅ logga ut - + }).then(res => { + console.log("Menyposter hĂ€mtade:", res.data); $scope.menu = {}; - response.data.forEach(item => { - const dayOfWeek = $scope.daysOfWeek[item.dayOfWeek - 1]; - if (!$scope.menu[dayOfWeek]) $scope.menu[dayOfWeek] = {}; - if (item.breakfastMealId) { - $scope.menu[dayOfWeek].breakfastMealId = item.breakfastMealId; - $scope.menu[dayOfWeek].breakfastMealName = getMealNameById(item.breakfastMealId); - } - if (item.lunchMealId) { - $scope.menu[dayOfWeek].lunchMealId = item.lunchMealId; - $scope.menu[dayOfWeek].lunchMealName = getMealNameById(item.lunchMealId); - } - if (item.dinnerMealId) { - $scope.menu[dayOfWeek].dinnerMealId = item.dinnerMealId; - $scope.menu[dayOfWeek].dinnerMealName = getMealNameById(item.dinnerMealId); + res.data.forEach(item => { + const dayIndex = item.DayOfWeek - 1; + if (dayIndex < 0 || dayIndex >= $scope.daysOfWeek.length) { + console.warn("Ogiltig dag:", item.DayOfWeek); + return; } + + const day = $scope.daysOfWeek[dayIndex]; + $scope.menu[day] = {}; + + ['breakfast', 'lunch', 'dinner'].forEach(type => { + // Konvertera till PascalCase + const capitalType = type.charAt(0).toUpperCase() + type.slice(1); + const idKey = capitalType + 'MealId'; + const nameKey = capitalType + 'MealName'; + + if (item[idKey]) { + const m = $scope.meals.find(x => x.Id === item[idKey]); + console.log(`Match för ${type} (${day}):`, m); + + $scope.menu[day][type + 'MealId'] = item[idKey]; + $scope.menu[day][type + 'MealName'] = m?.Name || item[nameKey] || 'OkĂ€nd rĂ€tt'; + + if (m?.ImageUrl) { + $scope.menu[day].imageUrl = m.ImageUrl; + } + } + }); }); - }).catch(error => console.error("Error fetching weekly menu:", error)); + + console.log("Byggd meny:", $scope.menu); + }).catch(err => console.error("Fel vid hĂ€mtning av veckomeny:", err)); }; - function getMealNameById(mealId) { - const meal = $scope.meals.find(m => m.id === mealId); - return meal ? meal.name : "Unknown Meal"; - } - - $scope.handleMealSelection = function (day, mealType) { - if ($scope.menu[day][mealType + "MealId"] === "new") { - $scope.showNewMealForm = true; - $scope.newMeal = { name: "", description: "", proteinType: "", carbType: "", recipeUrl: "" }; - $scope.selectedMealDay = day; - $scope.selectedMealType = mealType; - } + $scope.openMeal = function (mealId) { + if (!mealId) return; + window.open('/Meal/View/' + mealId, '_blank'); }; - $scope.saveNewMeal = function () { - if (!$scope.newMeal.name) { - alert("Meal name is required"); - return; - } - $http.post('/api/mealMenuApi/addMeal', $scope.newMeal) - .then(response => { - const addedMeal = response.data; - $scope.meals.push(addedMeal); - $scope.menu[$scope.selectedMealDay][$scope.selectedMealType + "MealId"] = addedMeal.id; - $scope.showNewMealForm = false; - $scope.newMeal = {}; // Reset new meal data after save - }) - .catch(error => console.error("Error saving new meal:", error)); + $scope.getDayImage = function (day) { + const item = $scope.menu[day]; + return (item && item.imageUrl) || '/images/default-meal.jpg'; }; - $scope.cancelNewMeal = function () { - $scope.showNewMealForm = false; - $scope.newMeal = {}; // Reset new meal data when canceled + $scope.getMealIdByDay = function (day) { + const item = $scope.menu[day] || {}; + return item.dinnerMealId || item.lunchMealId || item.breakfastMealId || null; }; - function getWeek(date) { - const day = date.getDay() || 7; - date.setDate(date.getDate() + 4 - day); - const yearStart = new Date(date.getFullYear(), 0, 1); - return Math.ceil(((date - yearStart) / 86400000 + 1) / 7); - } - $scope.goToPreviousWeek = function () { if ($scope.selectedWeek === 1) { $scope.selectedYear--; @@ -114,6 +99,17 @@ $scope.loadMenu(); }; - $scope.loadMeals(); - $scope.loadMenu(); + function getWeek(d) { + d = new Date(d.getFullYear(), d.getMonth(), d.getDate()); + const dayNum = d.getDay() || 7; + d.setDate(d.getDate() + 4 - dayNum); + const yearStart = new Date(d.getFullYear(), 0, 1); + return Math.ceil((((d - yearStart) / 86400000) + 1) / 7); + } + + console.log("Initierar mĂ„ltidsladdning..."); + $scope.loadMeals().then(() => { + console.log("Laddar meny efter mĂ„ltider..."); + $scope.loadMenu(); + }); });