platos: segundo plato por comida (ensalada + salmon)

- MealSlot.secondaryDishId (opcional, aditivo CloudKit); se limpia al
  sustituir/quitar/vaciar/marcar comer fuera y viaja en swaps, copia de
  semana anterior, undo y snapshot KV de iCloud (retrocompatible)
- Picker de hueco lleno: toggle "anadir como segundo plato" + boton para
  quitarlo; HomeViewModel.assignSecondaryDish/removeSecondaryDish
- Se muestra "Plato + Segundo" en calendario, widget y export; la lista
  de la compra incluye los ingredientes del segundo; stats lo cuentan
- Evento analytics secondary_dish_added; strings en 6 idiomas

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013H6bXqGX1ygwib1Dm3n3UG
This commit is contained in:
alexandrev-tibco
2026-09-01 11:37:23 +02:00
parent 7193234024
commit a0f9fa63d3
15 changed files with 128 additions and 13 deletions
@@ -34,10 +34,12 @@ struct ShoppingListView: View {
($0.dayOfWeek, $0.mealType) < ($1.dayOfWeek, $1.mealType)
}
for slot in sortedSlots {
guard let dishId = slot.dishId, !seen.contains(dishId),
let dish = allDishes.first(where: { $0.id == dishId }) else { continue }
seen.insert(dishId)
result.append(dish)
for dishId in [slot.dishId, slot.secondaryDishId].compactMap({ $0 }) {
guard !seen.contains(dishId),
let dish = allDishes.first(where: { $0.id == dishId }) else { continue }
seen.insert(dishId)
result.append(dish)
}
}
return result
}