| Code | What It Does | How It Does It |
| ▶ IMPORTS | | |
| import SwiftUI | Framework imports | Imports SwiftUI. |
| struct WatchShowsView: View {
@EnvironmentObject var store: WatchEntryStore
// MARK: - Sections
private var upcoming: [WatchEntry] {
let now = Date()
return store.entries
.filter { $0.entryMode == .show && !$0.consider && $0.dateTime >= now }
.sorted { $0.dateTime < $1.dateTime } // soonest first
}
private var consider: [WatchEntry] {
store.entries
.filter { $0.entryMode == .show && $0.consider }
.sorted { $0.playName.lowercased() < $1.playName.lowercased() }
}
private var past: [WatchEntry] {
let now = Date()
return store.entries
.filter { $0.entryMode == .show && !$0.consider && $0.dateTime < now }
.sorted { $0.dateTime > $1.dateTime } // most recent first
}
private var hasAny: Bool { !upcoming.isEmpty || !consider.isEmpty || !past.isEmpty }
// MARK: - Body
var body: some View {
Group {
if !store.isLoaded {
ProgressView()
} else if !hasAny {
VStack(spacing: 8) {
Image(systemName: "theatermasks")
.font(.system(size: 28))
.foregroundColor(.purple)
Text("No shows yet")
.font(.caption)
.foregroundColor(.secondary)
}
} else {
List {
if !upcoming.isEmpty {
Section("Upcoming") {
ForEach(upcoming) { entry in
NavigationLink(destination: WatchEntryDetailView(entry: entry)) {
ShowRow(entry: entry, showDate: true)
}
}
}
}
if !consider.isEmpty {
Section("Consider") {
ForEach(consider) { entry in
NavigationLink(destination: WatchEntryDetailView(entry: entry)) {
ShowRow(entry: entry, showDate: false)
}
}
}
}
if !past.isEmpty {
Section("Past") {
ForEach(past) { entry in
NavigationLink(destination: WatchEntryDetailView(entry: entry)) {
ShowRow(entry: entry, showDate: true)
}
}
}
}
}
.listStyle(.plain)
}
}
.navigationTitle("Shows")
.navigationBarTitleDisplayMode(.inline)
}
} | `WatchShowsView` struct | Defines the `WatchShowsView` struct. Conforms to View. |
| ▶ ROW | | |
| private struct ShowRow: View {
let entry: WatchEntry
let showDate: Bool
var body: some View {
VStack(alignment: .leading, spacing: 2) {
Text(entry.playName)
.font(.system(size: 14, weight: .semibold))
.foregroundColor(lavender)
.lineLimit(2)
if !entry.cuisine.isEmpty {
Text(entry.cuisine)
.font(.system(size: 12))
.foregroundColor(.white)
.lineLimit(1)
}
if showDate {
if let days = entry.daysUntil {
Text(days == 0 ? "Today!" : days == 1 ? "Tomorrow" : "\(days) days")
.font(.system(size: 11))
.foregroundColor(.yellow)
} else {
Text(entry.formattedDate)
.font(.system(size: 11))
.foregroundColor(.white.opacity(0.7))
}
} else if entry.starRating > 0 {
HStack(spacing: 2) {
ForEach(1...5, id: \.self) { star in
Image(systemName: star <= entry.starRating ? "star.fill" : "star")
.font(.system(size: 7))
.foregroundColor(star <= entry.starRating ? .yellow : .gray.opacity(0.4))
}
}
}
}
.padding(.vertical, 2)
}
} | `ShowRow` struct | Defines the `ShowRow` struct. Conforms to View. |
| #Preview {
NavigationStack { WatchShowsView() }
.environmentObject(WatchEntryStore())
} | Code block | See source code for full implementation. |