mirror of
https://github.com/NinjaCheetah/RIT-Dining.git
synced 2026-03-04 21:25:27 -05:00
Started work on refactors
- The favorites model now lives inside of the base dining model, since it was only ever used in places where the main dining model was also available and is only relevant when the dining model is available. - Removed unnecessary instances of models that were going unused. - Moved the favorite/map/menu buttons in the top right of the DetailView into the right side toolbar. - This frees up a good bit of space at the top of the DetailView and looks cleaner, especially with iOS 26's new toolbar style. - Actually added a copyright string to the about screen. More refactors, both internally and for the UI, will be coming soon.
This commit is contained in:
@@ -10,9 +10,10 @@ import SafariServices
|
||||
|
||||
struct DetailView: View {
|
||||
@State var locationId: Int
|
||||
@Environment(Favorites.self) var favorites
|
||||
|
||||
@Environment(DiningModel.self) var model
|
||||
@Environment(\.openURL) private var openURL
|
||||
|
||||
@State private var showingSafari: Bool = false
|
||||
@State private var occupancyLoading: Bool = true
|
||||
@State private var occupancyPercentage: Double = 0.0
|
||||
@@ -78,112 +79,63 @@ struct DetailView: View {
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
VStack(alignment: .leading) {
|
||||
HStack(alignment: .center) {
|
||||
VStack(alignment: .leading) {
|
||||
Text(location.name)
|
||||
.font(.title)
|
||||
.fontWeight(.bold)
|
||||
Text(location.summary)
|
||||
.font(.title2)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundStyle(.secondary)
|
||||
VStack(alignment: .leading) {
|
||||
Text(location.name)
|
||||
.font(.title)
|
||||
.fontWeight(.bold)
|
||||
Text(location.summary)
|
||||
.font(.title2)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundStyle(.secondary)
|
||||
VStack(alignment: .leading) {
|
||||
switch location.open {
|
||||
case .open:
|
||||
Text("Open")
|
||||
.font(.title3)
|
||||
.foregroundStyle(.green)
|
||||
case .closed:
|
||||
Text("Closed")
|
||||
.font(.title3)
|
||||
.foregroundStyle(.red)
|
||||
case .openingSoon:
|
||||
Text("Opening Soon")
|
||||
.font(.title3)
|
||||
.foregroundStyle(.orange)
|
||||
case .closingSoon:
|
||||
Text("Closing Soon")
|
||||
.font(.title3)
|
||||
.foregroundStyle(.orange)
|
||||
}
|
||||
if let times = location.diningTimes, !times.isEmpty {
|
||||
ForEach(times, id: \.self) { time in
|
||||
Text("\(dateDisplay.string(from: time.openTime)) - \(dateDisplay.string(from: time.closeTime))")
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
} else {
|
||||
Text("Not Open Today")
|
||||
switch location.open {
|
||||
case .open:
|
||||
Text("Open")
|
||||
.font(.title3)
|
||||
.foregroundStyle(.green)
|
||||
case .closed:
|
||||
Text("Closed")
|
||||
.font(.title3)
|
||||
.foregroundStyle(.red)
|
||||
case .openingSoon:
|
||||
Text("Opening Soon")
|
||||
.font(.title3)
|
||||
.foregroundStyle(.orange)
|
||||
case .closingSoon:
|
||||
Text("Closing Soon")
|
||||
.font(.title3)
|
||||
.foregroundStyle(.orange)
|
||||
}
|
||||
if let times = location.diningTimes, !times.isEmpty {
|
||||
ForEach(times, id: \.self) { time in
|
||||
Text("\(dateDisplay.string(from: time.openTime)) - \(dateDisplay.string(from: time.closeTime))")
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
} else {
|
||||
Text("Not Open Today")
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
#if DEBUG
|
||||
HStack(spacing: 0) {
|
||||
ForEach(Range(1...5), id: \.self) { index in
|
||||
if occupancyPercentage > (20 * Double(index)) {
|
||||
Image(systemName: "person.fill")
|
||||
} else {
|
||||
Image(systemName: "person")
|
||||
}
|
||||
}
|
||||
ProgressView()
|
||||
.progressViewStyle(.circular)
|
||||
.frame(width: 18, height: 18)
|
||||
.opacity(occupancyLoading ? 1 : 0)
|
||||
.task {
|
||||
await getOccupancy()
|
||||
}
|
||||
}
|
||||
.foregroundStyle(Color.accent.opacity(occupancyLoading ? 0.5 : 1.0))
|
||||
.font(.title3)
|
||||
#endif
|
||||
}
|
||||
Spacer()
|
||||
VStack(alignment: .trailing) {
|
||||
HStack(alignment: .center) {
|
||||
// Favorites toggle button.
|
||||
Button(action: {
|
||||
if favorites.contains(location) {
|
||||
favorites.remove(location)
|
||||
} else {
|
||||
favorites.add(location)
|
||||
}
|
||||
}) {
|
||||
if favorites.contains(location) {
|
||||
Image(systemName: "star.fill")
|
||||
.foregroundStyle(.yellow)
|
||||
.font(.title3)
|
||||
} else {
|
||||
Image(systemName: "star")
|
||||
.foregroundStyle(.yellow)
|
||||
.font(.title3)
|
||||
}
|
||||
}
|
||||
// THIS FEATURE DISABLED AT RIT'S REQUEST FOR SECURITY REASONS.
|
||||
// No hard feelings or anything though, I get it.
|
||||
// // Open OnDemand. Unfortunately the locations use arbitrary IDs, so just open the main OnDemand page.
|
||||
// Button(action: {
|
||||
// openURL(URL(string: "https://ondemand.rit.edu")!)
|
||||
// }) {
|
||||
// Image(systemName: "cart")
|
||||
// .font(.title3)
|
||||
// }
|
||||
// .disabled(location.open == .closed || location.open == .openingSoon)
|
||||
// Open this location on the RIT map in embedded Safari.
|
||||
Button(action: {
|
||||
showingSafari = true
|
||||
}) {
|
||||
Image(systemName: "map")
|
||||
.font(.title3)
|
||||
#if DEBUG
|
||||
HStack(spacing: 0) {
|
||||
ForEach(Range(1...5), id: \.self) { index in
|
||||
if occupancyPercentage > (20 * Double(index)) {
|
||||
Image(systemName: "person.fill")
|
||||
} else {
|
||||
Image(systemName: "person")
|
||||
}
|
||||
}
|
||||
if let fdmpIds = location.fdmpIds {
|
||||
NavigationLink(destination: MenuView(accountId: fdmpIds.accountId, locationId: fdmpIds.locationId)) {
|
||||
Text("View Menu")
|
||||
ProgressView()
|
||||
.progressViewStyle(.circular)
|
||||
.frame(width: 18, height: 18)
|
||||
.opacity(occupancyLoading ? 1 : 0)
|
||||
.task {
|
||||
await getOccupancy()
|
||||
}
|
||||
.padding(.top, 5)
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
.foregroundStyle(Color.accent.opacity(occupancyLoading ? 0.5 : 1.0))
|
||||
.font(.title3)
|
||||
#endif
|
||||
}
|
||||
.padding(.bottom, 12)
|
||||
if let visitingChefs = location.visitingChefs, !visitingChefs.isEmpty {
|
||||
@@ -267,6 +219,50 @@ struct DetailView: View {
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.padding(.horizontal, 8)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .primaryAction) {
|
||||
// Favorites toggle button.
|
||||
Button(action: {
|
||||
if model.favorites.contains(location) {
|
||||
model.favorites.remove(location)
|
||||
} else {
|
||||
model.favorites.add(location)
|
||||
}
|
||||
}) {
|
||||
if model.favorites.contains(location) {
|
||||
Image(systemName: "star.fill")
|
||||
.foregroundStyle(.yellow)
|
||||
//.font(.title3)
|
||||
} else {
|
||||
Image(systemName: "star")
|
||||
.foregroundStyle(.yellow)
|
||||
//.font(.title3)
|
||||
}
|
||||
}
|
||||
// THIS FEATURE DISABLED AT RIT'S REQUEST FOR SECURITY REASONS.
|
||||
// No hard feelings or anything though, I get it.
|
||||
// // Open OnDemand. Unfortunately the locations use arbitrary IDs, so just open the main OnDemand page.
|
||||
// Button(action: {
|
||||
// openURL(URL(string: "https://ondemand.rit.edu")!)
|
||||
// }) {
|
||||
// Image(systemName: "cart")
|
||||
// .font(.title3)
|
||||
// }
|
||||
// .disabled(location.open == .closed || location.open == .openingSoon)
|
||||
// Open this location on the RIT map in embedded Safari.
|
||||
Button(action: {
|
||||
showingSafari = true
|
||||
}) {
|
||||
Image(systemName: "map")
|
||||
//.font(.title3)
|
||||
}
|
||||
if let fdmpIds = location.fdmpIds {
|
||||
NavigationLink(destination: MenuView(accountId: fdmpIds.accountId, locationId: fdmpIds.locationId)) {
|
||||
Image(systemName: "menucard")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Details")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
|
||||
Reference in New Issue
Block a user