added info to meal

This commit is contained in:
2025-10-25 16:17:50 +02:00
parent 38db9c242b
commit b8046c87b9
4 changed files with 465 additions and 57 deletions

View File

@@ -61,6 +61,13 @@ func MealsHandler(w http.ResponseWriter, r *http.Request) {
{{end}}
</div>
<div>
<button
hx-get="/meals/{{.ID}}/edit"
hx-target="#edit-modal"
hx-swap="innerHTML"
class="edit-btn">
Edit
</button>
<button
hx-get="/meals/{{.ID}}/ingredients"
hx-target="#meal-{{.ID}}-ingredients"
@@ -82,6 +89,9 @@ func MealsHandler(w http.ResponseWriter, r *http.Request) {
</div>
{{end}}
</div>
<!-- Edit Modal -->
<div id="edit-modal"></div>
</div>
`
@@ -149,6 +159,13 @@ func AddMealHandler(w http.ResponseWriter, r *http.Request) {
{{end}}
</div>
<div>
<button
hx-get="/meals/{{.ID}}/edit"
hx-target="#edit-modal"
hx-swap="innerHTML"
class="edit-btn">
Edit
</button>
<button
hx-get="/meals/{{.ID}}/ingredients"
hx-target="#meal-{{.ID}}-ingredients"
@@ -386,3 +403,214 @@ func DeleteMealIngredientHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}
// GetEditMealHandler shows the edit modal for a meal
func GetEditMealHandler(w http.ResponseWriter, r *http.Request) {
userID := auth.GetUserID(r)
parts := strings.Split(r.URL.Path, "/")
if len(parts) < 3 {
http.Error(w, "Invalid URL", http.StatusBadRequest)
return
}
mealID, err := strconv.Atoi(parts[2])
if err != nil {
http.Error(w, "Invalid meal ID", http.StatusBadRequest)
return
}
// Get meal with security check
meal, err := database.GetMealByID(userID, mealID)
if err != nil {
http.Error(w, "Meal not found", http.StatusNotFound)
return
}
tmpl := `
<div class="modal-overlay" id="modal-overlay">
<div class="modal-content">
<h3>Edit Meal</h3>
<form hx-post="/meals/{{.ID}}/update"
hx-target="#meal-{{.ID}}"
hx-swap="outerHTML"
class="edit-form">
<div class="form-group">
<label>Name:</label>
<input type="text" name="name" value="{{.Name}}" required />
</div>
<div class="form-group">
<label>Description:</label>
<input type="text" name="description" value="{{.Description}}" />
</div>
<div class="form-group">
<label>Type:</label>
<select name="meal_type" required>
<option value="breakfast" {{if eq .MealType "breakfast"}}selected{{end}}>Breakfast</option>
<option value="lunch" {{if eq .MealType "lunch"}}selected{{end}}>Lunch</option>
<option value="snack" {{if eq .MealType "snack"}}selected{{end}}>Snack</option>
</select>
</div>
<div class="form-group">
<label>Prep Time (minutes):</label>
<input type="number" name="prep_time" value="{{.PrepTime}}" min="0" />
</div>
<div class="form-group">
<label>Image URL:</label>
<input type="url" name="image_url" value="{{.ImageURL}}" />
</div>
<div class="form-group">
<label>Instructions:</label>
<textarea name="instructions" rows="5">{{.Instructions}}</textarea>
</div>
<div class="modal-buttons">
<button type="submit" class="btn-primary">Save</button>
<button type="button" onclick="closeModal()" class="btn-secondary">Cancel</button>
</div>
</form>
</div>
</div>
<script>
function closeModal() {
document.getElementById('edit-modal').innerHTML = '';
}
document.getElementById('modal-overlay').addEventListener('click', function(e) {
if (e.target.id === 'modal-overlay') {
closeModal();
}
});
</script>
`
t := template.Must(template.New("editMeal").Parse(tmpl))
t.Execute(w, meal)
}
// UpdateMealHandler updates a meal
func UpdateMealHandler(w http.ResponseWriter, r *http.Request) {
userID := auth.GetUserID(r)
parts := strings.Split(r.URL.Path, "/")
if len(parts) < 3 {
http.Error(w, "Invalid URL", http.StatusBadRequest)
return
}
mealID, err := strconv.Atoi(parts[2])
if err != nil {
http.Error(w, "Invalid meal ID", http.StatusBadRequest)
return
}
// Verify ownership
_, err = database.GetMealByID(userID, mealID)
if err != nil {
http.Error(w, "Meal not found or access denied", http.StatusForbidden)
return
}
if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
name := strings.TrimSpace(r.FormValue("name"))
description := strings.TrimSpace(r.FormValue("description"))
mealType := r.FormValue("meal_type")
instructions := strings.TrimSpace(r.FormValue("instructions"))
imageURL := strings.TrimSpace(r.FormValue("image_url"))
prepTime := 0
if prepTimeStr := r.FormValue("prep_time"); prepTimeStr != "" {
prepTime, _ = strconv.Atoi(prepTimeStr)
}
if name == "" || mealType == "" {
http.Error(w, "Name and meal type are required", http.StatusBadRequest)
return
}
// Validate meal type
if mealType != "breakfast" && mealType != "lunch" && mealType != "snack" {
http.Error(w, "Invalid meal type", http.StatusBadRequest)
return
}
// Update meal
_, err = database.DB.Exec(
"UPDATE meals SET name = ?, description = ?, meal_type = ?, instructions = ?, prep_time = ?, image_url = ? WHERE id = ? AND user_id = ?",
name, description, mealType, instructions, prepTime, imageURL, mealID, userID,
)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Return updated meal card
tmpl := `
<div class="meal-item" id="meal-{{.ID}}">
<div class="meal-header">
{{if .ImageURL}}
<img src="{{.ImageURL}}" alt="{{.Name}}" class="meal-image" />
{{end}}
<div class="meal-info-section">
<div>
<span class="item-name">{{.Name}}</span>
<span class="meal-type-tag tag-{{.MealType}}">{{.MealType}}</span>
{{if gt .PrepTime 0}}
<span class="prep-time">⏱️ {{.PrepTime}} min</span>
{{end}}
</div>
<span class="item-description">{{.Description}}</span>
{{if .Instructions}}
<details class="instructions-preview">
<summary>Instructions</summary>
<p class="instructions-text">{{.Instructions}}</p>
</details>
{{end}}
</div>
<div>
<button
hx-get="/meals/{{.ID}}/edit"
hx-target="#edit-modal"
hx-swap="innerHTML"
class="edit-btn">
Edit
</button>
<button
hx-get="/meals/{{.ID}}/ingredients"
hx-target="#meal-{{.ID}}-ingredients"
hx-swap="innerHTML"
class="view-btn">
View Ingredients
</button>
<button
hx-delete="/meals/{{.ID}}"
hx-target="#meal-{{.ID}}"
hx-swap="outerHTML"
hx-confirm="Are you sure you want to delete this meal?"
class="delete-btn">
Delete
</button>
</div>
</div>
<div id="meal-{{.ID}}-ingredients" class="meal-ingredients"></div>
</div>
<script>
document.getElementById('edit-modal').innerHTML = '';
</script>
`
data := struct {
ID int
Name string
Description string
MealType string
Instructions string
PrepTime int
ImageURL string
}{mealID, name, description, mealType, instructions, prepTime, imageURL}
t := template.Must(template.New("updatedMeal").Parse(tmpl))
t.Execute(w, data)
}