Replaced direct access to DB model properties with a dedicated ViewModel.
Added per-recipe HTMX form including AntiForgeryToken and dynamic star icon based on IsFavorite status.
This commit is contained in:
@@ -1,58 +1,75 @@
|
|||||||
@model IEnumerable<Francesco.Recipes.World.Models.BackendModels.Recipe.Recipe>
|
@model IEnumerable<Francesco.Recipes.World.Models.SearchViewModel>
|
||||||
|
|
||||||
@{
|
@{
|
||||||
if (!Model.Any())
|
if (!Model.Any())
|
||||||
{
|
{
|
||||||
<p class="text-muted">Keine Ergebnisse gefunden.</p>
|
<p class="text-muted">Keine Ergebnisse gefunden.</p>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@foreach (var recipe in Model)
|
@foreach (var recipe in Model)
|
||||||
{
|
{
|
||||||
<div class="col-md-4 mb-3">
|
<div class="col-md-4 mb-3">
|
||||||
<div class="card h-100 shadow-sm">
|
<div class="card h-100 shadow-sm">
|
||||||
<div class="recipe-image">
|
<div class="recipe-image">
|
||||||
@{
|
@if (recipe.ImageData != null && recipe.MimeType != null)
|
||||||
var mediaFile = recipe.MediaFiles.FirstOrDefault();
|
{
|
||||||
|
<img src="data:@recipe.MimeType;base64,@Convert.ToBase64String(recipe.ImageData)"
|
||||||
if (mediaFile?.Data != null)
|
alt="@recipe.Name"
|
||||||
{
|
class="card-img-top" />
|
||||||
<img src="data:@mediaFile.MimeType;base64,@Convert.ToBase64String(mediaFile.Data)"
|
}
|
||||||
alt="@recipe.Name"
|
else
|
||||||
class="card-img-top" />
|
{
|
||||||
}
|
<img src="~/images/placeholder.png"
|
||||||
else
|
alt="Platzhalter"
|
||||||
{
|
class="card-img-top" />
|
||||||
<img src="~/images/placeholder.png"
|
}
|
||||||
alt="Platzhalter"
|
|
||||||
class="card-img-top" />
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-body d-flex flex-column justify-content-between">
|
|
||||||
<div>
|
|
||||||
<h5 class="card-title">@recipe.Name</h5>
|
|
||||||
<p class="card-text text-muted mb-2">
|
|
||||||
<i class="bi bi-clock"></i>
|
|
||||||
@recipe.PreparationTime.Hours h @recipe.PreparationTime.Minutes min
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="card-body d-flex flex-column justify-content-between">
|
||||||
<button class="btn btn-outline-secondary"
|
<div>
|
||||||
hx-post="/Recipe/ToggleFavorite"
|
<h5 class="card-title">@recipe.Name</h5>
|
||||||
hx-vals='{"id": "@recipe.Id"}'
|
<p class="card-text text-muted mb-2">
|
||||||
hx-swap="outerHTML">
|
<i class="bi bi-clock"></i>
|
||||||
<i class="bi @((recipe.IsFavorite) ? "bi-star-fill" : "bi-star")"></i>
|
@recipe.TotalTime.Hours h @recipe.TotalTime.Minutes min
|
||||||
</button>
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between align-items-center mt-3">
|
||||||
|
<div class="favorite-button-container">
|
||||||
|
<form hx-post="@Url.Action(recipe.IsFavorite ? "RemoveFavorite" : "AddFavorite", "Recipe")"
|
||||||
|
hx-target="this"
|
||||||
|
hx-swap="outerHTML">
|
||||||
|
@Html.AntiForgeryToken()
|
||||||
|
<input type="hidden" name="recipeId" value="@recipe.Id" />
|
||||||
|
<button type="submit" class="btn btn-link p-0" style="width: 40px; height: 40px;">
|
||||||
|
@if (recipe.IsFavorite)
|
||||||
|
{
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFD700">
|
||||||
|
<path d="M12 17.27L18.18 21 16.54 13.97
|
||||||
|
22 9.24l-7.19-.62L12 2 9.19 8.62
|
||||||
|
2 9.24l5.46 4.73L5.82 21z" />
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M12 17.27L18.18 21 16.54 13.97
|
||||||
|
22 9.24l-7.19-.62L12 2 9.19 8.62
|
||||||
|
2 9.24l5.46 4.73L5.82 21z" />
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a href="/Recipe/Details/@recipe.Id" class="btn btn-primary btn-sm">Details</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
}
|
</div>
|
||||||
</div>
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user