6fe16d8e29
- MealSlot.isSkipped: opcion "No planificar esta comida" en el picker de hueco vacio — cuenta como resuelto (semana completa, notificaciones, stats) y el autocompletado lo respeta; vista gris con guion, tap para desmarcar; viaja en undo, snapshot KV (junto con isEatingOut, que faltaba en el payload) y exports (— en imagen, omitido en texto) - ShoppingItem.isDismissed: "Ya lo tengo" por ingrediente (swipe izquierdo) y "Ya esta hecho" por plato entero (boton en la cabecera de su seccion); van a la seccion "Ya en casa" con restauracion de un tap, y quedan fuera del export de texto. No se borran porque reconcile los recrearia - Esquema CloudKit Development: CD_isSkipped, CD_isDismissed y el record type CD_ShoppingItem entero, que no existia — la lista de la compra no estaba sincronizando entre dispositivos (mismo bug que photoData) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013H6bXqGX1ygwib1Dm3n3UG
103 lines
3.2 KiB
Swift
103 lines
3.2 KiB
Swift
import SwiftUI
|
|
|
|
struct EmptySlotView: View {
|
|
let mealType: MealType
|
|
let isDropTarget: Bool
|
|
let isValidDrop: Bool?
|
|
|
|
init(mealType: MealType, isDropTarget: Bool = false, isValidDrop: Bool? = nil) {
|
|
self.mealType = mealType
|
|
self.isDropTarget = isDropTarget
|
|
self.isValidDrop = isValidDrop
|
|
}
|
|
|
|
var body: some View {
|
|
VStack(spacing: 6) {
|
|
Image(systemName: mealType.icon)
|
|
.font(.system(size: 20))
|
|
.foregroundColor(Color(hex: "#C4C4C4"))
|
|
|
|
Text(LocalizedStringKey(mealType.rawValue))
|
|
.font(.mealMoodCaption)
|
|
.foregroundColor(.mealMoodTextSecondary)
|
|
}
|
|
.frame(maxWidth: .infinity, minHeight: 80)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 12)
|
|
.fill(Color(hex: "#F9F9F9"))
|
|
.overlay(
|
|
RoundedRectangle(cornerRadius: 12)
|
|
.strokeBorder(
|
|
style: StrokeStyle(lineWidth: 2, dash: [5])
|
|
)
|
|
.foregroundColor(borderColor)
|
|
)
|
|
)
|
|
.animation(.easeInOut(duration: 0.2), value: isDropTarget)
|
|
}
|
|
|
|
private var borderColor: Color {
|
|
guard isDropTarget, let valid = isValidDrop else {
|
|
return Color(hex: "#E0E0E0")
|
|
}
|
|
return valid ? .mealMoodSuccess : .mealMoodError
|
|
}
|
|
}
|
|
|
|
struct EatingOutSlotView: View {
|
|
let mealType: MealType
|
|
|
|
var body: some View {
|
|
VStack(spacing: 6) {
|
|
Image(systemName: "fork.knife.circle")
|
|
.font(.system(size: 20))
|
|
.foregroundColor(Color(hex: "#A0C4B8"))
|
|
|
|
Text("slot_eating_out")
|
|
.font(.mealMoodCaption)
|
|
.foregroundColor(Color(hex: "#6B9E90"))
|
|
}
|
|
.frame(maxWidth: .infinity, minHeight: 80)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 12)
|
|
.fill(Color(hex: "#EEF8F5"))
|
|
.overlay(
|
|
RoundedRectangle(cornerRadius: 12)
|
|
.strokeBorder(
|
|
style: StrokeStyle(lineWidth: 2, dash: [5])
|
|
)
|
|
.foregroundColor(Color(hex: "#A0C4B8"))
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
/// "Not planning this meal" — intentionally blank, resolved slot.
|
|
struct SkippedSlotView: View {
|
|
let mealType: MealType
|
|
|
|
var body: some View {
|
|
VStack(spacing: 6) {
|
|
Image(systemName: "minus.circle")
|
|
.font(.system(size: 20))
|
|
.foregroundColor(Color(hex: "#B9B4AE"))
|
|
|
|
Text("slot_skipped")
|
|
.font(.mealMoodCaption)
|
|
.foregroundColor(Color(hex: "#8E8B86"))
|
|
}
|
|
.frame(maxWidth: .infinity, minHeight: 80)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 12)
|
|
.fill(Color(hex: "#F5F3F0"))
|
|
.overlay(
|
|
RoundedRectangle(cornerRadius: 12)
|
|
.strokeBorder(
|
|
style: StrokeStyle(lineWidth: 2, dash: [5])
|
|
)
|
|
.foregroundColor(Color(hex: "#CFCAC4"))
|
|
)
|
|
)
|
|
}
|
|
}
|