diff --git a/Aberwyn/Aberwyn.csproj b/Aberwyn/Aberwyn.csproj index 348d660..08e1112 100644 --- a/Aberwyn/Aberwyn.csproj +++ b/Aberwyn/Aberwyn.csproj @@ -3,12 +3,12 @@ net6.0 enable + false enable d748f28f-7908-4174-b2a1-c21d4d06499f Linux - @@ -29,4 +29,9 @@ + + + + + diff --git a/Aberwyn/Aberwyn_Veckomeny_v1.zip b/Aberwyn/Aberwyn_Veckomeny_v1.zip new file mode 100644 index 0000000..7dac77e Binary files /dev/null and b/Aberwyn/Aberwyn_Veckomeny_v1.zip differ diff --git a/Aberwyn/Controllers/FoodMenuController.cs b/Aberwyn/Controllers/FoodMenuController.cs new file mode 100644 index 0000000..663b057 --- /dev/null +++ b/Aberwyn/Controllers/FoodMenuController.cs @@ -0,0 +1,143 @@ +using Microsoft.AspNetCore.Mvc; +using Aberwyn.Models; +using Aberwyn.Data; +using System.Globalization; + +namespace Aberwyn.Controllers +{ + public class FoodMenuController : Controller + { + private readonly IConfiguration _configuration; + private readonly IHostEnvironment _env; + + public FoodMenuController(IConfiguration configuration, IHostEnvironment env) + { + _configuration = configuration; + _env = env; + } + + public IActionResult Veckomeny(int week = -1) + { + 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 model = new WeeklyMenuViewModel + { + WeekNumber = currentWeek, + Year = currentYear, + WeeklyMenus = menus, + AvailableCooks = menuService.GetUsers() + }; + + return View(model); + } + + 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 + return View("MealAdmin", meals); + } + + + + [HttpGet] + public JsonResult SearchMeals(string term) + { + if (string.IsNullOrWhiteSpace(term)) + return Json(new List()); + + var menuService = new MenuService(_configuration, _env); + var meals = menuService.GetMeals(); + + var result = meals + .Where(m => m.Name != null && m.Name.Contains(term, StringComparison.OrdinalIgnoreCase)) + .Select(m => m.Name) + .Distinct() + .Take(10) + .ToList(); + + return Json(result); + } + + + [HttpPost] + public IActionResult SaveVeckomeny(IFormCollection form) + { + var menuService = new MenuService(_configuration, _env); + var allMeals = menuService.GetMeals(); + + var model = new MenuViewModel + { + WeekNumber = ISOWeek.GetWeekOfYear(DateTime.Now), + Year = DateTime.Now.Year, + WeeklyMenus = new List() + }; + + var entriesByDay = new Dictionary(); + + 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) + { + 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) + { + meal = new Meal { Name = mealName }; + menuService.SaveMeal(meal); + } + + if (!entriesByDay.TryGetValue(day, out var entry)) + { + entry = new WeeklyMenu + { + WeekNumber = model.WeekNumber, + Year = model.Year + }; + entriesByDay[day] = entry; + } + + entry.DayOfWeek = day + 1; // se till att alltid sätta rätt dag + entry.Cook = cook; + + if (mealType.Equals("Lunch", StringComparison.OrdinalIgnoreCase)) + { + entry.LunchMealId = meal.Id; + entry.LunchMealName = meal.Name; + } + else if (mealType.Equals("Middag", StringComparison.OrdinalIgnoreCase)) + { + entry.DinnerMealId = meal.Id; + entry.DinnerMealName = meal.Name; + } + else if (mealType.Equals("Frukost", StringComparison.OrdinalIgnoreCase)) + { + entry.BreakfastMealId = meal.Id; + entry.BreakfastMealName = meal.Name; + } + } + } + + model.WeeklyMenus = entriesByDay.Values.ToList(); + menuService.UpdateWeeklyMenu(model); + + return RedirectToAction("Veckomeny"); + } + } + + + + } \ No newline at end of file diff --git a/Aberwyn/Controllers/HomeController.cs b/Aberwyn/Controllers/HomeController.cs index 15df38f..dda595f 100644 --- a/Aberwyn/Controllers/HomeController.cs +++ b/Aberwyn/Controllers/HomeController.cs @@ -39,6 +39,8 @@ namespace Aberwyn.Controllers public IActionResult Menu() { + + ViewData["HideSidebar"] = true; // Get the current date and week var currentDate = DateTime.Now; var currentYear = currentDate.Year; diff --git a/Aberwyn/Controllers/MealController.cs b/Aberwyn/Controllers/MealController.cs new file mode 100644 index 0000000..8007f35 --- /dev/null +++ b/Aberwyn/Controllers/MealController.cs @@ -0,0 +1,69 @@ +ï»żusing Microsoft.AspNetCore.Mvc; +using Aberwyn.Models; +using Aberwyn.Data; + +namespace Aberwyn.Controllers +{ + public class MealController : Controller + { + private readonly IConfiguration _configuration; + private readonly IHostEnvironment _env; + + public MealController(IConfiguration configuration, IHostEnvironment env) + { + _configuration = configuration; + _env = env; + } + [HttpGet] + public IActionResult View(int id) + { + var service = new MenuService(_configuration, _env); + var meal = service.GetMealById(id); + if (meal == null) + return NotFound(); + + return View("View", meal); + } + + [HttpGet] + public IActionResult Edit(int? id) + { + var service = new MenuService(_configuration, _env); + var meal = id.HasValue ? service.GetMealById(id.Value) : new Meal(); + return View("Meal", meal); + } + + [HttpPost] + public async Task 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); + + using (var fileStream = new FileStream(filePath, FileMode.Create)) + { + await ImageFile.CopyToAsync(fileStream); + } + + meal.ImageUrl = "/uploads/" + uniqueFileName; + } + + service.SaveOrUpdateMeal(meal); + return RedirectToAction("Edit", new { id = meal.Id }); + } + + + [HttpPost] + public IActionResult DeleteMeal(int id) + { + var service = new MenuService(_configuration, _env); + //service.DeleteMeal(id); + return RedirectToAction("Edit"); // eller tillbaka till lista + } + } +} diff --git a/Aberwyn/Data/MenuService.cs b/Aberwyn/Data/MenuService.cs index dc0ad90..e3c923c 100644 --- a/Aberwyn/Data/MenuService.cs +++ b/Aberwyn/Data/MenuService.cs @@ -25,6 +25,65 @@ namespace Aberwyn.Data 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; + + meal.Name = meal.Name.Trim(); + + using var connection = GetConnection(); + connection.Open(); + + 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}"); + } + } public List GetWeeklyMenu(int weekNumber, int year) { @@ -33,12 +92,16 @@ namespace Aberwyn.Data { connection.Open(); string query = @" - SELECT wm.Id, wm.DayOfWeek, wm.DinnerMealId, wm.LunchMealId, wm.WeekNumber, wm.Year, - dm.Name AS DinnerMealName, lm.Name AS LunchMealName - FROM WeeklyMenu wm - LEFT JOIN Meals dm ON wm.DinnerMealId = dm.Id - LEFT JOIN Meals lm ON wm.LunchMealId = lm.Id - WHERE wm.WeekNumber = @weekNumber AND wm.Year = @year"; + 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"; using (var cmd = new MySqlCommand(query, connection)) { @@ -53,13 +116,15 @@ namespace Aberwyn.Data { Id = reader.GetInt32("Id"), DayOfWeek = reader.GetInt32("DayOfWeek"), - DinnerMealId = reader.IsDBNull(reader.GetOrdinal("DinnerMealId")) ? (int?)null : reader.GetInt32("DinnerMealId"), - LunchMealId = reader.IsDBNull(reader.GetOrdinal("LunchMealId")) ? (int?)null : reader.GetInt32("LunchMealId"), + 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"), - DinnerMealName = reader.IsDBNull(reader.GetOrdinal("DinnerMealName")) ? null : reader.GetString("DinnerMealName"), - LunchMealName = reader.IsDBNull(reader.GetOrdinal("LunchMealName")) ? null : reader.GetString("LunchMealName"), - + 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")) }); } } @@ -68,6 +133,7 @@ namespace Aberwyn.Data return weeklyMenu; } + public List GetMeals() { var meals = new List(); @@ -92,6 +158,119 @@ namespace Aberwyn.Data } return meals; } + public List GetMealsDetailed() + { + var meals = new List(); + + using (var connection = GetConnection()) + { + connection.Open(); + string query = @" + SELECT Id, Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt + 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")), + CreatedAt = reader.GetDateTime(reader.GetOrdinal("CreatedAt")) + }); + } + } + } + + return meals; + } + + public Meal GetMealById(int id) + { + using var connection = GetConnection(); + connection.Open(); + + string query = @"SELECT Id, Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt + 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")), + CreatedAt = reader.GetDateTime(reader.GetOrdinal("CreatedAt")) + }; + + } + + return null; + } + + 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(); + } + + public void SaveOrUpdateMeal(Meal meal) + { + using var connection = GetConnection(); + connection.Open(); + + string query; + bool isNew = meal.Id == 0; + + if (isNew) + { + query = @"INSERT INTO Meals (Name, Description, ProteinType, CarbType, RecipeUrl, CreatedAt) + VALUES (@name, @desc, @protein, @carb, @url, @created)"; + } + else + { + query = @"UPDATE Meals + SET Name = @name, Description = @desc, ProteinType = @protein, CarbType = @carb, RecipeUrl = @url + WHERE Id = @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 ?? ""); + + if (isNew) + { + cmd.Parameters.AddWithValue("@created", meal.CreatedAt == default ? DateTime.Now : meal.CreatedAt); + } + else + { + cmd.Parameters.AddWithValue("@id", meal.Id); + } + + cmd.ExecuteNonQuery(); + } + public void UpdateWeeklyMenu(MenuViewModel menuData) { @@ -105,33 +284,50 @@ namespace Aberwyn.Data { try { - // Loop over each WeeklyMenu in the WeeklyMenus list - foreach (var weeklyMenu in menuData.WeeklyMenus) + foreach (var menu in menuData.WeeklyMenus) { - int dayOfWeek = weeklyMenu.DayOfWeek; - var menu = weeklyMenu; + int dayOfWeek = menu.DayOfWeek; - // SQL query to update the existing records - string query = @" + string updateQuery = @" UPDATE WeeklyMenu SET - DinnerMealId = @dinnerMealId, + BreakfastMealId = @breakfastMealId, LunchMealId = @lunchMealId, + DinnerMealId = @dinnerMealId, Cook = @cook WHERE DayOfWeek = @dayOfWeek AND WeekNumber = @weekNumber AND Year = @year;"; - using (var cmd = new MySqlCommand(query, connection, transaction)) + using (var cmd = new MySqlCommand(updateQuery, connection, transaction)) { cmd.Parameters.AddWithValue("@dayOfWeek", dayOfWeek); - cmd.Parameters.AddWithValue("@dinnerMealId", menu.DinnerMealId ?? (object)DBNull.Value); + 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); - cmd.ExecuteNonQuery(); + 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(); + } } } @@ -147,6 +343,7 @@ namespace Aberwyn.Data } } + public int AddMeal(Meal meal) { using (var connection = GetConnection()) diff --git a/Aberwyn/Dockerfile b/Aberwyn/Dockerfile index d944d2d..defcf32 100644 --- a/Aberwyn/Dockerfile +++ b/Aberwyn/Dockerfile @@ -1,40 +1,22 @@ -# Base image for runtime +#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. + FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app +EXPOSE 80 +EXPOSE 443 -RUN mkdir -p /app/build && chmod -R 777 /app/build - -# Leave the ports exposed to allow Unraid to configure them -EXPOSE 80 443 - -# Image for building the project FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src - -# Copy the .csproj and restore dependencies -COPY Aberwyn/Aberwyn.csproj ./ -RUN dotnet restore - -#COPY Aberwyn/Aberwyn.csproj ./Aberwyn/ -#WORKDIR /src/Aberwyn -#RUN dotnet restore - - -# Copy everything else and build the app +COPY ["Aberwyn/Aberwyn.csproj", "Aberwyn/"] +RUN dotnet restore "Aberwyn/Aberwyn.csproj" COPY . . -RUN dotnet build Aberwyn.csproj -c Release -o /app/build/ +WORKDIR "/src/Aberwyn" +RUN dotnet build "Aberwyn.csproj" -c Release -o /app/build -# Publish the app to the /app/publish folder FROM build AS publish -RUN dotnet publish Aberwyn.csproj -c Release -o /app/publish +RUN dotnet publish "Aberwyn.csproj" -c Release -o /app/publish -# Use the base runtime image to run the app FROM base AS final WORKDIR /app COPY --from=publish /app/publish . - -# Use environment variable for ports to allow flexibility -ENV ASPNETCORE_URLS="http://+:80" - -# Set entry point to start the application -ENTRYPOINT ["dotnet", "Aberwyn.dll"] +ENTRYPOINT ["dotnet", "Aberwyn.dll"] \ No newline at end of file diff --git a/Aberwyn/Models/MenuViewModel.cs b/Aberwyn/Models/MenuViewModel.cs index c911363..525edce 100644 --- a/Aberwyn/Models/MenuViewModel.cs +++ b/Aberwyn/Models/MenuViewModel.cs @@ -15,15 +15,18 @@ namespace Aberwyn.Models { public int Id { get; set; } public int DayOfWeek { get; set; } - public int? DinnerMealId { 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 DinnerMealName { get; set; } + public string BreakfastMealName { get; set; } // 👈 Och denna public string LunchMealName { get; set; } + public string DinnerMealName { get; set; } } + public class Meal { public int Id { get; set; } @@ -32,6 +35,7 @@ namespace Aberwyn.Models public string ProteinType { get; set; } public string CarbType { get; set; } public string RecipeUrl { get; set; } + public string ImageUrl { get; set; } public DateTime CreatedAt { get; set; } } } diff --git a/Aberwyn/Models/User.cs b/Aberwyn/Models/User.cs new file mode 100644 index 0000000..c00ed42 --- /dev/null +++ b/Aberwyn/Models/User.cs @@ -0,0 +1,10 @@ +ï»żnamespace Aberwyn.Models +{ + public class User + { + public int UserID { get; set; } + public string Username { get; set; } + public string Name { get; set; } + } + +} diff --git a/Aberwyn/Models/WeeklyMenuViewModel.cs b/Aberwyn/Models/WeeklyMenuViewModel.cs new file mode 100644 index 0000000..6f7b2d8 --- /dev/null +++ b/Aberwyn/Models/WeeklyMenuViewModel.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +namespace Aberwyn.Models +{ + public class WeeklyMenuViewModel + { + public int WeekNumber { get; set; } + public int Year { get; set; } + + public List WeeklyMenus { get; set; } = new(); + public List AvailableCooks { get; set; } = new(); + + public WeeklyMenu GetMealEntry(int day, string type) + { + int dayOfWeek = day + 1; + + return WeeklyMenus.FirstOrDefault(m => + m.DayOfWeek == dayOfWeek && + ( + (type == "Frukost" && m.BreakfastMealId.HasValue) || + (type == "Lunch" && m.LunchMealId.HasValue) || + (type == "Middag" && m.DinnerMealId.HasValue) + ) + ); + } + } +} diff --git a/Aberwyn/Program.cs b/Aberwyn/Program.cs index b9e26af..82a20e6 100644 --- a/Aberwyn/Program.cs +++ b/Aberwyn/Program.cs @@ -1,6 +1,9 @@ using Microsoft.EntityFrameworkCore; // Add this for DbContext using Aberwyn.Data; // Include your data namespace using MySql.EntityFrameworkCore.Extensions; // For MySQL support +using System.Text; +using System.Globalization; +using Microsoft.AspNetCore.Localization; var builder = WebApplication.CreateBuilder(args); @@ -20,6 +23,14 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); +Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); +builder.Services.Configure(options => +{ + var supportedCultures = new[] { new CultureInfo("sv-SE") }; + options.DefaultRequestCulture = new RequestCulture("sv-SE"); + options.SupportedCultures = supportedCultures; + options.SupportedUICultures = supportedCultures; +}); var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/Aberwyn/Views/FoodMenu/MealAdmin.cshtml b/Aberwyn/Views/FoodMenu/MealAdmin.cshtml new file mode 100644 index 0000000..838ee38 --- /dev/null +++ b/Aberwyn/Views/FoodMenu/MealAdmin.cshtml @@ -0,0 +1,45 @@ +ï»ż@model List +@{ + ViewData["Title"] = "Alla mĂ„ltider"; +} + +

Alla mÄltider

+ + + + + + + + + + + + + + + @foreach (var meal in Model) + { + + + + + + + + + + } + +
NamnBeskrivningProteinKolhydratReceptlÀnkSkapadRedigera
+ @meal.Name + @meal.Description@meal.ProteinType@meal.CarbType + @if (!string.IsNullOrWhiteSpace(meal.RecipeUrl)) + { + LĂ€nk + } + @meal.CreatedAt.ToString("yyyy-MM-dd") + Redigera +
+ +LÀgg till ny mÄltid diff --git a/Aberwyn/Views/FoodMenu/Veckomeny.cshtml b/Aberwyn/Views/FoodMenu/Veckomeny.cshtml new file mode 100644 index 0000000..975068a --- /dev/null +++ b/Aberwyn/Views/FoodMenu/Veckomeny.cshtml @@ -0,0 +1,93 @@ +@model WeeklyMenuViewModel +@{ + ViewData["Title"] = "Veckomeny"; + var days = new[] { "MÄndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag", "Söndag" }; + var mealTypes = new[] { "Frukost", "Lunch", "Middag" }; +} + +

Veckomeny - Vecka @Model.WeekNumber

+ + + +
+ + + + + @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/Index.cshtml b/Aberwyn/Views/Home/Index.cshtml index 88c8ce4..905ed9a 100644 --- a/Aberwyn/Views/Home/Index.cshtml +++ b/Aberwyn/Views/Home/Index.cshtml @@ -1,127 +1,21 @@ ï»ż@{ - ViewData["Title"] = "Home Page"; + ViewData["Title"] = "Welcome to Aberwyn!"; } -
- - - + + - - - - - + + + @ViewData["Title"] + - - - - - - - -
- - - - - -
- -
- - - - - - - - - - - - - -

- - - -
- - - - - - - - - -
- + +
+

Welcome to Aberwyn!

+

Your home for managing all your budget and meal planning needs.

+

We’re glad to have you here. Get started by exploring our features.

+ Learn More +
- -
diff --git a/Aberwyn/Views/Home/Menu.cshtml b/Aberwyn/Views/Home/Menu.cshtml index b8e87a0..ef2c6c1 100644 --- a/Aberwyn/Views/Home/Menu.cshtml +++ b/Aberwyn/Views/Home/Menu.cshtml @@ -1,7 +1,9 @@ ï»ż@model Aberwyn.Models.MenuViewModel @{ - Layout = "_Layout"; + // 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' } @@ -20,14 +22,9 @@

Meal Menu Overview

- - Week {{ selectedWeek }} - {{ selectedYear }} - -
- -
- - + + Vecka {{ selectedWeek }} - {{ selectedYear }} +
@@ -37,62 +34,21 @@
- Breakfast: {{ menu[day].breakfastMealName }} + Frukost: {{ menu[day].breakfastMealName }}
Lunch: {{ menu[day].lunchMealName }}
- Dinner: {{ menu[day].dinnerMealName }} + Middag: {{ menu[day].dinnerMealName }}
- Not Assigned -
-
- -
-
- Breakfast: - -
-
- Lunch: - -
-
- Dinner: - + Inte bestÀmd
- - - -
-

Add a New Meal

- - - - - - - -
- diff --git a/Aberwyn/Views/Meal/Meal.cshtml b/Aberwyn/Views/Meal/Meal.cshtml new file mode 100644 index 0000000..2dac870 --- /dev/null +++ b/Aberwyn/Views/Meal/Meal.cshtml @@ -0,0 +1,77 @@ +ï»ż@model Aberwyn.Models.Meal +@{ + ViewData["Title"] = Model.Id == 0 ? "Ny mĂ„ltid" : Model.Name; + var isNew = Model.Id == 0; +} + +
+

@(isNew ? "Skapa ny mÄltid" : Model.Name)

+ +
+ @if (!isNew) + { + + } + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ +
+ + diff --git a/Aberwyn/Views/Meal/View.cshtml b/Aberwyn/Views/Meal/View.cshtml new file mode 100644 index 0000000..a2230f5 --- /dev/null +++ b/Aberwyn/Views/Meal/View.cshtml @@ -0,0 +1,90 @@ +ï»ż@model Aberwyn.Models.Meal +@{ + ViewData["Title"] = Model.Name; +} + +
+

@Model.Name

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

@Model.Description

+ } + +
+ + Redigera +
+ + +
+ + + + diff --git a/Aberwyn/Views/Shared/_Layout.cshtml b/Aberwyn/Views/Shared/_Layout.cshtml index b9f27a0..f9e78a4 100644 --- a/Aberwyn/Views/Shared/_Layout.cshtml +++ b/Aberwyn/Views/Shared/_Layout.cshtml @@ -37,17 +37,30 @@ RealEstate + + + + - +
@RenderBody() + @RenderSection("Scripts", required: false)
@@ -57,5 +70,6 @@ + diff --git a/Aberwyn/appsettings.json b/Aberwyn/appsettings.json index c97db5f..f93bc0e 100644 --- a/Aberwyn/appsettings.json +++ b/Aberwyn/appsettings.json @@ -8,6 +8,6 @@ "AllowedHosts": "*", "ConnectionStrings": { "DefaultConnection": "Server=192.168.1.108;Database=Nevyn;Uid=root;Pwd=3edc4RFV;", - "ProductionConnection": "Server=172.18.0.2;Database=Nevyn;Uid=root;Pwd=3edc4RFV;" + "ProductionConnection": "Server=192.168.1.108;Database=Nevyn;Uid=root;Pwd=3edc4RFV;" } } diff --git a/Aberwyn/wwwroot/css/menu-style.css b/Aberwyn/wwwroot/css/menu-style.css new file mode 100644 index 0000000..f6ecbb3 --- /dev/null +++ b/Aberwyn/wwwroot/css/menu-style.css @@ -0,0 +1,15 @@ + +.menu-table { + width: 100%; + border-collapse: collapse; + margin-top: 1em; +} +.menu-table th, .menu-table td { + border: 1px solid #444; + padding: 0.5em; +} +.week-nav { + margin-bottom: 1em; + display: flex; + gap: 1em; +} diff --git a/Aberwyn/wwwroot/css/site.css b/Aberwyn/wwwroot/css/site.css index de35bab..eb6325b 100644 --- a/Aberwyn/wwwroot/css/site.css +++ b/Aberwyn/wwwroot/css/site.css @@ -224,3 +224,4 @@ body { .date-picker-dropdown select:hover { background-color: #555; } + diff --git a/Aberwyn/wwwroot/js/meal-menu.js b/Aberwyn/wwwroot/js/meal-menu.js new file mode 100644 index 0000000..1b686ec --- /dev/null +++ b/Aberwyn/wwwroot/js/meal-menu.js @@ -0,0 +1,10 @@ + +document.addEventListener("DOMContentLoaded", function () { + document.querySelectorAll(".meal-cell").forEach(cell => { + cell.addEventListener("click", function () { + const name = this.getAttribute("data-name"); + const cook = this.getAttribute("data-cook"); + alert(`MĂ„ltid: ${name}\nLagas av: ${cook}`); + }); + }); +}); diff --git a/Aberwyn/wwwroot/js/menu.js b/Aberwyn/wwwroot/js/menu.js index 93f48e5..f355bb2 100644 --- a/Aberwyn/wwwroot/js/menu.js +++ b/Aberwyn/wwwroot/js/menu.js @@ -1,4 +1,4 @@ -angular.module('mealMenuApp', []) +ï»żangular.module('mealMenuApp', []) .controller('MealMenuController', function ($scope, $http) { $scope.isEditing = false; $scope.toggleEditMode = function () { @@ -15,7 +15,7 @@ angular.module('mealMenuApp', []) const today = new Date(); $scope.selectedWeek = getWeek(today); $scope.selectedYear = today.getFullYear(); - $scope.daysOfWeek = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]; + $scope.daysOfWeek = ["MĂ„ndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag", "Söndag"]; $scope.loadMeals = function () { $http.get('/api/mealMenuApi/getMeals') @@ -29,6 +29,8 @@ angular.module('mealMenuApp', []) $http.get('/api/mealMenuApi/menu', { params: { weekNumber: $scope.selectedWeek, year: $scope.selectedYear } }).then(response => { + console.log("Veckomenydata:", response.data); // ✅ logga ut + $scope.menu = {}; response.data.forEach(item => { const dayOfWeek = $scope.daysOfWeek[item.dayOfWeek - 1]; diff --git a/Aberwyn/wwwroot/uploads/fc8aff8c-4bef-45a8-9e40-7b78f76f04e8.png b/Aberwyn/wwwroot/uploads/fc8aff8c-4bef-45a8-9e40-7b78f76f04e8.png new file mode 100644 index 0000000..69bf922 Binary files /dev/null and b/Aberwyn/wwwroot/uploads/fc8aff8c-4bef-45a8-9e40-7b78f76f04e8.png differ