This commit is contained in:
@@ -18,7 +18,11 @@ namespace Aberwyn.Controllers
|
||||
_configuration = configuration;
|
||||
_env = env;
|
||||
}
|
||||
|
||||
[HttpGet("/meal")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View("Index");
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult View(int? id, bool edit = false)
|
||||
{
|
||||
|
||||
@@ -30,11 +30,12 @@ namespace Aberwyn.Controllers
|
||||
[HttpGet("getMeals")]
|
||||
public IActionResult GetMeals()
|
||||
{
|
||||
var meals = _menuService.GetMealsDetailed(); // Hämtar med ImageData
|
||||
var mealDtos = meals.Select(MealDto.FromMeal).ToList();
|
||||
var meals = _menuService.GetMealsSlim(true);
|
||||
var mealDtos = meals.Select(m => MealDto.FromMeal(m, includeThumbnail: true)).ToList(); // 👈 fix
|
||||
return Ok(mealDtos);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("getWeeklyMenu")]
|
||||
public IActionResult GetWeeklyMenu(int weekNumber, int year)
|
||||
{
|
||||
|
||||
@@ -165,9 +165,35 @@ public class MenuService
|
||||
_context.SaveChanges();
|
||||
return updatedCount;
|
||||
}
|
||||
|
||||
public List<WeeklyMenu> GetAllWeeklyMenus()
|
||||
public List<Meal> GetMealsSlim(bool includeThumbnail = false)
|
||||
{
|
||||
if (includeThumbnail)
|
||||
{
|
||||
return _context.Meals
|
||||
.Select(m => new Meal
|
||||
{
|
||||
Id = m.Id,
|
||||
Name = m.Name,
|
||||
Description = m.Description,
|
||||
ThumbnailData = m.ThumbnailData
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
return _context.Meals
|
||||
.Select(m => new Meal
|
||||
{
|
||||
Id = m.Id,
|
||||
Name = m.Name,
|
||||
Description = m.Description
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public List<WeeklyMenu> GetAllWeeklyMenus()
|
||||
{
|
||||
var menus = _context.WeeklyMenus.ToList();
|
||||
|
||||
var allMeals = _context.Meals.ToDictionary(m => m.Id, m => m.Name);
|
||||
|
||||
@@ -104,20 +104,39 @@ public class WeeklyMenu
|
||||
public string? ImageData { get; set; } // base64
|
||||
public string? ImageMimeType { get; set; }
|
||||
|
||||
public static MealDto FromMeal(Meal meal)
|
||||
public static MealListDto FromMeal(Meal meal, bool includeThumbnail = false)
|
||||
{
|
||||
return new MealDto
|
||||
return new MealListDto
|
||||
{
|
||||
Id = meal.Id,
|
||||
Name = meal.Name,
|
||||
Category = meal.Category,
|
||||
IsAvailable = meal.IsAvailable,
|
||||
ImageUrl = meal.ImageUrl,
|
||||
ImageMimeType = meal.ImageMimeType,
|
||||
ImageData = meal.ImageData != null ? Convert.ToBase64String(meal.ImageData) : null
|
||||
Description = meal.Description,
|
||||
ThumbnailData = includeThumbnail && meal.ThumbnailData != null
|
||||
? Convert.ToBase64String(meal.ThumbnailData)
|
||||
: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public class MealListDto
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; } = "";
|
||||
public string? Description { get; set; }
|
||||
public string? ThumbnailData { get; set; }
|
||||
|
||||
public static MealListDto FromMeal(Meal meal, bool includeThumbnail = false)
|
||||
{
|
||||
return new MealListDto
|
||||
{
|
||||
Id = meal.Id,
|
||||
Name = meal.Name,
|
||||
Description = meal.Description,
|
||||
ThumbnailData = includeThumbnail && meal.ThumbnailData != null
|
||||
? Convert.ToBase64String(meal.ThumbnailData)
|
||||
: null
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
48
Aberwyn/Views/Meal/Index.cshtml
Normal file
48
Aberwyn/Views/Meal/Index.cshtml
Normal file
@@ -0,0 +1,48 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="sv" ng-app="mealGalleryApp">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Måltider</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
|
||||
<link rel="stylesheet" href="/css/meal-gallery.css">
|
||||
</head>
|
||||
<body ng-controller="MealGalleryController">
|
||||
<div class="meal-gallery-container" ng-controller="MealGalleryController">
|
||||
<div class="meal-gallery-header">
|
||||
<h1>Recept</h1>
|
||||
<div class="search-container">
|
||||
<input type="text" ng-model="search" placeholder="Sök recept...">
|
||||
<i class="fa-solid fa-magnifying-glass"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="meal-gallery-grid">
|
||||
<div class="meal-card" ng-repeat="meal in meals | filter:search">
|
||||
<img ng-src="{{ meal.ThumbnailData ? 'data:image/webp;base64,' + meal.ThumbnailData : '/images/fallback.jpg' }}"
|
||||
alt="{{ meal.Name }}">
|
||||
<div class="meal-card-content">
|
||||
<h3>{{ meal.Name }}</h3>
|
||||
<p ng-if="meal.Description">{{ meal.Description }}</p>
|
||||
<a class="btn-readmore" ng-href="/meal/view/{{ meal.Id }}">Läs mer</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
<script>
|
||||
angular.module("mealGalleryApp", []).controller("MealGalleryController", function ($scope, $http) {
|
||||
$scope.meals = [];
|
||||
$scope.search = "";
|
||||
|
||||
$http.get("/api/mealMenuApi/getMeals").then(res => {
|
||||
$scope.meals = res.data;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
107
Aberwyn/wwwroot/css/meal-gallery.css
Normal file
107
Aberwyn/wwwroot/css/meal-gallery.css
Normal file
@@ -0,0 +1,107 @@
|
||||
body {
|
||||
background-color: #f7f7f7;
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
color: #222;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.meal-gallery-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 1rem;
|
||||
}
|
||||
|
||||
.meal-gallery-header {
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.meal-gallery-header h1 {
|
||||
font-size: 2.4rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
margin-top: 1rem;
|
||||
position: relative;
|
||||
max-width: 400px;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.search-container input {
|
||||
width: 100%;
|
||||
padding: 10px 38px 10px 12px;
|
||||
border-radius: 25px;
|
||||
border: 1px solid #ccc;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.search-container i {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.meal-gallery-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.meal-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.meal-card:hover {
|
||||
transform: scale(1.015);
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.meal-card img {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.meal-card-content {
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.meal-card-content h3 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 1.2rem;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.meal-card-content p {
|
||||
flex-grow: 1;
|
||||
font-size: 0.95rem;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.btn-readmore {
|
||||
align-self: flex-start;
|
||||
background: #007d36;
|
||||
color: white;
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
text-decoration: none;
|
||||
font-size: 0.95rem;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.btn-readmore:hover {
|
||||
background: #005c27;
|
||||
}
|
||||
|
||||
BIN
Aberwyn/wwwroot/images/fallback.jpg
Normal file
BIN
Aberwyn/wwwroot/images/fallback.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
Reference in New Issue
Block a user