package handlers import ( "html/template" "mealprep/auth" "mealprep/database" "net/http" "strconv" "strings" "time" ) // WeekPlanHandler handles the week plan page func WeekPlanHandler(w http.ResponseWriter, r *http.Request) { userID := auth.GetUserID(r) weekPlan, err := database.GetWeekPlan(userID) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } meals, err := database.GetAllMeals(userID) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Group by date planByDate := make(map[string][]interface{}) for _, entry := range weekPlan { dateStr := entry.Date.Format("2006-01-02") planByDate[dateStr] = append(planByDate[dateStr], entry) } // Get next 7 days starting from upcoming Monday (or current Monday if today is Monday) today := time.Now() // Calculate the upcoming Monday // If today is Monday, use today. Otherwise, find next Monday. weekday := int(today.Weekday()) daysUntilMonday := (8 - weekday) % 7 if weekday == 1 { // Today is Monday daysUntilMonday = 0 } startDate := today.AddDate(0, 0, daysUntilMonday) var dates []string for i := 0; i < 7; i++ { date := startDate.AddDate(0, 0, i) dates = append(dates, date.Format("2006-01-02")) } tmpl := `

Week Plan

Planning week: {{.WeekStart}} - {{.WeekEnd}}

{{range $index, $date := .Dates}}

{{formatDate $date}}

🌅 Breakfast

{{$entries := index $.PlanByDate $date}} {{range $entries}} {{if eq .MealType "breakfast"}}
{{.MealName}}
{{end}} {{end}}

🍽️ Lunch

{{$entries := index $.PlanByDate $date}} {{range $entries}} {{if eq .MealType "lunch"}}
{{.MealName}}
{{end}} {{end}}

🍪 Snack

{{$entries := index $.PlanByDate $date}} {{range $entries}} {{if eq .MealType "snack"}}
{{.MealName}}
{{end}} {{end}}
{{end}}
` funcMap := template.FuncMap{ "formatDate": func(dateStr string) string { date, _ := time.Parse("2006-01-02", dateStr) // Show full date with day name return date.Format("Monday, Jan 2") }, "index": func(m map[string][]interface{}, key string) []interface{} { return m[key] }, } // Format week range for display weekStart := startDate.Format("Mon, Jan 2") weekEnd := startDate.AddDate(0, 0, 6).Format("Mon, Jan 2") // Separate meals by type var breakfastMeals, lunchMeals, snackMeals []interface{} for _, meal := range meals { switch meal.MealType { case "breakfast": breakfastMeals = append(breakfastMeals, meal) case "lunch": lunchMeals = append(lunchMeals, meal) case "snack": snackMeals = append(snackMeals, meal) } } data := struct { Dates []string PlanByDate map[string][]interface{} BreakfastMeals interface{} LunchMeals interface{} SnackMeals interface{} WeekStart string WeekEnd string }{ Dates: dates, PlanByDate: planByDate, BreakfastMeals: breakfastMeals, LunchMeals: lunchMeals, SnackMeals: snackMeals, WeekStart: weekStart, WeekEnd: weekEnd, } t := template.Must(template.New("weekplan").Funcs(funcMap).Parse(tmpl)) t.Execute(w, data) } // AddWeekPlanEntryHandler adds a meal to a specific day func AddWeekPlanEntryHandler(w http.ResponseWriter, r *http.Request) { userID := auth.GetUserID(r) if err := r.ParseForm(); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } dateStr := r.FormValue("date") mealType := r.FormValue("meal_type") mealID, err := strconv.Atoi(r.FormValue("meal_id")) if err != nil { http.Error(w, "Invalid meal ID", http.StatusBadRequest) return } // Validate meal type if mealType != "breakfast" && mealType != "lunch" && mealType != "snack" { http.Error(w, "Invalid meal type", http.StatusBadRequest) return } date, err := time.Parse("2006-01-02", dateStr) if err != nil { http.Error(w, "Invalid date", http.StatusBadRequest) return } if err := database.AddWeekPlanEntry(userID, date, mealID); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Get the meal details meal, err := database.GetMealByID(userID, mealID) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Verify meal type matches if meal.MealType != mealType { http.Error(w, "Meal type does not match", http.StatusBadRequest) return } // Get the ID of the entry we just added weekPlan, err := database.GetWeekPlan(userID) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } var entryID int for _, entry := range weekPlan { if entry.Date.Format("2006-01-02") == dateStr && entry.MealID == mealID { entryID = entry.ID } } tmpl := `
{{.MealName}}
` data := struct { ID int MealName string }{entryID, meal.Name} t := template.Must(template.New("planEntry").Parse(tmpl)) t.Execute(w, data) } // DeleteWeekPlanEntryHandler removes a meal from the week plan func DeleteWeekPlanEntryHandler(w http.ResponseWriter, r *http.Request) { userID := auth.GetUserID(r) idStr := strings.TrimPrefix(r.URL.Path, "/week-plan/") id, err := strconv.Atoi(idStr) if err != nil { http.Error(w, "Invalid ID", http.StatusBadRequest) return } if err := database.DeleteWeekPlanEntry(userID, id); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) }