From bbf12fc441ca36c423e865107d34df178e3d26de Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Mon, 26 Jan 2026 17:00:30 -1000 Subject: Fix multiple UI issues and shopping completion bug - #54: Fix shopping item completion - now works for all sources (trello, plantoeat, user) with state stored in local DB - #48: Hide 12:00am times in timeline (all-day items) - #49: Remove "Task" type label from timeline items for cleaner UI - #51: Combine multiple PlanToEat meals for same date+mealType - #52: Change Conditions tab to standard link to standalone page Co-Authored-By: Claude Opus 4.5 --- internal/handlers/timeline_logic.go | 49 ++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 9 deletions(-) (limited to 'internal/handlers/timeline_logic.go') diff --git a/internal/handlers/timeline_logic.go b/internal/handlers/timeline_logic.go index bead98f..553593d 100644 --- a/internal/handlers/timeline_logic.go +++ b/internal/handlers/timeline_logic.go @@ -3,6 +3,7 @@ package handlers import ( "context" "sort" + "strings" "time" "task-dashboard/internal/api" @@ -40,15 +41,38 @@ func BuildTimeline(ctx context.Context, s *store.Store, calendarClient api.Googl items = append(items, item) } - // 2. Fetch Meals + // 2. Fetch Meals - combine multiple items for same date+mealType meals, err := s.GetMealsByDateRange(start, end) if err != nil { return nil, err } + + // Group meals by date+mealType key + type mealKey struct { + date string + mealType string + } + mealGroups := make(map[mealKey][]models.Meal) for _, meal := range meals { - mealTime := meal.Date - // Apply Meal Defaults - switch meal.MealType { + key := mealKey{ + date: meal.Date.Format("2006-01-02"), + mealType: meal.MealType, + } + mealGroups[key] = append(mealGroups[key], meal) + } + + // Create combined timeline items for each group + for _, group := range mealGroups { + if len(group) == 0 { + continue + } + + // Use first meal as base + firstMeal := group[0] + mealTime := firstMeal.Date + + // Apply Meal time defaults + switch firstMeal.MealType { case "breakfast": mealTime = time.Date(mealTime.Year(), mealTime.Month(), mealTime.Day(), config.BreakfastHour, 0, 0, 0, mealTime.Location()) case "lunch": @@ -59,14 +83,21 @@ func BuildTimeline(ctx context.Context, s *store.Store, calendarClient api.Googl mealTime = time.Date(mealTime.Year(), mealTime.Month(), mealTime.Day(), config.LunchHour, 0, 0, 0, mealTime.Location()) } + // Combine recipe names with " + " + var names []string + for _, m := range group { + names = append(names, m.RecipeName) + } + combinedTitle := strings.Join(names, " + ") + item := models.TimelineItem{ - ID: meal.ID, + ID: firstMeal.ID, Type: models.TimelineItemTypeMeal, - Title: meal.RecipeName, + Title: combinedTitle, Time: mealTime, - URL: meal.RecipeURL, - OriginalItem: meal, - IsCompleted: false, // Meals don't have completion status + URL: firstMeal.RecipeURL, // Use first meal's URL + OriginalItem: group, // Store all meals + IsCompleted: false, Source: "plantoeat", } item.ComputeDaySection(now) -- cgit v1.2.3