| struct WatchEntryDetailView: View {
let entry: WatchEntry
@Environment(\.openURL) private var openURL
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 8) {
Text(entry.playName)
.font(.headline)
.foregroundColor(.red)
.fixedSize(horizontal: false, vertical: true)
if entry.rating > 0 {
HStack(spacing: 2) {
ForEach(0..<entry.rating, id: \.self) { _ in
Image(systemName: "star.fill")
.font(.system(size: 10))
.foregroundColor(.yellow)
}
}
}
Divider()
Label(entry.formattedDate, systemImage: "calendar")
.font(.caption)
if !entry.cuisine.isEmpty {
if entry.address.isEmpty {
Button {
openInMaps(entry.cuisine, displayName: entry.cuisine)
} label: {
Label(entry.cuisine, systemImage: "building.2")
.font(.caption)
}
.buttonStyle(.plain)
} else {
Label(entry.cuisine, systemImage: "building.2")
.font(.caption)
}
}
if !entry.neighborhood.isEmpty {
Label(entry.neighborhood, systemImage: "chair")
.font(.caption)
}
// Address — always shown; tappable when not empty
if !entry.address.isEmpty {
Button {
openInMaps(entry.address, displayName: entry.cuisine.isEmpty ? entry.address : entry.cuisine)
} label: {
Label(entry.address, systemImage: "location")
.font(.caption)
}
.buttonStyle(.plain)
} else {
Label("No address", systemImage: "location")
.font(.caption)
.foregroundColor(.secondary)
}
if !entry.phone.isEmpty {
Label(entry.phone, systemImage: "phone")
.font(.caption)
.foregroundColor(.secondary)
}
if let days = entry.daysUntil {
Divider()
Text(days == 0 ? "Today!" : days == 1 ? "Tomorrow!" : "\(days) days away")
.font(.caption)
.foregroundColor(.yellow)
.frame(maxWidth: .infinity, alignment: .center)
}
}
.padding(.horizontal, 4)
}
.navigationTitle(entry.playName)
.navigationBarTitleDisplayMode(.inline)
}
private func openInMaps(_ query: String, displayName: String) {
let queryWithCity = query.contains(",") ? query : "\"\(query)\", New York"
openWithAppleMaps(queryWithCity, displayName: displayName)
}
private func openWithAppleMaps(_ query: String, displayName: String) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(query) { placemarks, _ in
if let placemark = placemarks?.first {
let mapItem = MKMapItem(placemark: MKPlacemark(placemark: placemark))
mapItem.name = displayName
mapItem.openInMaps()
} else {
let request = MKLocalSearch.Request()
request.naturalLanguageQuery = query
MKLocalSearch(request: request).start { response, _ in
if let mapItem = response?.mapItems.first {
mapItem.openInMaps()
}
}
}
}
}
} | `WatchEntryDetailView` struct | Defines the `WatchEntryDetailView` struct. Conforms to View. |