Files
FamilyMealPlanner/MealMood/Views/Home/DishDrawerView.swift
T

203 lines
7.5 KiB
Swift

import SwiftUI
struct DishDrawerView: View {
let dishes: [Dish]
let tags: [Tag]
let language: AppLanguage
let usedDishIds: Set<UUID>
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()
}
}