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
+5 -1
View File
@@ -214,6 +214,7 @@ struct WeekCalendarView: View {
dayOfWeek: day,
mealType: mealType.rawValue,
dishId: preferred.dishId,
secondaryDishId: preferred.secondaryDishId,
isRuleOverridden: preferred.isRuleOverridden,
isEatingOut: preferred.isEatingOut
)
@@ -264,8 +265,9 @@ struct WeekCalendarView: View {
if let slot = slot, let dishId = slot.dishId,
let dishData = dishData(for: dishId) {
let dishTags = tags.filter { dishData.tagIds.contains($0.id) }
let secondaryName = slot.secondaryDishId.flatMap { self.dishData(for: $0)?.name }
FilledSlotView(
dishName: dishData.name,
dishName: secondaryName.map { "\(dishData.name) + \($0)" } ?? dishData.name,
dishDescription: dishData.descriptionText,
tags: dishTags.map { (name: $0.localizedName(language: settings.languageEnum.resolved()), color: $0.color) },
mealType: mealType,
@@ -321,6 +323,7 @@ struct WeekCalendarView: View {
let dayOfWeek: Int
let mealType: String
let dishId: UUID?
let secondaryDishId: UUID?
let isRuleOverridden: Bool
let isEatingOut: Bool
}
@@ -370,6 +373,7 @@ struct WeekCalendarView: View {
dayOfWeek: preferred.dayOfWeek,
mealType: preferred.mealType,
dishId: preferred.dishId,
secondaryDishId: preferred.secondaryDishId,
isRuleOverridden: preferred.isRuleOverridden,
isEatingOut: preferred.isEatingOut
)