Skip to content
This repository has been archived by the owner on Jan 10, 2024. It is now read-only.

Commit

Permalink
Feature/map (#398)
Browse files Browse the repository at this point in the history
* MC

* Draft some kind of viewmodel (#396)

Co-authored-by: Tim Gymnich <tgymnich@icloud.com>

* Bug fix for next weeks menu

* Menu Prices

* Toolbar

* - added MenuBtn to Toolbar
- added clearBtn to search field

* directions functionality in maps/toolbar

* - Mealplan List built
- fitted to lastest EatAPI update

* - Mealplan List built
- fitted to lastest EatAPI update

* Full MealPlan & MenuViews

* MC

* Draft some kind of viewmodel (#396)

Co-authored-by: Tim Gymnich <tgymnich@icloud.com>

* Bug fix for next weeks menu

* Menu Prices

* Toolbar

* resolved merge conflicts map-grades

Co-authored-by: Tim Gymnich <tgymnich@icloud.com>
  • Loading branch information
AW-tum and tgymnich authored Jan 27, 2022
1 parent d800bbf commit 2715bf6
Show file tree
Hide file tree
Showing 18 changed files with 792 additions and 459 deletions.
607 changes: 320 additions & 287 deletions Campus-iOS.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@
"version": "2.0.0"
}
},
{
"package": "Snap",
"repositoryURL": "https://github.com/nerdsupremacist/Snap.git",
"state": {
"branch": null,
"revision": "29943b7064547f391ea8352dea04903e2263d831",
"version": "0.2.2"
}
},
{
"package": "SwiftProtobuf",
"repositoryURL": "https://github.com/apple/swift-protobuf.git",
Expand Down
5 changes: 3 additions & 2 deletions Campus-iOS/App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ struct CampusApp: App {
MapView(zoomOnUser: true,
panelPosition: "down",
canteens: [],
selectedCanteenName: "",
selectedAnnotationIndex: 0)
selectedCanteenName: " ",
selectedAnnotationIndex: 0,
selectedCanteen: Cafeteria(location: Location(latitude: 0, longitude: 0, address: " "), name: " ", id: " "))
}
.tag(3)
.tabItem {
Expand Down
50 changes: 9 additions & 41 deletions Campus-iOS/Map/Cafeterias/MealPlanView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,59 +9,27 @@ import SwiftUI
import Alamofire

struct MealPlanView: View {
@State var canteen: Cafeteria?
@State var menus: [Menu] = []
@ObservedObject var viewModel: MealPlanViewModel

let endpoint = EatAPI.canteens
let sessionManager = Session.defaultSession

let dateFormatter = DateFormatter()
let formatter = DateFormatter()

var body: some View {
VStack {
List {
ForEach(menus, id: \.self) { item in
HStack {
Text(dateFormatter.string(from: item.date!))
Spacer()
NavigationLink(destination: MenuView(title: dateFormatter.string(from: item.date!), menu: item)) { EmptyView() }
.frame(width: 0, height: 0, alignment: .leading)
Spacer().frame(width: 10)
ForEach(viewModel.menus) { menu in
let title = formatter.string(from: menu.date)
NavigationLink(destination: MenuView(viewModel: menu, title: title)) {
Text(formatter.string(from: menu.date))
}
}
}
.navigationTitle(canteen!.name)
.navigationTitle(viewModel.title)
.onAppear {
dateFormatter.dateFormat = "EEEE, dd.MM.yyyy"
fetch()
formatter.dateFormat = "EEEE, dd.MM.yyyy"
viewModel.fetch()
}
}
}

func fetch() {
guard let cafeteria = canteen else { return }
let decoder = JSONDecoder()
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
decoder.dateDecodingStrategy = .formatted(formatter)
menus.removeAll()
let thisWeekEndpoint = EatAPI.menu(location: cafeteria.id, year: Date().year, week: Date().weekOfYear)
sessionManager.request(thisWeekEndpoint).responseDecodable(of: MealPlan.self, decoder: decoder) { [self] response in
guard let value = response.value else { return }
menus.append(contentsOf: value.days.filter({ !$0.dishes.isEmpty && ($0.date?.isToday ?? false || $0.date?.isLaterThanOrEqual(to: Date()) ?? false) }))
menus.sort(by: <)
print("MenuCount: ", menus.count)
}

let calendar = Calendar.current
guard let nextWeek = calendar.date(byAdding: .weekOfYear, value: 1, to: Date()) else { return }
let nextWeekEndpoint = EatAPI.menu(location: cafeteria.id, year: nextWeek.year, week: nextWeek.weekOfYear)
sessionManager.request(nextWeekEndpoint).responseDecodable(of: MealPlan.self, decoder: decoder) { [self] response in
guard let value = response.value else { return }
menus.append(contentsOf: value.days.filter({ !$0.dishes.isEmpty && ($0.date?.isToday ?? false || $0.date?.isLaterThanOrEqual(to: Date()) ?? false) }))
menus.sort(by: <)
}
}
}

/*struct MealPlanView_Previews: PreviewProvider {
Expand Down
80 changes: 80 additions & 0 deletions Campus-iOS/Map/Cafeterias/MealPlanViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// File.swift
// Campus-iOS
//
// Created by Tim Gymnich on 19.01.22.
//

import Foundation
import SwiftUI
import Alamofire

final class MealPlanViewModel: ObservableObject {
private let cafeteria: Cafeteria
private let endpoint = EatAPI.canteens
private let sessionManager = Session.defaultSession

@Published private(set) var title: String
@Published private(set) var menus: [MenuViewModel] = []

init(cafeteria: Cafeteria) {
self.cafeteria = cafeteria
self.title = cafeteria.name
}

func fetch() {
let decoder = JSONDecoder()
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
decoder.dateDecodingStrategy = .formatted(formatter)

let thisWeekEndpoint = EatAPI.menu(location: cafeteria.id, year: Date().year, week: Date().weekOfYear)

sessionManager.request(thisWeekEndpoint).responseDecodable(of: MealPlan.self, decoder: decoder) { [self] response in
guard let mealPlans = response.value else { return }
self.menus = mealPlans.days
.filter { !$0.dishes.isEmpty && ($0.date.isToday || $0.date.isLaterThanOrEqual(to: Date())) }
.sorted { $0.date < $1.date }
.map {
let categories = $0.dishes
.sorted { $0.dishType < $1.dishType }
.reduce(into: [:]) { (acc: inout [String: [Dish]], dish: Dish) -> () in
let type = dish.dishType.isEmpty ? "Sonstige" : dish.dishType
if acc[type] != nil {
acc[type]?.append(dish)
}
acc[type] = [dish]
}
.map { CategoryViewModel(name: $0.key, dishes: $0.value) }

return MenuViewModel(title: formatter.string(from: $0.date), date: $0.date, categories: categories) }
}

guard let nextWeek = Calendar.current.date(byAdding: .weekOfYear, value: 1, to: Date()) else { return }

let nextWeekEndpoint = EatAPI.menu(location: cafeteria.id, year: nextWeek.year, week: nextWeek.weekOfYear)

sessionManager.request(nextWeekEndpoint).responseDecodable(of: MealPlan.self, decoder: decoder) { [self] response in
guard let mealPlans = response.value else { return }
self.menus.append(contentsOf: mealPlans.days
.filter { !$0.dishes.isEmpty && ($0.date.isToday || $0.date.isLaterThanOrEqual(to: Date())) }
.sorted { $0.date < $1.date }
.map {
let categories = $0.dishes
.sorted { $0.dishType < $1.dishType }
.reduce(into: [:]) { (acc: inout [String: [Dish]], dish: Dish) -> () in
let type = dish.dishType.isEmpty ? "Sonstige" : dish.dishType
if acc[type] != nil {
acc[type]?.append(dish)
}
acc[type] = [dish]
}
.map { CategoryViewModel(name: $0.key, dishes: $0.value) }

print("DATE: ", $0.date)

return MenuViewModel(title: formatter.string(from: $0.date), date: $0.date, categories: categories) }
)
}
}
}
85 changes: 56 additions & 29 deletions Campus-iOS/Map/Cafeterias/MenuView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,74 @@
import SwiftUI

struct MenuView: View {
@ObservedObject var viewModel: MenuViewModel
@State var title: String
@State var menu: Menu
@State var categories: [Category] = []
@State var dishNames: [String] = []

var body: some View {
List {
ForEach(categories, id: \.self) { categoryItem in
Section(categoryItem.name) {
ForEach(categoryItem.dishes, id: \.self) { dish in
Text(dish.name)
ForEach($viewModel.categories) { $category in
Section(category.name) {
DisclosureGroup(isExpanded: $category.isExpanded) {
ForEach(category.dishes, id: \.self) { dish in
ForEach(Array(dish.prices.keys).sorted(by: >), id: \.self) { key in
HStack {
Text(key)
Spacer()
Text(self.configureDropDown(dish: dish, key: key))
}
}
}
} label: {
ForEach(category.dishes, id: \.self) { dish in
Text(dish.name)
.onTapGesture {
withAnimation {
category.isExpanded.toggle()
}
}
}
}
}
.font(.subheadline)
.foregroundColor(.black)
}
}
.navigationTitle(title)
.onAppear {
setList()
}
}

func setList() {
let sortedCategories = menu.categories.sorted(by: { (lhs, rhs) -> Bool in
return lhs.name > rhs.name
})

for var c in sortedCategories {
for d in menu.dishes {
if c.name == d.dishType {
if !c.dishes.contains(d) {
c.dishes.append(d)
}
}
}
var newCat = Category()
newCat.name = c.name
newCat.dishes = c.dishes
categories.append(newCat)
func configureDropDown(dish: Dish, key: String) -> String {
let priceFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.currencySymbol = ""
formatter.numberStyle = .currency
return formatter
}()

let price: Price

var basePriceString: String?
var unitPriceString: String?

switch key {
case "staff":
price = dish.prices["staff"]!
case "guests":
price = dish.prices["guests"]!
default:
price = dish.prices["students"]!
}

if let basePrice = price.basePrice, basePrice != 0 {
basePriceString = priceFormatter.string(for: basePrice)
}

if let unitPrice = price.unitPrice, let unit = price.unit, unitPrice != 0 {
unitPriceString = priceFormatter.string(for: unitPrice)?.appending(" / " + unit)
}

let divider: String = !(basePriceString?.isEmpty ?? true) && !(unitPriceString?.isEmpty ?? true) ? " + " : ""

let finalPrice: String = (basePriceString ?? "") + divider + (unitPriceString ?? "")

return finalPrice
}
}

Expand Down
35 changes: 35 additions & 0 deletions Campus-iOS/Map/Cafeterias/MenuViewModel 2.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// MealPlanViewModel.swift
// Campus-iOS
//
// Created by Tim Gymnich on 19.01.22.
//

import Foundation
import SwiftUI


final class MenuViewModel: ObservableObject, Identifiable {
let id = UUID()
let title: String
let date: Date
@Published var categories: [CategoryViewModel]

init(title: String, date: Date, categories: [CategoryViewModel]) {
self.title = title
self.date = date
self.categories = categories
}
}

struct CategoryViewModel: Identifiable {
var id = UUID()
var name: String
var dishes: [Dish]
var isExpanded: Bool = false

init(name: String, dishes: [Dish]) {
self.name = name
self.dishes = dishes
}
}
35 changes: 35 additions & 0 deletions Campus-iOS/Map/Cafeterias/MenuViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// MealPlanViewModel.swift
// Campus-iOS
//
// Created by Tim Gymnich on 19.01.22.
//

import Foundation
import SwiftUI


final class MenuViewModel: ObservableObject, Identifiable {
let id = UUID()
let title: String
let date: Date
@Published var categories: [CategoryViewModel]

init(title: String, date: Date, categories: [CategoryViewModel]) {
self.title = title
self.date = date
self.categories = categories
}
}

struct CategoryViewModel: Identifiable {
var id = UUID()
var name: String
var dishes: [Dish]
var isExpanded: Bool = false

init(name: String, dishes: [Dish]) {
self.name = name
self.dishes = dishes
}
}
Loading

0 comments on commit 2715bf6

Please sign in to comment.