Files
FamilyMealPlanner/MealMood/Components/FilledSlotView.swift
T
alexandrev-tibco 29cba08678 2.0: beta feedback — edit dish from shopping list + dish photos in planner
- Shopping list: dishes under "No ingredients yet" now open the dish editor on
  tap (pencil affordance); list reconciles on dismiss. This was a dead end on
  devices without Apple Intelligence (no Generate button, e.g. iPhone 14).
- Planner: dish photo as a scrimmed card background in the week calendar,
  behind a new Settings toggle (settings_show_dish_photos, default on). New
  optional AppSettings.showDishPhotosInPlanner (CloudKit/migration safe).
- FilledSlotView: inlines the meal-card chrome to support the photo layer.
- Toggle localized in all 6 languages.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BkanrydYtrme8wipTzWssG
2026-07-14 22:06:11 +02:00

80 lines
2.7 KiB
Swift

import SwiftUI
struct FilledSlotView: View {
let dishName: String
let dishDescription: String?
let tags: [(name: String, color: String)]
let mealType: MealType
var showsRuleWarning: Bool = false
var photoData: Data? = nil
var onRemove: (() -> Void)?
var body: some View {
VStack(alignment: .leading, spacing: 4) {
HStack {
Image(systemName: mealType.icon)
.font(.system(size: 12))
.foregroundColor(.mealMoodTextSecondary)
if showsRuleWarning {
Image(systemName: "exclamationmark.triangle.fill")
.font(.system(size: 12))
.foregroundColor(.mealMoodWarning)
}
Spacer()
if onRemove != nil {
Button {
onRemove?()
} label: {
Image(systemName: "xmark.circle.fill")
.font(.system(size: 14))
.foregroundColor(.mealMoodTextSecondary.opacity(0.5))
}
}
}
Text(dishName)
.font(.system(size: 13, weight: .semibold))
.foregroundColor(.mealMoodTextPrimary)
.lineLimit(1)
.minimumScaleFactor(0.75)
.frame(maxWidth: .infinity, alignment: .leading)
HStack(spacing: 3) {
ForEach(Array(tags.prefix(2).enumerated()), id: \.offset) { _, tag in
TagDot(color: tag.color, size: 9)
}
if tags.count > 2 {
Text("+\(tags.count - 2)")
.font(.system(size: 10, weight: .medium))
.foregroundColor(.mealMoodTextSecondary)
}
}
}
.padding(10)
.frame(maxWidth: .infinity, minHeight: 80, alignment: .topLeading)
.background(cardBackground)
.cornerRadius(16)
.shadow(color: Color.black.opacity(0.05), radius: 8, y: 4)
.overlay(
RoundedRectangle(cornerRadius: 16)
.stroke(Color(hex: "#F0F0F0"), lineWidth: 1)
)
}
/// Dish photo as a subtle card background, scrimmed so text stays legible.
@ViewBuilder
private var cardBackground: some View {
if let photoData, let image = UIImage(data: photoData) {
ZStack {
Image(uiImage: image)
.resizable()
.scaledToFill()
Color.mealMoodSurface.opacity(0.75)
}
} else {
Color.mealMoodSurface
}
}
}