import SwiftUI struct DishDrawerView: View { let dishes: [Dish] let tags: [Tag] let language: AppLanguage let usedDishIds: Set var onAddDish: () -> Void var onQuickAssignDish: (Dish) -> Void var onEditDish: (Dish) -> Void var onDeleteDish: (Dish) -> Void @Binding var draggedDish: Dish? @State private var searchText: String = "" @State private var hideUsedThisWeek: Bool = false private var filteredDishes: [Dish] { let term = searchText.trimmingCharacters(in: .whitespacesAndNewlines) return Dish.stableSortedForDisplay(dishes).filter { dish in let matchesSearch = term.isEmpty || dish.name.localizedCaseInsensitiveContains(term) let matchesUsedFilter = !hideUsedThisWeek || !usedDishIds.contains(dish.id) return matchesSearch && matchesUsedFilter } } var body: some View { VStack(spacing: 12) { HStack { HStack(spacing: 6) { Image(systemName: "list.clipboard") Text("home_my_dishes") .font(.mealMoodH3) } .foregroundColor(.mealMoodTextPrimary) Spacer() Button(action: onAddDish) { Image(systemName: "plus.circle.fill") .font(.system(size: 28)) .foregroundColor(.mealMoodCoral) } } .padding(.horizontal, 16) if dishes.isEmpty { VStack(spacing: 16) { Image(systemName: "fork.knife") .font(.system(size: 40)) .foregroundColor(Color(hex: "#C4C4C4")) Text("home_add_first_dish") .font(.mealMoodBody) .foregroundColor(.mealMoodTextSecondary) PrimaryButton(title: String(localized: "home_add_dish"), icon: nil, action: onAddDish) .padding(.horizontal, 40) } .padding(.vertical, 32) } else { HStack(spacing: 8) { Image(systemName: "magnifyingglass") .foregroundColor(.mealMoodTextSecondary) TextField("home_my_dishes_search", text: $searchText) .font(.mealMoodBody) if !searchText.isEmpty { Button { searchText = "" } label: { Image(systemName: "xmark.circle.fill") .foregroundColor(.mealMoodTextSecondary) } .buttonStyle(.plain) } } .padding(.horizontal, 12) .padding(.vertical, 10) .background(Color.mealMoodSurface) .cornerRadius(12) .padding(.horizontal, 16) Button { hideUsedThisWeek.toggle() } label: { HStack(spacing: 8) { Image(systemName: hideUsedThisWeek ? "checkmark.square.fill" : "square") .foregroundColor(hideUsedThisWeek ? .mealMoodCoral : .mealMoodTextSecondary) Text("home_my_dishes_hide_used") .font(.mealMoodSmall) .foregroundColor(.mealMoodTextPrimary) Spacer() } .padding(.horizontal, 16) .padding(.vertical, 6) } .buttonStyle(.plain) LazyVStack(spacing: 8) { ForEach(filteredDishes, id: \.id) { dish in DishCardView( dish: dish, tags: tags, language: language, onEdit: { onEditDish(dish) }, onDelete: { onDeleteDish(dish) } ) .contentShape(Rectangle()) .onTapGesture { onQuickAssignDish(dish) } .swipeActions(edge: .leading, allowsFullSwipe: false) { Button { onEditDish(dish) } label: { Label("dish_edit_title", systemImage: "pencil") } .tint(.mealMoodCoral) } .swipeActions(edge: .trailing, allowsFullSwipe: true) { Button(role: .destructive) { onDeleteDish(dish) } label: { Label("dish_delete", systemImage: "trash") } } .draggable("dish:\(dish.id.uuidString)") { DishCardView(dish: dish, tags: tags, language: language) .frame(width: 200) .opacity(0.8) } } if filteredDishes.isEmpty { Text("home_my_dishes_search_empty") .font(.mealMoodBody) .foregroundColor(.mealMoodTextSecondary) .padding(.top, 8) } } .padding(.horizontal, 16) } } .padding(.top, 16) } } struct DishCardView: View { let dish: Dish let tags: [Tag] let language: AppLanguage var onEdit: (() -> Void)? = nil var onDelete: (() -> Void)? = nil private var dishTags: [Tag] { tags.filter { dish.tagIds.contains($0.id) } } var body: some View { HStack { VStack(alignment: .leading, spacing: 4) { Text(dish.name) .font(.mealMoodBodyBold) .foregroundColor(.mealMoodTextPrimary) if let desc = dish.descriptionText, !desc.isEmpty { Text(desc) .font(.mealMoodCaption) .foregroundColor(.mealMoodTextSecondary) .lineLimit(1) } } Spacer() HStack(spacing: 4) { ForEach(dishTags.prefix(3)) { tag in TagDot(color: tag.color, size: 10) } } if onEdit != nil || onDelete != nil { HStack(spacing: 8) { if let onEdit { Button(action: onEdit) { Image(systemName: "pencil.circle") .foregroundColor(.mealMoodCoral) } .buttonStyle(.plain) } if let onDelete { Button(action: onDelete) { Image(systemName: "trash.circle") .foregroundColor(.mealMoodError) } .buttonStyle(.plain) } } } } .padding(14) .mealCardStyle() } }