development
swift 72 lines 3 KB
Raw
1 import SwiftUI
2
3 struct SavedView: View {
4 @EnvironmentObject private var appState: AppState
5 @EnvironmentObject private var favoritesStore: FavoritesStore
6
7 private var savedEntries: [GuideEntry] {
8 appState.contentRepository.entries.filter { favoritesStore.favoriteIDs.contains($0.id) }
9 }
10
11 var body: some View {
12 ScrollView {
13 VStack(alignment: .leading, spacing: 20) {
14 #if os(tvOS)
15 TVPageHeader("Saved")
16 #endif
17
18 if savedEntries.isEmpty {
19 EmptyStateView(
20 title: "Save dishes you want to revisit",
21 message:
22 "Build a shortlist as you browse so it is easy to come back to dishes, ingredients, and traditions later.",
23 systemImage: "heart"
24 )
25 } else {
26 SectionHeader(
27 "Your shortlist", subtitle: "A calm place to keep what you want to remember"
28 )
29
30 ForEach(savedEntries) { entry in
31 KleponCard {
32 HStack(alignment: .top, spacing: 12) {
33 NavigationLink {
34 GuideDetailView(entry: entry)
35 } label: {
36 VStack(alignment: .leading, spacing: 8) {
37 Text(entry.title)
38 .font(KleponTypography.cardTitle)
39 .foregroundStyle(KleponColor.textPrimary)
40
41 Text(entry.summary)
42 .font(KleponTypography.bodySecondary)
43 .foregroundStyle(KleponColor.textSecondary)
44 }
45 .frame(maxWidth: .infinity, alignment: .leading)
46 }
47 .kleponInteractiveButtonStyle()
48
49 Button {
50 favoritesStore.toggle(entry.id)
51 } label: {
52 Image(systemName: "heart.slash")
53 .foregroundStyle(KleponColor.highlight)
54 .padding(10)
55 .background(Circle().fill(KleponColor.surfaceSecondary))
56 }
57 .kleponInteractiveButtonStyle()
58 }
59 }
60 }
61 }
62 }
63 .padding(.horizontal, 20)
64 .padding(.vertical, 16)
65 }
66 .background(KleponColor.background.ignoresSafeArea())
67 .navigationTitle("Saved")
68 #if os(tvOS)
69 .toolbar(.hidden, for: .navigationBar)
70 #endif
71 }
72 }