moodlit-native/Sources/Features/Moods/MoodCard.swift
till 9fe686780d feat: Favorit-Toggle + SequenceRow-Kontextmenü
MoodCard-Kontextmenü um Favorit/Aus-Favoriten erweitert (store.
toggleFavorite), an beiden Grid-Aufrufstellen verdrahtet. SequenceRow
bekommt ein Kontextmenü (Abspielen + Löschen) parallel zum Swipe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 13:24:16 +02:00

89 lines
2.1 KiB
Swift

import SwiftUI
/// Karten-Vorschau eines Mood statische Gradient-Tile in der
/// Übersichts-Grid (kein TimelineView, damit die Auswahl nicht
/// flimmert). Klick öffnet `MoodPlayerView` mit der Animation.
public struct MoodCard: View {
let mood: Mood
let isFavorite: Bool
let onTap: () -> Void
let onToggleFavorite: (() -> Void)?
let onDelete: (() -> Void)?
public init(
mood: Mood,
isFavorite: Bool = false,
onTap: @escaping () -> Void,
onToggleFavorite: (() -> Void)? = nil,
onDelete: (() -> Void)? = nil
) {
self.mood = mood
self.isFavorite = isFavorite
self.onTap = onTap
self.onToggleFavorite = onToggleFavorite
self.onDelete = onDelete
}
public var body: some View {
Button(action: onTap) {
ZStack(alignment: .bottomLeading) {
staticPreview
.aspectRatio(16.0 / 10.0, contentMode: .fill)
.frame(maxWidth: .infinity)
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
LinearGradient(
colors: [.black.opacity(0.55), .clear],
startPoint: .bottom,
endPoint: .center
)
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
.allowsHitTesting(false)
Text(mood.name)
.font(.headline)
.foregroundStyle(.white)
.shadow(radius: 4)
.padding(12)
if isFavorite {
Image(systemName: "heart.fill")
.foregroundStyle(.red)
.shadow(radius: 4)
.padding(10)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
.allowsHitTesting(false)
}
}
}
.buttonStyle(.plain)
.contextMenu {
if let onToggleFavorite {
Button(action: onToggleFavorite) {
Label(
isFavorite ? "Aus Favoriten" : "Favorit",
systemImage: isFavorite ? "heart.slash" : "heart"
)
}
}
if let onDelete, !mood.isPreset {
Button(role: .destructive, action: onDelete) {
Label("Löschen", systemImage: "trash")
}
}
}
}
@ViewBuilder
private var staticPreview: some View {
if mood.colors.count == 1 {
Color(hex: mood.colors[0])
} else {
LinearGradient(
colors: mood.swiftUIColors,
startPoint: .topLeading,
endPoint: .bottomTrailing
)
}
}
}