From 2715bf6f99a163e44ed5c665b1fbae8b2b32c68d Mon Sep 17 00:00:00 2001 From: August Wittgenstein <75639931+AW-tum@users.noreply.github.com> Date: Thu, 27 Jan 2022 17:02:34 +0100 Subject: [PATCH] Feature/map (#398) * MC * Draft some kind of viewmodel (#396) Co-authored-by: Tim Gymnich * 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 * Bug fix for next weeks menu * Menu Prices * Toolbar * resolved merge conflicts map-grades Co-authored-by: Tim Gymnich --- Campus-iOS.xcodeproj/project.pbxproj | 607 +++++++++--------- .../xcshareddata/swiftpm/Package.resolved | 9 + Campus-iOS/App.swift | 5 +- Campus-iOS/Map/Cafeterias/MealPlanView.swift | 50 +- .../Map/Cafeterias/MealPlanViewModel.swift | 80 +++ Campus-iOS/Map/Cafeterias/MenuView.swift | 85 ++- .../Map/Cafeterias/MenuViewModel 2.swift | 35 + Campus-iOS/Map/Cafeterias/MenuViewModel.swift | 35 + Campus-iOS/Map/MainView/MapContent.swift | 21 +- Campus-iOS/Map/MainView/MapView.swift | 9 +- Campus-iOS/Map/MainView/Panel.swift | 12 +- Campus-iOS/Map/MainView/PanelContent.swift | 92 +-- Campus-iOS/Map/MainView/PanelRow 2.swift | 62 ++ Campus-iOS/Map/MainView/PanelRow.swift | 62 ++ Campus-iOS/Map/MainView/Toolbar.swift | 48 ++ Campus-iOS/Map/Types/Cafeteria.swift | 4 +- Campus-iOS/Map/Types/Dish.swift | 6 +- Campus-iOS/Map/Types/Menu.swift | 29 +- 18 files changed, 792 insertions(+), 459 deletions(-) create mode 100644 Campus-iOS/Map/Cafeterias/MealPlanViewModel.swift create mode 100644 Campus-iOS/Map/Cafeterias/MenuViewModel 2.swift create mode 100644 Campus-iOS/Map/Cafeterias/MenuViewModel.swift create mode 100644 Campus-iOS/Map/MainView/PanelRow 2.swift create mode 100644 Campus-iOS/Map/MainView/PanelRow.swift create mode 100644 Campus-iOS/Map/MainView/Toolbar.swift diff --git a/Campus-iOS.xcodeproj/project.pbxproj b/Campus-iOS.xcodeproj/project.pbxproj index 5c7a2639..f3d03b3c 100644 --- a/Campus-iOS.xcodeproj/project.pbxproj +++ b/Campus-iOS.xcodeproj/project.pbxproj @@ -9,15 +9,20 @@ /* Begin PBXBuildFile section */ 100803462764E2C50013ED0E /* ProfileToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 100803452764E2C50013ED0E /* ProfileToolbar.swift */; }; 100803482764E37A0013ED0E /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 100803472764E37A0013ED0E /* ProfileView.swift */; }; + 226CB5172798BD910043ABCA /* MenuViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 226CB5162798BD910043ABCA /* MenuViewModel.swift */; }; + 226CB5192798BF3E0043ABCA /* MealPlanViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 226CB5182798BF3E0043ABCA /* MealPlanViewModel.swift */; }; + 226CB51B2798DA050043ABCA /* PanelRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 226CB51A2798DA050043ABCA /* PanelRow.swift */; }; + 226CB51E2798DF9C0043ABCA /* Snap in Frameworks */ = {isa = PBXBuildFile; productRef = 226CB51D2798DF9C0043ABCA /* Snap */; }; + 226CB5202798E34E0043ABCA /* Panel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 226CB51F2798E34E0043ABCA /* Panel.swift */; }; 3616C4B8278F6EF2000A1BC9 /* MealPlan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3616C4AD278F6EF2000A1BC9 /* MealPlan.swift */; }; 3616C4B9278F6EF2000A1BC9 /* Dish.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3616C4AE278F6EF2000A1BC9 /* Dish.swift */; }; 3616C4BA278F6EF2000A1BC9 /* Cafeteria.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3616C4AF278F6EF2000A1BC9 /* Cafeteria.swift */; }; 3616C4BB278F6EF2000A1BC9 /* Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3616C4B0278F6EF2000A1BC9 /* Menu.swift */; }; 3616C4BC278F6EF2000A1BC9 /* MealPlanView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3616C4B2278F6EF2000A1BC9 /* MealPlanView.swift */; }; 3616C4BD278F6EF2000A1BC9 /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3616C4B4278F6EF2000A1BC9 /* MapView.swift */; }; - 3616C4BE278F6EF2000A1BC9 /* Panel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3616C4B5278F6EF2000A1BC9 /* Panel.swift */; }; 3616C4BF278F6EF2000A1BC9 /* MapContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3616C4B6278F6EF2000A1BC9 /* MapContent.swift */; }; 3616C4C0278F6EF2000A1BC9 /* PanelContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3616C4B7278F6EF2000A1BC9 /* PanelContent.swift */; }; + 3616C4C2278F6F23000A1BC9 /* EatAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3616C4C1278F6F23000A1BC9 /* EatAPI.swift */; }; 3616C4C4278F9C0A000A1BC9 /* SheetNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3616C4C3278F9C0A000A1BC9 /* SheetNavigator.swift */; }; 3616C4C7278FA2D3000A1BC9 /* Enums.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3616C4C6278FA2D3000A1BC9 /* Enums.swift */; }; 36203E7F2761B9D000C24658 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 36203E7D2761B9D000C24658 /* Localizable.strings */; }; @@ -44,72 +49,72 @@ 36E964AA277498B60055777F /* KVKCalendar in Frameworks */ = {isa = PBXBuildFile; productRef = 36E964A9277498B60055777F /* KVKCalendar */; }; 36E964AC277499860055777F /* CalendarDisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36E964AB277499860055777F /* CalendarDisplayView.swift */; }; 36FAE365277472EF00628799 /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FAE364277472EF00628799 /* LoginViewModel.swift */; }; + 36FF90602773BB5800F4C785 /* MVGAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FF905D2773BB5800F4C785 /* MVGAPI.swift */; }; + 36FF90612773BB5800F4C785 /* TUMOnlineAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FF905E2773BB5800F4C785 /* TUMOnlineAPI.swift */; }; + 36FF90622773BB5800F4C785 /* TUMCabeAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FF905F2773BB5800F4C785 /* TUMCabeAPI.swift */; }; 36FF90652773BB8200F4C785 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FF90642773BB8100F4C785 /* Extensions.swift */; }; 36FF90682773BCA600F4C785 /* SWXMLHash in Frameworks */ = {isa = PBXBuildFile; productRef = 36FF90672773BCA600F4C785 /* SWXMLHash */; }; + 36FF906C2773BE3000F4C785 /* BackendError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FF906A2773BE3000F4C785 /* BackendError.swift */; }; + 36FF906D2773BE3000F4C785 /* XMLSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FF906B2773BE3000F4C785 /* XMLSerializer.swift */; }; 36FF906F2773BE8100F4C785 /* AuthenticationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FF906E2773BE8100F4C785 /* AuthenticationHandler.swift */; }; 36FF90722773BFC300F4C785 /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 36FF90712773BFC300F4C785 /* FirebaseAnalytics */; }; 36FF90742773BFC300F4C785 /* FirebaseAnalyticsSwift-Beta in Frameworks */ = {isa = PBXBuildFile; productRef = 36FF90732773BFC300F4C785 /* FirebaseAnalyticsSwift-Beta */; }; 36FF90762773BFC300F4C785 /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = 36FF90752773BFC300F4C785 /* FirebaseCrashlytics */; }; + 4146FE89279D52DC00655D1A /* Toolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4146FE88279D52DC00655D1A /* Toolbar.swift */; }; 41BD20E2279228B8001FA1B0 /* DishLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41BD20E1279228B8001FA1B0 /* DishLabel.swift */; }; 41BD20E4279228E2001FA1B0 /* MensaEnumService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41BD20E3279228E2001FA1B0 /* MensaEnumService.swift */; }; + 41D55D6E27A2EFB200DE7155 /* LRUCache in Frameworks */ = {isa = PBXBuildFile; productRef = 41D55D6D27A2EFB200DE7155 /* LRUCache */; }; + 41D55D7227A2F06800DE7155 /* Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D7127A2F06800DE7155 /* Cache.swift */; }; + 41D55D7427A2F0CA00DE7155 /* Modus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D7327A2F0CA00DE7155 /* Modus.swift */; }; + 41D55D7C27A2F17300DE7155 /* LectureDetailsViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D7827A2F17300DE7155 /* LectureDetailsViewModel+State.swift */; }; + 41D55D7D27A2F17300DE7155 /* LectureDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D7927A2F17300DE7155 /* LectureDetailsViewModel.swift */; }; + 41D55D7E27A2F17300DE7155 /* LecturesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D7A27A2F17300DE7155 /* LecturesViewModel.swift */; }; + 41D55D7F27A2F17300DE7155 /* LecturesViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D7B27A2F17300DE7155 /* LecturesViewModel+State.swift */; }; + 41D55D8B27A2F20300DE7155 /* LecturesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D8127A2F20300DE7155 /* LecturesView.swift */; }; + 41D55D8C27A2F20300DE7155 /* LectureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D8227A2F20300DE7155 /* LectureView.swift */; }; + 41D55D8D27A2F20300DE7155 /* LectureDetailsBasicInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D8427A2F20300DE7155 /* LectureDetailsBasicInfoView.swift */; }; + 41D55D8E27A2F20300DE7155 /* LectureDetailsTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D8527A2F20300DE7155 /* LectureDetailsTitleView.swift */; }; + 41D55D8F27A2F20300DE7155 /* LectureDetailsDetailedInfoRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D8627A2F20300DE7155 /* LectureDetailsDetailedInfoRowView.swift */; }; + 41D55D9027A2F20300DE7155 /* LectureDetailsDetailedInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D8727A2F20300DE7155 /* LectureDetailsDetailedInfoView.swift */; }; + 41D55D9127A2F20300DE7155 /* LectureDetailsBasicInfoRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D8827A2F20300DE7155 /* LectureDetailsBasicInfoRowView.swift */; }; + 41D55D9227A2F20300DE7155 /* LectureDetailsLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D8927A2F20300DE7155 /* LectureDetailsLinkView.swift */; }; + 41D55D9327A2F20300DE7155 /* LecturesDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D8A27A2F20300DE7155 /* LecturesDetailView.swift */; }; + 41D55D9627A2F23700DE7155 /* FailedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D9427A2F23700DE7155 /* FailedView.swift */; }; + 41D55D9727A2F23700DE7155 /* GroupBoxLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D9527A2F23700DE7155 /* GroupBoxLabelView.swift */; }; + 41D55D9927A2F28400DE7155 /* LectureDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D9827A2F28400DE7155 /* LectureDetails.swift */; }; + 41D55D9B27A2F2B100DE7155 /* LectureDetailsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D9A27A2F2B100DE7155 /* LectureDetailsService.swift */; }; + 41D55D9E27A2F32800DE7155 /* GradesViewModel+ChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D9C27A2F32800DE7155 /* GradesViewModel+ChartData.swift */; }; + 41D55D9F27A2F32800DE7155 /* GradesViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55D9D27A2F32800DE7155 /* GradesViewModel+State.swift */; }; + 41D55DA227A2F34700DE7155 /* BarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55DA027A2F34700DE7155 /* BarChartView.swift */; }; + 41D55DA327A2F34700DE7155 /* GradesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55DA127A2F34700DE7155 /* GradesView.swift */; }; + 41D55DA527A2F38300DE7155 /* LectureDetailsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41D55DA427A2F38300DE7155 /* LectureDetailsScreen.swift */; }; 41DDB33B2792F70A00FBEC81 /* MenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41DDB33A2792F70A00FBEC81 /* MenuView.swift */; }; + 972397412772825D004BF7AB /* Lecture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 972397402772825D004BF7AB /* Lecture.swift */; }; + 9723974327728268004BF7AB /* LecturesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9723974227728268004BF7AB /* LecturesScreen.swift */; }; + 972397452772826E004BF7AB /* LecturesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 972397442772826E004BF7AB /* LecturesService.swift */; }; + 97997AD22772179D0079F809 /* APIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97997AD12772179D0079F809 /* APIConstants.swift */; }; + 97997AD5277222730079F809 /* Grade.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97997AD4277222730079F809 /* Grade.swift */; }; + 97997AD82772265D0079F809 /* GradesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97997AD72772265D0079F809 /* GradesScreen.swift */; }; + 97997ADA27722A0A0079F809 /* GradeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97997AD927722A0A0079F809 /* GradeView.swift */; }; + 97997ADE27722B470079F809 /* GradesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97997ADD27722B470079F809 /* GradesService.swift */; }; 97997AE127722D660079F809 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 97997AE027722D660079F809 /* Alamofire */; }; + 97997AE427722E3B0079F809 /* GradesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97997AE327722E3B0079F809 /* GradesViewModel.swift */; }; 97997AE7277234120079F809 /* XMLCoder in Frameworks */ = {isa = PBXBuildFile; productRef = 97997AE6277234120079F809 /* XMLCoder */; }; - 979DBFAC2798C00C00E45513 /* LRUCache in Frameworks */ = {isa = PBXBuildFile; productRef = 979DBFAB2798C00C00E45513 /* LRUCache */; }; - 979DBFF82798C08C00E45513 /* LectureDetailsViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFAF2798C08C00E45513 /* LectureDetailsViewModel+State.swift */; }; - 979DBFF92798C08C00E45513 /* LectureDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFB02798C08C00E45513 /* LectureDetailsViewModel.swift */; }; - 979DBFFA2798C08C00E45513 /* LecturesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFB12798C08C00E45513 /* LecturesViewModel.swift */; }; - 979DBFFB2798C08C00E45513 /* LecturesViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFB22798C08C00E45513 /* LecturesViewModel+State.swift */; }; - 979DBFFC2798C08C00E45513 /* LectureDetailsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFB42798C08C00E45513 /* LectureDetailsScreen.swift */; }; - 979DBFFD2798C08C00E45513 /* LecturesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFB52798C08C00E45513 /* LecturesScreen.swift */; }; - 979DBFFE2798C08C00E45513 /* LectureDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFB72798C08C00E45513 /* LectureDetails.swift */; }; - 979DBFFF2798C08C00E45513 /* Lecture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFB82798C08C00E45513 /* Lecture.swift */; }; - 979DC0002798C08C00E45513 /* LecturesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFBA2798C08C00E45513 /* LecturesService.swift */; }; - 979DC0012798C08C00E45513 /* LectureDetailsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFBB2798C08C00E45513 /* LectureDetailsService.swift */; }; - 979DC0022798C08C00E45513 /* LecturesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFBD2798C08C00E45513 /* LecturesView.swift */; }; - 979DC0032798C08C00E45513 /* LectureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFBE2798C08C00E45513 /* LectureView.swift */; }; - 979DC0042798C08C00E45513 /* LectureDetailsBasicInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFC02798C08C00E45513 /* LectureDetailsBasicInfoView.swift */; }; - 979DC0052798C08C00E45513 /* LectureDetailsTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFC12798C08C00E45513 /* LectureDetailsTitleView.swift */; }; - 979DC0062798C08C00E45513 /* LectureDetailsDetailedInfoRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFC22798C08C00E45513 /* LectureDetailsDetailedInfoRowView.swift */; }; - 979DC0072798C08C00E45513 /* LectureDetailsDetailedInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFC32798C08C00E45513 /* LectureDetailsDetailedInfoView.swift */; }; - 979DC0082798C08C00E45513 /* LectureDetailsBasicInfoRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFC42798C08C00E45513 /* LectureDetailsBasicInfoRowView.swift */; }; - 979DC0092798C08C00E45513 /* LectureDetailsLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFC52798C08C00E45513 /* LectureDetailsLinkView.swift */; }; - 979DC00A2798C08C00E45513 /* LecturesDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFC62798C08C00E45513 /* LecturesDetailView.swift */; }; - 979DC00B2798C08C00E45513 /* EatAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFC92798C08C00E45513 /* EatAPI.swift */; }; - 979DC00C2798C08C00E45513 /* MVGAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFCA2798C08C00E45513 /* MVGAPI.swift */; }; - 979DC00D2798C08C00E45513 /* NetworkingAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFCB2798C08C00E45513 /* NetworkingAPI.swift */; }; - 979DC00E2798C08C00E45513 /* CampusOnlineAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFCC2798C08C00E45513 /* CampusOnlineAPI.swift */; }; - 979DC00F2798C08C00E45513 /* APIResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFCD2798C08C00E45513 /* APIResponse.swift */; }; - 979DC0102798C08C00E45513 /* TUMOnlineAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFCE2798C08C00E45513 /* TUMOnlineAPI.swift */; }; - 979DC0112798C08C00E45513 /* Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFCF2798C08C00E45513 /* Cache.swift */; }; - 979DC0122798C08C00E45513 /* TUMCabeAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFD02798C08C00E45513 /* TUMCabeAPI.swift */; }; - 979DC0132798C08C00E45513 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFD22798C08C00E45513 /* Constants.swift */; }; - 979DC0142798C08C00E45513 /* APIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFD32798C08C00E45513 /* APIConstants.swift */; }; - 979DC0172798C08C00E45513 /* NetworkingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFD82798C08C00E45513 /* NetworkingError.swift */; }; - 979DC0182798C08C00E45513 /* BackendError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFD92798C08C00E45513 /* BackendError.swift */; }; - 979DC0192798C08C00E45513 /* View+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFDA2798C08C00E45513 /* View+Error.swift */; }; - 979DC01A2798C08C00E45513 /* ErrorEmittingViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFDB2798C08C00E45513 /* ErrorEmittingViewModifier.swift */; }; - 979DC01B2798C08C00E45513 /* AlertErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFDC2798C08C00E45513 /* AlertErrorHandler.swift */; }; - 979DC01C2798C08C00E45513 /* ErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFDD2798C08C00E45513 /* ErrorHandler.swift */; }; - 979DC01D2798C08C00E45513 /* Environment+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFDE2798C08C00E45513 /* Environment+Error.swift */; }; - 979DC01E2798C08C00E45513 /* ErrorCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFDF2798C08C00E45513 /* ErrorCategory.swift */; }; - 979DC01F2798C08C00E45513 /* Error+Category.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFE02798C08C00E45513 /* Error+Category.swift */; }; - 979DC0202798C08C00E45513 /* FailedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFE22798C08C00E45513 /* FailedView.swift */; }; - 979DC0212798C08C00E45513 /* GroupBoxLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFE32798C08C00E45513 /* GroupBoxLabelView.swift */; }; - 979DC0222798C08C00E45513 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFE42798C08C00E45513 /* LoadingView.swift */; }; - 979DC0232798C08C00E45513 /* XMLSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFE62798C08C00E45513 /* XMLSerializer.swift */; }; - 979DC0242798C08C00E45513 /* GradeColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFE92798C08C00E45513 /* GradeColor.swift */; }; - 979DC0252798C08C00E45513 /* GradesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFEA2798C08C00E45513 /* GradesViewModel.swift */; }; - 979DC0262798C08C00E45513 /* GradesViewModel+ChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFEB2798C08C00E45513 /* GradesViewModel+ChartData.swift */; }; - 979DC0272798C08C00E45513 /* GradesViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFEC2798C08C00E45513 /* GradesViewModel+State.swift */; }; - 979DC0282798C08C00E45513 /* GradesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFEE2798C08C00E45513 /* GradesScreen.swift */; }; - 979DC0292798C08C00E45513 /* Grade.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFF02798C08C00E45513 /* Grade.swift */; }; - 979DC02A2798C08C00E45513 /* Modus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFF12798C08C00E45513 /* Modus.swift */; }; - 979DC02B2798C08C00E45513 /* GradesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFF32798C08C00E45513 /* GradesService.swift */; }; - 979DC02C2798C08C00E45513 /* GradesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFF52798C08C00E45513 /* GradesView.swift */; }; - 979DC02D2798C08C00E45513 /* GradeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFF62798C08C00E45513 /* GradeView.swift */; }; - 979DC02E2798C08C00E45513 /* BarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979DBFF72798C08C00E45513 /* BarChartView.swift */; }; + 97997AED27723C510079F809 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97997AEC27723C510079F809 /* LoadingView.swift */; }; 97C9AB1227732A200097B10C /* SwiftUICharts in Frameworks */ = {isa = PBXBuildFile; productRef = 97C9AB1127732A200097B10C /* SwiftUICharts */; }; + 97C9AB15277330B00097B10C /* ErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C9AB14277330B00097B10C /* ErrorHandler.swift */; }; + 97C9AB17277331510097B10C /* AlertErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C9AB16277331510097B10C /* AlertErrorHandler.swift */; }; + 97C9AB19277332710097B10C /* Error+Category.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C9AB18277332710097B10C /* Error+Category.swift */; }; + 97C9AB1C277332830097B10C /* ErrorCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C9AB1B277332830097B10C /* ErrorCategory.swift */; }; + 97C9AB1E277332BF0097B10C /* NetworkingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C9AB1D277332BF0097B10C /* NetworkingError.swift */; }; + 97C9AB20277333040097B10C /* Environment+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C9AB1F277333040097B10C /* Environment+Error.swift */; }; + 97C9AB22277333160097B10C /* View+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C9AB21277333160097B10C /* View+Error.swift */; }; + 97C9AB24277333320097B10C /* ErrorEmittingViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C9AB23277333320097B10C /* ErrorEmittingViewModifier.swift */; }; + 97C9AB27277358B20097B10C /* CampusOnlineAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C9AB26277358B20097B10C /* CampusOnlineAPI.swift */; }; + 97C9AB29277359AE0097B10C /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C9AB28277359AE0097B10C /* Constants.swift */; }; + 97C9AB2B27735AE70097B10C /* NetworkingAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C9AB2A27735AE70097B10C /* NetworkingAPI.swift */; }; + 97C9AB2D27736FE00097B10C /* APIResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C9AB2C27736FE00097B10C /* APIResponse.swift */; }; + 97E7B11027729A7F00D64EDF /* GradeColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97E7B10F27729A7F00D64EDF /* GradeColor.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -132,6 +137,10 @@ /* Begin PBXFileReference section */ 100803452764E2C50013ED0E /* ProfileToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileToolbar.swift; sourceTree = ""; }; 100803472764E37A0013ED0E /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; + 226CB5162798BD910043ABCA /* MenuViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuViewModel.swift; sourceTree = ""; }; + 226CB5182798BF3E0043ABCA /* MealPlanViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MealPlanViewModel.swift; sourceTree = ""; }; + 226CB51A2798DA050043ABCA /* PanelRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelRow.swift; sourceTree = ""; }; + 226CB51F2798E34E0043ABCA /* Panel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Panel.swift; sourceTree = ""; }; 227FBB492762AC440062FEC3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 227FBB4A2762AC4C0062FEC3 /* Campus-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Campus-iOS.entitlements"; sourceTree = ""; }; 3616C4AD278F6EF2000A1BC9 /* MealPlan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MealPlan.swift; sourceTree = ""; }; @@ -140,9 +149,9 @@ 3616C4B0278F6EF2000A1BC9 /* Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Menu.swift; sourceTree = ""; }; 3616C4B2278F6EF2000A1BC9 /* MealPlanView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MealPlanView.swift; sourceTree = ""; }; 3616C4B4278F6EF2000A1BC9 /* MapView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapView.swift; sourceTree = ""; }; - 3616C4B5278F6EF2000A1BC9 /* Panel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Panel.swift; sourceTree = ""; }; 3616C4B6278F6EF2000A1BC9 /* MapContent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapContent.swift; sourceTree = ""; }; 3616C4B7278F6EF2000A1BC9 /* PanelContent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PanelContent.swift; sourceTree = ""; }; + 3616C4C1278F6F23000A1BC9 /* EatAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EatAPI.swift; sourceTree = ""; }; 3616C4C3278F9C0A000A1BC9 /* SheetNavigator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetNavigator.swift; sourceTree = ""; }; 3616C4C6278FA2D3000A1BC9 /* Enums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Enums.swift; sourceTree = ""; }; 36203E7E2761B9D000C24658 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = "Campus-iOS/Base.lproj/Localizable.strings"; sourceTree = ""; }; @@ -171,64 +180,64 @@ 36E964A6277498540055777F /* CalendarContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarContentView.swift; sourceTree = ""; }; 36E964AB277499860055777F /* CalendarDisplayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarDisplayView.swift; sourceTree = ""; }; 36FAE364277472EF00628799 /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = ""; }; + 36FF905D2773BB5800F4C785 /* MVGAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MVGAPI.swift; sourceTree = ""; }; + 36FF905E2773BB5800F4C785 /* TUMOnlineAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TUMOnlineAPI.swift; sourceTree = ""; }; + 36FF905F2773BB5800F4C785 /* TUMCabeAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TUMCabeAPI.swift; sourceTree = ""; }; 36FF90642773BB8100F4C785 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; + 36FF906A2773BE3000F4C785 /* BackendError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackendError.swift; sourceTree = ""; }; + 36FF906B2773BE3000F4C785 /* XMLSerializer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XMLSerializer.swift; sourceTree = ""; }; 36FF906E2773BE8100F4C785 /* AuthenticationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticationHandler.swift; sourceTree = ""; }; + 4146FE88279D52DC00655D1A /* Toolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toolbar.swift; sourceTree = ""; }; 41BD20E1279228B8001FA1B0 /* DishLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DishLabel.swift; sourceTree = ""; }; 41BD20E3279228E2001FA1B0 /* MensaEnumService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MensaEnumService.swift; sourceTree = ""; }; + 41D55D7127A2F06800DE7155 /* Cache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cache.swift; sourceTree = ""; }; + 41D55D7327A2F0CA00DE7155 /* Modus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Modus.swift; sourceTree = ""; }; + 41D55D7827A2F17300DE7155 /* LectureDetailsViewModel+State.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "LectureDetailsViewModel+State.swift"; sourceTree = ""; }; + 41D55D7927A2F17300DE7155 /* LectureDetailsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsViewModel.swift; sourceTree = ""; }; + 41D55D7A27A2F17300DE7155 /* LecturesViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LecturesViewModel.swift; sourceTree = ""; }; + 41D55D7B27A2F17300DE7155 /* LecturesViewModel+State.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "LecturesViewModel+State.swift"; sourceTree = ""; }; + 41D55D8127A2F20300DE7155 /* LecturesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LecturesView.swift; sourceTree = ""; }; + 41D55D8227A2F20300DE7155 /* LectureView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureView.swift; sourceTree = ""; }; + 41D55D8427A2F20300DE7155 /* LectureDetailsBasicInfoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsBasicInfoView.swift; sourceTree = ""; }; + 41D55D8527A2F20300DE7155 /* LectureDetailsTitleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsTitleView.swift; sourceTree = ""; }; + 41D55D8627A2F20300DE7155 /* LectureDetailsDetailedInfoRowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsDetailedInfoRowView.swift; sourceTree = ""; }; + 41D55D8727A2F20300DE7155 /* LectureDetailsDetailedInfoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsDetailedInfoView.swift; sourceTree = ""; }; + 41D55D8827A2F20300DE7155 /* LectureDetailsBasicInfoRowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsBasicInfoRowView.swift; sourceTree = ""; }; + 41D55D8927A2F20300DE7155 /* LectureDetailsLinkView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsLinkView.swift; sourceTree = ""; }; + 41D55D8A27A2F20300DE7155 /* LecturesDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LecturesDetailView.swift; sourceTree = ""; }; + 41D55D9427A2F23700DE7155 /* FailedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FailedView.swift; sourceTree = ""; }; + 41D55D9527A2F23700DE7155 /* GroupBoxLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupBoxLabelView.swift; sourceTree = ""; }; + 41D55D9827A2F28400DE7155 /* LectureDetails.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetails.swift; sourceTree = ""; }; + 41D55D9A27A2F2B100DE7155 /* LectureDetailsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsService.swift; sourceTree = ""; }; + 41D55D9C27A2F32800DE7155 /* GradesViewModel+ChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GradesViewModel+ChartData.swift"; sourceTree = ""; }; + 41D55D9D27A2F32800DE7155 /* GradesViewModel+State.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GradesViewModel+State.swift"; sourceTree = ""; }; + 41D55DA027A2F34700DE7155 /* BarChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarChartView.swift; sourceTree = ""; }; + 41D55DA127A2F34700DE7155 /* GradesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradesView.swift; sourceTree = ""; }; + 41D55DA427A2F38300DE7155 /* LectureDetailsScreen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsScreen.swift; sourceTree = ""; }; 41DDB33A2792F70A00FBEC81 /* MenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuView.swift; sourceTree = ""; }; - 979DBFAF2798C08C00E45513 /* LectureDetailsViewModel+State.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "LectureDetailsViewModel+State.swift"; sourceTree = ""; }; - 979DBFB02798C08C00E45513 /* LectureDetailsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsViewModel.swift; sourceTree = ""; }; - 979DBFB12798C08C00E45513 /* LecturesViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LecturesViewModel.swift; sourceTree = ""; }; - 979DBFB22798C08C00E45513 /* LecturesViewModel+State.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "LecturesViewModel+State.swift"; sourceTree = ""; }; - 979DBFB42798C08C00E45513 /* LectureDetailsScreen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsScreen.swift; sourceTree = ""; }; - 979DBFB52798C08C00E45513 /* LecturesScreen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LecturesScreen.swift; sourceTree = ""; }; - 979DBFB72798C08C00E45513 /* LectureDetails.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetails.swift; sourceTree = ""; }; - 979DBFB82798C08C00E45513 /* Lecture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lecture.swift; sourceTree = ""; }; - 979DBFBA2798C08C00E45513 /* LecturesService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LecturesService.swift; sourceTree = ""; }; - 979DBFBB2798C08C00E45513 /* LectureDetailsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsService.swift; sourceTree = ""; }; - 979DBFBD2798C08C00E45513 /* LecturesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LecturesView.swift; sourceTree = ""; }; - 979DBFBE2798C08C00E45513 /* LectureView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureView.swift; sourceTree = ""; }; - 979DBFC02798C08C00E45513 /* LectureDetailsBasicInfoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsBasicInfoView.swift; sourceTree = ""; }; - 979DBFC12798C08C00E45513 /* LectureDetailsTitleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsTitleView.swift; sourceTree = ""; }; - 979DBFC22798C08C00E45513 /* LectureDetailsDetailedInfoRowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsDetailedInfoRowView.swift; sourceTree = ""; }; - 979DBFC32798C08C00E45513 /* LectureDetailsDetailedInfoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsDetailedInfoView.swift; sourceTree = ""; }; - 979DBFC42798C08C00E45513 /* LectureDetailsBasicInfoRowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsBasicInfoRowView.swift; sourceTree = ""; }; - 979DBFC52798C08C00E45513 /* LectureDetailsLinkView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LectureDetailsLinkView.swift; sourceTree = ""; }; - 979DBFC62798C08C00E45513 /* LecturesDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LecturesDetailView.swift; sourceTree = ""; }; - 979DBFC92798C08C00E45513 /* EatAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EatAPI.swift; sourceTree = ""; }; - 979DBFCA2798C08C00E45513 /* MVGAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MVGAPI.swift; sourceTree = ""; }; - 979DBFCB2798C08C00E45513 /* NetworkingAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkingAPI.swift; sourceTree = ""; }; - 979DBFCC2798C08C00E45513 /* CampusOnlineAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CampusOnlineAPI.swift; sourceTree = ""; }; - 979DBFCD2798C08C00E45513 /* APIResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIResponse.swift; sourceTree = ""; }; - 979DBFCE2798C08C00E45513 /* TUMOnlineAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TUMOnlineAPI.swift; sourceTree = ""; }; - 979DBFCF2798C08C00E45513 /* Cache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cache.swift; sourceTree = ""; }; - 979DBFD02798C08C00E45513 /* TUMCabeAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TUMCabeAPI.swift; sourceTree = ""; }; - 979DBFD22798C08C00E45513 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; - 979DBFD32798C08C00E45513 /* APIConstants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIConstants.swift; sourceTree = ""; }; - 979DBFD82798C08C00E45513 /* NetworkingError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkingError.swift; sourceTree = ""; }; - 979DBFD92798C08C00E45513 /* BackendError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackendError.swift; sourceTree = ""; }; - 979DBFDA2798C08C00E45513 /* View+Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+Error.swift"; sourceTree = ""; }; - 979DBFDB2798C08C00E45513 /* ErrorEmittingViewModifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorEmittingViewModifier.swift; sourceTree = ""; }; - 979DBFDC2798C08C00E45513 /* AlertErrorHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertErrorHandler.swift; sourceTree = ""; }; - 979DBFDD2798C08C00E45513 /* ErrorHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorHandler.swift; sourceTree = ""; }; - 979DBFDE2798C08C00E45513 /* Environment+Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Environment+Error.swift"; sourceTree = ""; }; - 979DBFDF2798C08C00E45513 /* ErrorCategory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorCategory.swift; sourceTree = ""; }; - 979DBFE02798C08C00E45513 /* Error+Category.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Error+Category.swift"; sourceTree = ""; }; - 979DBFE22798C08C00E45513 /* FailedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FailedView.swift; sourceTree = ""; }; - 979DBFE32798C08C00E45513 /* GroupBoxLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupBoxLabelView.swift; sourceTree = ""; }; - 979DBFE42798C08C00E45513 /* LoadingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = ""; }; - 979DBFE62798C08C00E45513 /* XMLSerializer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XMLSerializer.swift; sourceTree = ""; }; - 979DBFE92798C08C00E45513 /* GradeColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradeColor.swift; sourceTree = ""; }; - 979DBFEA2798C08C00E45513 /* GradesViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradesViewModel.swift; sourceTree = ""; }; - 979DBFEB2798C08C00E45513 /* GradesViewModel+ChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GradesViewModel+ChartData.swift"; sourceTree = ""; }; - 979DBFEC2798C08C00E45513 /* GradesViewModel+State.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GradesViewModel+State.swift"; sourceTree = ""; }; - 979DBFEE2798C08C00E45513 /* GradesScreen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradesScreen.swift; sourceTree = ""; }; - 979DBFF02798C08C00E45513 /* Grade.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Grade.swift; sourceTree = ""; }; - 979DBFF12798C08C00E45513 /* Modus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Modus.swift; sourceTree = ""; }; - 979DBFF32798C08C00E45513 /* GradesService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradesService.swift; sourceTree = ""; }; - 979DBFF52798C08C00E45513 /* GradesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradesView.swift; sourceTree = ""; }; - 979DBFF62798C08C00E45513 /* GradeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradeView.swift; sourceTree = ""; }; - 979DBFF72798C08C00E45513 /* BarChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarChartView.swift; sourceTree = ""; }; + 972397402772825D004BF7AB /* Lecture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lecture.swift; sourceTree = ""; }; + 9723974227728268004BF7AB /* LecturesScreen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LecturesScreen.swift; sourceTree = ""; }; + 972397442772826E004BF7AB /* LecturesService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LecturesService.swift; sourceTree = ""; }; + 97997AD12772179D0079F809 /* APIConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIConstants.swift; sourceTree = ""; }; + 97997AD4277222730079F809 /* Grade.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Grade.swift; sourceTree = ""; }; + 97997AD72772265D0079F809 /* GradesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradesScreen.swift; sourceTree = ""; }; + 97997AD927722A0A0079F809 /* GradeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradeView.swift; sourceTree = ""; }; + 97997ADD27722B470079F809 /* GradesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradesService.swift; sourceTree = ""; }; + 97997AE327722E3B0079F809 /* GradesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradesViewModel.swift; sourceTree = ""; }; + 97997AEC27723C510079F809 /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = ""; }; + 97C9AB14277330B00097B10C /* ErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorHandler.swift; sourceTree = ""; }; + 97C9AB16277331510097B10C /* AlertErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertErrorHandler.swift; sourceTree = ""; }; + 97C9AB18277332710097B10C /* Error+Category.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Error+Category.swift"; sourceTree = ""; }; + 97C9AB1B277332830097B10C /* ErrorCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorCategory.swift; sourceTree = ""; }; + 97C9AB1D277332BF0097B10C /* NetworkingError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkingError.swift; sourceTree = ""; }; + 97C9AB1F277333040097B10C /* Environment+Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Environment+Error.swift"; sourceTree = ""; }; + 97C9AB21277333160097B10C /* View+Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Error.swift"; sourceTree = ""; }; + 97C9AB23277333320097B10C /* ErrorEmittingViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorEmittingViewModifier.swift; sourceTree = ""; }; + 97C9AB26277358B20097B10C /* CampusOnlineAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CampusOnlineAPI.swift; sourceTree = ""; }; + 97C9AB28277359AE0097B10C /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; + 97C9AB2A27735AE70097B10C /* NetworkingAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkingAPI.swift; sourceTree = ""; }; + 97C9AB2C27736FE00097B10C /* APIResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIResponse.swift; sourceTree = ""; }; + 97E7B10F27729A7F00D64EDF /* GradeColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradeColor.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -236,8 +245,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 226CB51E2798DF9C0043ABCA /* Snap in Frameworks */, + 41D55D6E27A2EFB200DE7155 /* LRUCache in Frameworks */, 97997AE7277234120079F809 /* XMLCoder in Frameworks */, - 979DBFAC2798C00C00E45513 /* LRUCache in Frameworks */, 97C9AB1227732A200097B10C /* SwiftUICharts in Frameworks */, 36E964AA277498B60055777F /* KVKCalendar in Frameworks */, 36FF90722773BFC300F4C785 /* FirebaseAnalytics in Frameworks */, @@ -301,7 +311,9 @@ 3616C4B1278F6EF2000A1BC9 /* Cafeterias */ = { isa = PBXGroup; children = ( + 226CB5182798BF3E0043ABCA /* MealPlanViewModel.swift */, 3616C4B2278F6EF2000A1BC9 /* MealPlanView.swift */, + 226CB5162798BD910043ABCA /* MenuViewModel.swift */, 41DDB33A2792F70A00FBEC81 /* MenuView.swift */, ); path = Cafeterias; @@ -312,8 +324,10 @@ children = ( 3616C4B4278F6EF2000A1BC9 /* MapView.swift */, 3616C4B6278F6EF2000A1BC9 /* MapContent.swift */, - 3616C4B5278F6EF2000A1BC9 /* Panel.swift */, + 226CB51F2798E34E0043ABCA /* Panel.swift */, 3616C4B7278F6EF2000A1BC9 /* PanelContent.swift */, + 226CB51A2798DA050043ABCA /* PanelRow.swift */, + 4146FE88279D52DC00655D1A /* Toolbar.swift */, ); path = MainView; sourceTree = ""; @@ -359,13 +373,13 @@ 366F0E8227580CFB0091651D /* Campus-iOS */ = { isa = PBXGroup; children = ( - 979DBFC72798C08C00E45513 /* Base */, - 979DBFE72798C08C00E45513 /* GradesComponent */, - 979DBFAD2798C08C00E45513 /* LectureComponent */, 3616C4C5278FA2B9000A1BC9 /* Enums */, 3616C4AB278F6EF2000A1BC9 /* Map */, 36E9649E277492AE0055777F /* CalendarComponent */, 36FF90632773BB8100F4C785 /* Extensions */, + 9723973A27728224004BF7AB /* LectureComponent */, + 97997AEA27723C340079F809 /* Base */, + 97997ACF2772176A0079F809 /* GradesComponent */, 100803442764E2A90013ED0E /* ProfileComponent */, 227FBB4A2762AC4C0062FEC3 /* Campus-iOS.entitlements */, 227FBB492762AC440062FEC3 /* Info.plist */, @@ -496,206 +510,206 @@ path = Extensions; sourceTree = ""; }; - 979DBFAD2798C08C00E45513 /* LectureComponent */ = { + 36FF90692773BE3000F4C785 /* Helpers */ = { isa = PBXGroup; children = ( - 979DBFAE2798C08C00E45513 /* ViewModel */, - 979DBFB32798C08C00E45513 /* Screen */, - 979DBFB62798C08C00E45513 /* Model */, - 979DBFB92798C08C00E45513 /* Service */, - 979DBFBC2798C08C00E45513 /* Views */, + 36FF906B2773BE3000F4C785 /* XMLSerializer.swift */, ); - path = LectureComponent; + path = Helpers; sourceTree = ""; }; - 979DBFAE2798C08C00E45513 /* ViewModel */ = { + 41D55D8327A2F20300DE7155 /* LectureDetailsViews */ = { isa = PBXGroup; children = ( - 979DBFAF2798C08C00E45513 /* LectureDetailsViewModel+State.swift */, - 979DBFB02798C08C00E45513 /* LectureDetailsViewModel.swift */, - 979DBFB12798C08C00E45513 /* LecturesViewModel.swift */, - 979DBFB22798C08C00E45513 /* LecturesViewModel+State.swift */, + 41D55D8427A2F20300DE7155 /* LectureDetailsBasicInfoView.swift */, + 41D55D8527A2F20300DE7155 /* LectureDetailsTitleView.swift */, + 41D55D8627A2F20300DE7155 /* LectureDetailsDetailedInfoRowView.swift */, + 41D55D8727A2F20300DE7155 /* LectureDetailsDetailedInfoView.swift */, + 41D55D8827A2F20300DE7155 /* LectureDetailsBasicInfoRowView.swift */, + 41D55D8927A2F20300DE7155 /* LectureDetailsLinkView.swift */, ); - path = ViewModel; + path = LectureDetailsViews; sourceTree = ""; }; - 979DBFB32798C08C00E45513 /* Screen */ = { + 9723973A27728224004BF7AB /* LectureComponent */ = { isa = PBXGroup; children = ( - 979DBFB42798C08C00E45513 /* LectureDetailsScreen.swift */, - 979DBFB52798C08C00E45513 /* LecturesScreen.swift */, + 9723973F2772824F004BF7AB /* Views */, + 9723973E27728248004BF7AB /* ViewModel */, + 9723973D27728243004BF7AB /* Service */, + 9723973C2772823E004BF7AB /* Screen */, + 9723973B27728239004BF7AB /* Model */, ); - path = Screen; + path = LectureComponent; sourceTree = ""; }; - 979DBFB62798C08C00E45513 /* Model */ = { + 9723973B27728239004BF7AB /* Model */ = { isa = PBXGroup; children = ( - 979DBFB72798C08C00E45513 /* LectureDetails.swift */, - 979DBFB82798C08C00E45513 /* Lecture.swift */, + 41D55D9827A2F28400DE7155 /* LectureDetails.swift */, + 972397402772825D004BF7AB /* Lecture.swift */, ); path = Model; sourceTree = ""; }; - 979DBFB92798C08C00E45513 /* Service */ = { + 9723973C2772823E004BF7AB /* Screen */ = { isa = PBXGroup; children = ( - 979DBFBA2798C08C00E45513 /* LecturesService.swift */, - 979DBFBB2798C08C00E45513 /* LectureDetailsService.swift */, + 41D55DA427A2F38300DE7155 /* LectureDetailsScreen.swift */, + 9723974227728268004BF7AB /* LecturesScreen.swift */, ); - path = Service; + path = Screen; sourceTree = ""; }; - 979DBFBC2798C08C00E45513 /* Views */ = { + 9723973D27728243004BF7AB /* Service */ = { isa = PBXGroup; children = ( - 979DBFBD2798C08C00E45513 /* LecturesView.swift */, - 979DBFBE2798C08C00E45513 /* LectureView.swift */, - 979DBFBF2798C08C00E45513 /* LectureDetailsViews */, - 979DBFC62798C08C00E45513 /* LecturesDetailView.swift */, + 41D55D9A27A2F2B100DE7155 /* LectureDetailsService.swift */, + 972397442772826E004BF7AB /* LecturesService.swift */, ); - path = Views; + path = Service; sourceTree = ""; }; - 979DBFBF2798C08C00E45513 /* LectureDetailsViews */ = { + 9723973E27728248004BF7AB /* ViewModel */ = { isa = PBXGroup; children = ( - 979DBFC02798C08C00E45513 /* LectureDetailsBasicInfoView.swift */, - 979DBFC12798C08C00E45513 /* LectureDetailsTitleView.swift */, - 979DBFC22798C08C00E45513 /* LectureDetailsDetailedInfoRowView.swift */, - 979DBFC32798C08C00E45513 /* LectureDetailsDetailedInfoView.swift */, - 979DBFC42798C08C00E45513 /* LectureDetailsBasicInfoRowView.swift */, - 979DBFC52798C08C00E45513 /* LectureDetailsLinkView.swift */, + 41D55D7827A2F17300DE7155 /* LectureDetailsViewModel+State.swift */, + 41D55D7927A2F17300DE7155 /* LectureDetailsViewModel.swift */, + 41D55D7A27A2F17300DE7155 /* LecturesViewModel.swift */, + 41D55D7B27A2F17300DE7155 /* LecturesViewModel+State.swift */, ); - path = LectureDetailsViews; + path = ViewModel; sourceTree = ""; }; - 979DBFC72798C08C00E45513 /* Base */ = { + 9723973F2772824F004BF7AB /* Views */ = { isa = PBXGroup; children = ( - 979DBFC82798C08C00E45513 /* Networking */, - 979DBFD12798C08C00E45513 /* Constants */, - 979DBFD72798C08C00E45513 /* Errors */, - 979DBFE12798C08C00E45513 /* Views */, - 979DBFE52798C08C00E45513 /* Helpers */, + 41D55D8127A2F20300DE7155 /* LecturesView.swift */, + 41D55D8227A2F20300DE7155 /* LectureView.swift */, + 41D55D8327A2F20300DE7155 /* LectureDetailsViews */, + 41D55D8A27A2F20300DE7155 /* LecturesDetailView.swift */, ); - path = Base; + path = Views; sourceTree = ""; }; - 979DBFC82798C08C00E45513 /* Networking */ = { + 97997ACF2772176A0079F809 /* GradesComponent */ = { isa = PBXGroup; children = ( - 979DBFC92798C08C00E45513 /* EatAPI.swift */, - 979DBFCA2798C08C00E45513 /* MVGAPI.swift */, - 979DBFCB2798C08C00E45513 /* NetworkingAPI.swift */, - 979DBFCC2798C08C00E45513 /* CampusOnlineAPI.swift */, - 979DBFCD2798C08C00E45513 /* APIResponse.swift */, - 979DBFCE2798C08C00E45513 /* TUMOnlineAPI.swift */, - 979DBFCF2798C08C00E45513 /* Cache.swift */, - 979DBFD02798C08C00E45513 /* TUMCabeAPI.swift */, + 97997AE227722E1A0079F809 /* ViewModel */, + 97997ADC27722B160079F809 /* Service */, + 97997ADB27722B0D0079F809 /* Views */, + 97997AD62772264E0079F809 /* Screen */, + 97997AD32772180F0079F809 /* Model */, ); - path = Networking; + path = GradesComponent; sourceTree = ""; }; - 979DBFD12798C08C00E45513 /* Constants */ = { + 97997AD02772178D0079F809 /* Constants */ = { isa = PBXGroup; children = ( - 979DBFD22798C08C00E45513 /* Constants.swift */, - 979DBFD32798C08C00E45513 /* APIConstants.swift */, + 97997AD12772179D0079F809 /* APIConstants.swift */, + 97C9AB28277359AE0097B10C /* Constants.swift */, ); path = Constants; sourceTree = ""; }; - 979DBFD72798C08C00E45513 /* Errors */ = { + 97997AD32772180F0079F809 /* Model */ = { isa = PBXGroup; children = ( - 979DBFD82798C08C00E45513 /* NetworkingError.swift */, - 979DBFD92798C08C00E45513 /* BackendError.swift */, - 979DBFDA2798C08C00E45513 /* View+Error.swift */, - 979DBFDB2798C08C00E45513 /* ErrorEmittingViewModifier.swift */, - 979DBFDC2798C08C00E45513 /* AlertErrorHandler.swift */, - 979DBFDD2798C08C00E45513 /* ErrorHandler.swift */, - 979DBFDE2798C08C00E45513 /* Environment+Error.swift */, - 979DBFDF2798C08C00E45513 /* ErrorCategory.swift */, - 979DBFE02798C08C00E45513 /* Error+Category.swift */, + 41D55D7327A2F0CA00DE7155 /* Modus.swift */, + 97997AD4277222730079F809 /* Grade.swift */, ); - path = Errors; + path = Model; sourceTree = ""; }; - 979DBFE12798C08C00E45513 /* Views */ = { + 97997AD62772264E0079F809 /* Screen */ = { isa = PBXGroup; children = ( - 979DBFE22798C08C00E45513 /* FailedView.swift */, - 979DBFE32798C08C00E45513 /* GroupBoxLabelView.swift */, - 979DBFE42798C08C00E45513 /* LoadingView.swift */, + 97997AD72772265D0079F809 /* GradesScreen.swift */, ); - path = Views; + path = Screen; sourceTree = ""; }; - 979DBFE52798C08C00E45513 /* Helpers */ = { + 97997ADB27722B0D0079F809 /* Views */ = { isa = PBXGroup; children = ( - 979DBFE62798C08C00E45513 /* XMLSerializer.swift */, + 41D55DA027A2F34700DE7155 /* BarChartView.swift */, + 41D55DA127A2F34700DE7155 /* GradesView.swift */, + 97997AD927722A0A0079F809 /* GradeView.swift */, ); - path = Helpers; + path = Views; sourceTree = ""; }; - 979DBFE72798C08C00E45513 /* GradesComponent */ = { + 97997ADC27722B160079F809 /* Service */ = { isa = PBXGroup; children = ( - 979DBFE82798C08C00E45513 /* ViewModel */, - 979DBFED2798C08C00E45513 /* Screen */, - 979DBFEF2798C08C00E45513 /* Model */, - 979DBFF22798C08C00E45513 /* Service */, - 979DBFF42798C08C00E45513 /* Views */, + 97997ADD27722B470079F809 /* GradesService.swift */, ); - path = GradesComponent; + path = Service; sourceTree = ""; }; - 979DBFE82798C08C00E45513 /* ViewModel */ = { + 97997AE227722E1A0079F809 /* ViewModel */ = { isa = PBXGroup; children = ( - 979DBFE92798C08C00E45513 /* GradeColor.swift */, - 979DBFEA2798C08C00E45513 /* GradesViewModel.swift */, - 979DBFEB2798C08C00E45513 /* GradesViewModel+ChartData.swift */, - 979DBFEC2798C08C00E45513 /* GradesViewModel+State.swift */, + 41D55D9C27A2F32800DE7155 /* GradesViewModel+ChartData.swift */, + 41D55D9D27A2F32800DE7155 /* GradesViewModel+State.swift */, + 97997AE327722E3B0079F809 /* GradesViewModel.swift */, + 97E7B10F27729A7F00D64EDF /* GradeColor.swift */, ); path = ViewModel; sourceTree = ""; }; - 979DBFED2798C08C00E45513 /* Screen */ = { + 97997AEA27723C340079F809 /* Base */ = { isa = PBXGroup; children = ( - 979DBFEE2798C08C00E45513 /* GradesScreen.swift */, + 36FF90692773BE3000F4C785 /* Helpers */, + 97C9AB252773587D0097B10C /* Networking */, + 97C9AB13277330A00097B10C /* Errors */, + 97997AEB27723C460079F809 /* Views */, + 97997AD02772178D0079F809 /* Constants */, ); - path = Screen; + path = Base; sourceTree = ""; }; - 979DBFEF2798C08C00E45513 /* Model */ = { + 97997AEB27723C460079F809 /* Views */ = { isa = PBXGroup; children = ( - 979DBFF02798C08C00E45513 /* Grade.swift */, - 979DBFF12798C08C00E45513 /* Modus.swift */, + 41D55D9427A2F23700DE7155 /* FailedView.swift */, + 41D55D9527A2F23700DE7155 /* GroupBoxLabelView.swift */, + 97997AEC27723C510079F809 /* LoadingView.swift */, ); - path = Model; + path = Views; sourceTree = ""; }; - 979DBFF22798C08C00E45513 /* Service */ = { + 97C9AB13277330A00097B10C /* Errors */ = { isa = PBXGroup; children = ( - 979DBFF32798C08C00E45513 /* GradesService.swift */, + 36FF906A2773BE3000F4C785 /* BackendError.swift */, + 97C9AB14277330B00097B10C /* ErrorHandler.swift */, + 97C9AB16277331510097B10C /* AlertErrorHandler.swift */, + 97C9AB18277332710097B10C /* Error+Category.swift */, + 97C9AB1B277332830097B10C /* ErrorCategory.swift */, + 97C9AB1D277332BF0097B10C /* NetworkingError.swift */, + 97C9AB1F277333040097B10C /* Environment+Error.swift */, + 97C9AB21277333160097B10C /* View+Error.swift */, + 97C9AB23277333320097B10C /* ErrorEmittingViewModifier.swift */, ); - path = Service; + path = Errors; sourceTree = ""; }; - 979DBFF42798C08C00E45513 /* Views */ = { + 97C9AB252773587D0097B10C /* Networking */ = { isa = PBXGroup; children = ( - 979DBFF52798C08C00E45513 /* GradesView.swift */, - 979DBFF62798C08C00E45513 /* GradeView.swift */, - 979DBFF72798C08C00E45513 /* BarChartView.swift */, + 41D55D7127A2F06800DE7155 /* Cache.swift */, + 3616C4C1278F6F23000A1BC9 /* EatAPI.swift */, + 36FF905D2773BB5800F4C785 /* MVGAPI.swift */, + 36FF905E2773BB5800F4C785 /* TUMOnlineAPI.swift */, + 36FF905F2773BB5800F4C785 /* TUMCabeAPI.swift */, + 97C9AB26277358B20097B10C /* CampusOnlineAPI.swift */, + 97C9AB2A27735AE70097B10C /* NetworkingAPI.swift */, + 97C9AB2C27736FE00097B10C /* APIResponse.swift */, ); - path = Views; + path = Networking; sourceTree = ""; }; /* End PBXGroup section */ @@ -724,7 +738,8 @@ 36FF90732773BFC300F4C785 /* FirebaseAnalyticsSwift-Beta */, 36FF90752773BFC300F4C785 /* FirebaseCrashlytics */, 36E964A9277498B60055777F /* KVKCalendar */, - 979DBFAB2798C00C00E45513 /* LRUCache */, + 226CB51D2798DF9C0043ABCA /* Snap */, + 41D55D6D27A2EFB200DE7155 /* LRUCache */, ); productName = "Campus-iOS"; productReference = 366F0E8027580CFB0091651D /* Campus-iOS.app */; @@ -807,7 +822,8 @@ 36FF90662773BCA600F4C785 /* XCRemoteSwiftPackageReference "SWXMLHash" */, 36FF90702773BFC300F4C785 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, 36E964A8277498B60055777F /* XCRemoteSwiftPackageReference "KVKCalendar" */, - 979DBFAA2798C00B00E45513 /* XCRemoteSwiftPackageReference "LRUCache" */, + 226CB51C2798DF9C0043ABCA /* XCRemoteSwiftPackageReference "Snap" */, + 41D55D6C27A2EFB200DE7155 /* XCRemoteSwiftPackageReference "LRUCache" */, ); productRefGroup = 366F0E8127580CFB0091651D /* Products */; projectDirPath = ""; @@ -852,93 +868,97 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 979DC00D2798C08C00E45513 /* NetworkingAPI.swift in Sources */, 41DDB33B2792F70A00FBEC81 /* MenuView.swift in Sources */, - 979DC0252798C08C00E45513 /* GradesViewModel.swift in Sources */, - 979DC00C2798C08C00E45513 /* MVGAPI.swift in Sources */, - 979DC0242798C08C00E45513 /* GradeColor.swift in Sources */, - 979DC02B2798C08C00E45513 /* GradesService.swift in Sources */, - 979DC0042798C08C00E45513 /* LectureDetailsBasicInfoView.swift in Sources */, - 979DC0082798C08C00E45513 /* LectureDetailsBasicInfoRowView.swift in Sources */, - 979DC0282798C08C00E45513 /* GradesScreen.swift in Sources */, 3683C3182758117900082930 /* Model.swift in Sources */, 366F0E8D27580CFD0091651D /* Persistence.swift in Sources */, + 41D55D7E27A2F17300DE7155 /* LecturesViewModel.swift in Sources */, + 41D55D7D27A2F17300DE7155 /* LectureDetailsViewModel.swift in Sources */, 36E964AC277499860055777F /* CalendarDisplayView.swift in Sources */, 36FAE365277472EF00628799 /* LoginViewModel.swift in Sources */, - 979DC0132798C08C00E45513 /* Constants.swift in Sources */, - 979DC0032798C08C00E45513 /* LectureView.swift in Sources */, + 3616C4C2278F6F23000A1BC9 /* EatAPI.swift in Sources */, 36E964A32774932B0055777F /* CalendarToolbar.swift in Sources */, - 979DBFFC2798C08C00E45513 /* LectureDetailsScreen.swift in Sources */, - 979DC0062798C08C00E45513 /* LectureDetailsDetailedInfoRowView.swift in Sources */, + 97997AD82772265D0079F809 /* GradesScreen.swift in Sources */, + 36FF90612773BB5800F4C785 /* TUMOnlineAPI.swift in Sources */, + 41D55D8C27A2F20300DE7155 /* LectureView.swift in Sources */, + 972397452772826E004BF7AB /* LecturesService.swift in Sources */, 36D0C8A32762075900A142CD /* TokenActivationTutorialView.swift in Sources */, - 979DC0272798C08C00E45513 /* GradesViewModel+State.swift in Sources */, + 97997ADE27722B470079F809 /* GradesService.swift in Sources */, + 97C9AB1E277332BF0097B10C /* NetworkingError.swift in Sources */, + 36FF90602773BB5800F4C785 /* MVGAPI.swift in Sources */, + 41D55D8E27A2F20300DE7155 /* LectureDetailsTitleView.swift in Sources */, 41BD20E4279228E2001FA1B0 /* MensaEnumService.swift in Sources */, - 979DC0002798C08C00E45513 /* LecturesService.swift in Sources */, - 979DC02C2798C08C00E45513 /* GradesView.swift in Sources */, 3616C4B8278F6EF2000A1BC9 /* MealPlan.swift in Sources */, - 979DC0212798C08C00E45513 /* GroupBoxLabelView.swift in Sources */, + 97C9AB22277333160097B10C /* View+Error.swift in Sources */, + 97C9AB19277332710097B10C /* Error+Category.swift in Sources */, 41BD20E2279228B8001FA1B0 /* DishLabel.swift in Sources */, - 979DBFF92798C08C00E45513 /* LectureDetailsViewModel.swift in Sources */, - 979DC0012798C08C00E45513 /* LectureDetailsService.swift in Sources */, 36203E8D2761C6EC00C24658 /* Credentials.swift in Sources */, + 97C9AB2B27735AE70097B10C /* NetworkingAPI.swift in Sources */, 3698CBED2761E014001C5735 /* CustomRoundedBorderTextFieldStyle.swift in Sources */, - 979DBFFD2798C08C00E45513 /* LecturesScreen.swift in Sources */, 3616C4BA278F6EF2000A1BC9 /* Cafeteria.swift in Sources */, + 41D55D9227A2F20300DE7155 /* LectureDetailsLinkView.swift in Sources */, 36203E8B2761C6EC00C24658 /* Spinner.swift in Sources */, + 4146FE89279D52DC00655D1A /* Toolbar.swift in Sources */, + 9723974327728268004BF7AB /* LecturesScreen.swift in Sources */, + 41D55D9327A2F20300DE7155 /* LecturesDetailView.swift in Sources */, 3616C4BF278F6EF2000A1BC9 /* MapContent.swift in Sources */, - 979DBFFF2798C08C00E45513 /* Lecture.swift in Sources */, 3616C4C0278F6EF2000A1BC9 /* PanelContent.swift in Sources */, - 3616C4BE278F6EF2000A1BC9 /* Panel.swift in Sources */, - 979DC0192798C08C00E45513 /* View+Error.swift in Sources */, + 97E7B11027729A7F00D64EDF /* GradeColor.swift in Sources */, 36E964A5277493D90055777F /* CalendarViewModel.swift in Sources */, - 979DBFFA2798C08C00E45513 /* LecturesViewModel.swift in Sources */, + 41D55D7F27A2F17300DE7155 /* LecturesViewModel+State.swift in Sources */, + 36FF90622773BB5800F4C785 /* TUMCabeAPI.swift in Sources */, + 97C9AB24277333320097B10C /* ErrorEmittingViewModifier.swift in Sources */, + 97C9AB29277359AE0097B10C /* Constants.swift in Sources */, + 41D55D7C27A2F17300DE7155 /* LectureDetailsViewModel+State.swift in Sources */, + 226CB5172798BD910043ABCA /* MenuViewModel.swift in Sources */, + 226CB5202798E34E0043ABCA /* Panel.swift in Sources */, 3616C4BB278F6EF2000A1BC9 /* Menu.swift in Sources */, - 979DBFF82798C08C00E45513 /* LectureDetailsViewModel+State.swift in Sources */, - 979DC00F2798C08C00E45513 /* APIResponse.swift in Sources */, - 979DC0022798C08C00E45513 /* LecturesView.swift in Sources */, + 41D55D9E27A2F32800DE7155 /* GradesViewModel+ChartData.swift in Sources */, + 41D55D8D27A2F20300DE7155 /* LectureDetailsBasicInfoView.swift in Sources */, + 97C9AB17277331510097B10C /* AlertErrorHandler.swift in Sources */, 3698CBEF2761E6CC001C5735 /* TokenConfirmationView.swift in Sources */, - 979DC00B2798C08C00E45513 /* EatAPI.swift in Sources */, + 41D55D9927A2F28400DE7155 /* LectureDetails.swift in Sources */, + 41D55D9727A2F23700DE7155 /* GroupBoxLabelView.swift in Sources */, + 97C9AB2D27736FE00097B10C /* APIResponse.swift in Sources */, + 226CB51B2798DA050043ABCA /* PanelRow.swift in Sources */, + 97C9AB15277330B00097B10C /* ErrorHandler.swift in Sources */, 3683C31A2758118A00082930 /* MockModel.swift in Sources */, 3616C4BC278F6EF2000A1BC9 /* MealPlanView.swift in Sources */, - 979DC0232798C08C00E45513 /* XMLSerializer.swift in Sources */, - 979DC01B2798C08C00E45513 /* AlertErrorHandler.swift in Sources */, + 36FF906C2773BE3000F4C785 /* BackendError.swift in Sources */, + 97C9AB27277358B20097B10C /* CampusOnlineAPI.swift in Sources */, + 41D55D8F27A2F20300DE7155 /* LectureDetailsDetailedInfoRowView.swift in Sources */, 36FF906F2773BE8100F4C785 /* AuthenticationHandler.swift in Sources */, - 979DC01C2798C08C00E45513 /* ErrorHandler.swift in Sources */, - 979DC0182798C08C00E45513 /* BackendError.swift in Sources */, - 979DC0222798C08C00E45513 /* LoadingView.swift in Sources */, - 979DC0292798C08C00E45513 /* Grade.swift in Sources */, - 979DC02D2798C08C00E45513 /* GradeView.swift in Sources */, + 97C9AB1C277332830097B10C /* ErrorCategory.swift in Sources */, 3616C4BD278F6EF2000A1BC9 /* MapView.swift in Sources */, 366F0E9027580CFD0091651D /* Campus_iOS.xcdatamodeld in Sources */, - 979DC0262798C08C00E45513 /* GradesViewModel+ChartData.swift in Sources */, - 979DC0092798C08C00E45513 /* LectureDetailsLinkView.swift in Sources */, 3616C4C7278FA2D3000A1BC9 /* Enums.swift in Sources */, - 979DC0172798C08C00E45513 /* NetworkingError.swift in Sources */, + 97997AD5277222730079F809 /* Grade.swift in Sources */, + 41D55D9027A2F20300DE7155 /* LectureDetailsDetailedInfoView.swift in Sources */, + 226CB5192798BF3E0043ABCA /* MealPlanViewModel.swift in Sources */, + 97997AE427722E3B0079F809 /* GradesViewModel.swift in Sources */, + 41D55D7427A2F0CA00DE7155 /* Modus.swift in Sources */, + 41D55D9F27A2F32800DE7155 /* GradesViewModel+State.swift in Sources */, 3616C4C4278F9C0A000A1BC9 /* SheetNavigator.swift in Sources */, - 979DC0102798C08C00E45513 /* TUMOnlineAPI.swift in Sources */, - 979DC0112798C08C00E45513 /* Cache.swift in Sources */, + 41D55D7227A2F06800DE7155 /* Cache.swift in Sources */, 100803462764E2C50013ED0E /* ProfileToolbar.swift in Sources */, - 979DC0072798C08C00E45513 /* LectureDetailsDetailedInfoView.swift in Sources */, - 979DC0142798C08C00E45513 /* APIConstants.swift in Sources */, - 979DC00E2798C08C00E45513 /* CampusOnlineAPI.swift in Sources */, + 97997AED27723C510079F809 /* LoadingView.swift in Sources */, 36203E8C2761C6EC00C24658 /* LoginView.swift in Sources */, - 979DC01E2798C08C00E45513 /* ErrorCategory.swift in Sources */, + 41D55DA327A2F34700DE7155 /* GradesView.swift in Sources */, + 97C9AB20277333040097B10C /* Environment+Error.swift in Sources */, 36E964A7277498540055777F /* CalendarContentView.swift in Sources */, - 979DC02A2798C08C00E45513 /* Modus.swift in Sources */, + 41D55D9127A2F20300DE7155 /* LectureDetailsBasicInfoRowView.swift in Sources */, 3616C4B9278F6EF2000A1BC9 /* Dish.swift in Sources */, - 979DC00A2798C08C00E45513 /* LecturesDetailView.swift in Sources */, - 979DC01F2798C08C00E45513 /* Error+Category.swift in Sources */, + 97997AD22772179D0079F809 /* APIConstants.swift in Sources */, + 36FF906D2773BE3000F4C785 /* XMLSerializer.swift in Sources */, + 97997ADA27722A0A0079F809 /* GradeView.swift in Sources */, + 972397412772825D004BF7AB /* Lecture.swift in Sources */, 100803482764E37A0013ED0E /* ProfileView.swift in Sources */, - 979DC0122798C08C00E45513 /* TUMCabeAPI.swift in Sources */, - 979DBFFB2798C08C00E45513 /* LecturesViewModel+State.swift in Sources */, + 41D55DA527A2F38300DE7155 /* LectureDetailsScreen.swift in Sources */, + 41D55D9B27A2F2B100DE7155 /* LectureDetailsService.swift in Sources */, + 41D55D9627A2F23700DE7155 /* FailedView.swift in Sources */, + 41D55D8B27A2F20300DE7155 /* LecturesView.swift in Sources */, 366F0E8427580CFB0091651D /* App.swift in Sources */, - 979DC01A2798C08C00E45513 /* ErrorEmittingViewModifier.swift in Sources */, - 979DC0202798C08C00E45513 /* FailedView.swift in Sources */, - 979DC01D2798C08C00E45513 /* Environment+Error.swift in Sources */, - 979DBFFE2798C08C00E45513 /* LectureDetails.swift in Sources */, 36FF90652773BB8200F4C785 /* Extensions.swift in Sources */, - 979DC0052798C08C00E45513 /* LectureDetailsTitleView.swift in Sources */, - 979DC02E2798C08C00E45513 /* BarChartView.swift in Sources */, + 41D55DA227A2F34700DE7155 /* BarChartView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1321,6 +1341,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 226CB51C2798DF9C0043ABCA /* XCRemoteSwiftPackageReference "Snap" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/nerdsupremacist/Snap.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.2.2; + }; + }; 36203E812761BDD100C24658 /* XCRemoteSwiftPackageReference "KeychainAccess" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/kishikawakatsumi/KeychainAccess.git"; @@ -1353,6 +1381,14 @@ minimumVersion = 8.0.0; }; }; + 41D55D6C27A2EFB200DE7155 /* XCRemoteSwiftPackageReference "LRUCache" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/nicklockwood/LRUCache.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.0.0; + }; + }; 97997ADF27722D660079F809 /* XCRemoteSwiftPackageReference "Alamofire" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Alamofire/Alamofire.git"; @@ -1369,14 +1405,6 @@ minimumVersion = 0.9.0; }; }; - 979DBFAA2798C00B00E45513 /* XCRemoteSwiftPackageReference "LRUCache" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/nicklockwood/LRUCache.git"; - requirement = { - kind = exactVersion; - version = 1.0.2; - }; - }; 97C9AB1027732A200097B10C /* XCRemoteSwiftPackageReference "SwiftUICharts" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/willdale/SwiftUICharts"; @@ -1388,6 +1416,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 226CB51D2798DF9C0043ABCA /* Snap */ = { + isa = XCSwiftPackageProductDependency; + package = 226CB51C2798DF9C0043ABCA /* XCRemoteSwiftPackageReference "Snap" */; + productName = Snap; + }; 36203E822761BDD100C24658 /* KeychainAccess */ = { isa = XCSwiftPackageProductDependency; package = 36203E812761BDD100C24658 /* XCRemoteSwiftPackageReference "KeychainAccess" */; @@ -1418,6 +1451,11 @@ package = 36FF90702773BFC300F4C785 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; productName = FirebaseCrashlytics; }; + 41D55D6D27A2EFB200DE7155 /* LRUCache */ = { + isa = XCSwiftPackageProductDependency; + package = 41D55D6C27A2EFB200DE7155 /* XCRemoteSwiftPackageReference "LRUCache" */; + productName = LRUCache; + }; 97997AE027722D660079F809 /* Alamofire */ = { isa = XCSwiftPackageProductDependency; package = 97997ADF27722D660079F809 /* XCRemoteSwiftPackageReference "Alamofire" */; @@ -1428,11 +1466,6 @@ package = 97997AE5277234120079F809 /* XCRemoteSwiftPackageReference "XMLCoder" */; productName = XMLCoder; }; - 979DBFAB2798C00C00E45513 /* LRUCache */ = { - isa = XCSwiftPackageProductDependency; - package = 979DBFAA2798C00B00E45513 /* XCRemoteSwiftPackageReference "LRUCache" */; - productName = LRUCache; - }; 97C9AB1127732A200097B10C /* SwiftUICharts */ = { isa = XCSwiftPackageProductDependency; package = 97C9AB1027732A200097B10C /* XCRemoteSwiftPackageReference "SwiftUICharts" */; diff --git a/Campus-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Campus-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 1708237b..8e3e99a0 100644 --- a/Campus-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Campus-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -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", diff --git a/Campus-iOS/App.swift b/Campus-iOS/App.swift index f300789a..1a6f9a9b 100644 --- a/Campus-iOS/App.swift +++ b/Campus-iOS/App.swift @@ -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 { diff --git a/Campus-iOS/Map/Cafeterias/MealPlanView.swift b/Campus-iOS/Map/Cafeterias/MealPlanView.swift index b709e276..57e8d757 100644 --- a/Campus-iOS/Map/Cafeterias/MealPlanView.swift +++ b/Campus-iOS/Map/Cafeterias/MealPlanView.swift @@ -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 { diff --git a/Campus-iOS/Map/Cafeterias/MealPlanViewModel.swift b/Campus-iOS/Map/Cafeterias/MealPlanViewModel.swift new file mode 100644 index 00000000..70ca78d4 --- /dev/null +++ b/Campus-iOS/Map/Cafeterias/MealPlanViewModel.swift @@ -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) } + ) + } + } +} diff --git a/Campus-iOS/Map/Cafeterias/MenuView.swift b/Campus-iOS/Map/Cafeterias/MenuView.swift index 35dcd982..194b8398 100644 --- a/Campus-iOS/Map/Cafeterias/MenuView.swift +++ b/Campus-iOS/Map/Cafeterias/MenuView.swift @@ -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 } } diff --git a/Campus-iOS/Map/Cafeterias/MenuViewModel 2.swift b/Campus-iOS/Map/Cafeterias/MenuViewModel 2.swift new file mode 100644 index 00000000..d71b3ffe --- /dev/null +++ b/Campus-iOS/Map/Cafeterias/MenuViewModel 2.swift @@ -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 + } +} diff --git a/Campus-iOS/Map/Cafeterias/MenuViewModel.swift b/Campus-iOS/Map/Cafeterias/MenuViewModel.swift new file mode 100644 index 00000000..f1af5e82 --- /dev/null +++ b/Campus-iOS/Map/Cafeterias/MenuViewModel.swift @@ -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 + } +} \ No newline at end of file diff --git a/Campus-iOS/Map/MainView/MapContent.swift b/Campus-iOS/Map/MainView/MapContent.swift index a850e3f8..628b0d95 100644 --- a/Campus-iOS/Map/MainView/MapContent.swift +++ b/Campus-iOS/Map/MainView/MapContent.swift @@ -10,6 +10,17 @@ import MapKit import CoreLocation import Alamofire +final class Annotation: NSObject, MKAnnotation { + let coordinate: CLLocationCoordinate2D + let title: String? + + init(title: String?, coordinate: CLLocationCoordinate2D) { + self.title = title + self.coordinate = coordinate + super.init() + } +} + struct MapContent: UIViewRepresentable { @Binding var zoomOnUser: Bool @Binding var panelPosition: String @@ -44,7 +55,7 @@ struct MapContent: UIViewRepresentable { let newCenter = screenHeight/3 - if panelPosition == "up" || panelPosition == "pushMid"{ + if panelPosition == "mid" || panelPosition == "pushMid"{ view.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: newCenter, right: 0) } else if panelPosition == "down" || panelPosition == "pushDown"{ view.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) @@ -114,7 +125,11 @@ struct MapContent: UIViewRepresentable { cafeterias.sortByDistance(to: currentLocation) } - mapView.addAnnotations(response.value ?? []) + guard let cafeterias = response.value else { return } + + let annotations = cafeterias.map { Annotation(title: $0.name, coordinate: $0.coordinate) } + + mapView.addAnnotations(annotations) canteens = cafeterias @@ -134,7 +149,7 @@ struct MapContent: UIViewRepresentable { func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) { control.zoomOnUser = false - control.selectedCanteenName = "" + //control.selectedCanteenName = "" control.selectedAnnotationIndex = -1 } diff --git a/Campus-iOS/Map/MainView/MapView.swift b/Campus-iOS/Map/MainView/MapView.swift index 4bb0d528..3abe21e0 100644 --- a/Campus-iOS/Map/MainView/MapView.swift +++ b/Campus-iOS/Map/MainView/MapView.swift @@ -14,6 +14,7 @@ struct MapView: View { @State var canteens: [Cafeteria] @State var selectedCanteenName: String @State var selectedAnnotationIndex: Int + @State var selectedCanteen: Cafeteria var body: some View { ZStack { @@ -27,7 +28,9 @@ struct MapView: View { panelPosition: $panelPosition, canteens: $canteens, selectedCanteenName: $selectedCanteenName, - selectedAnnotationIndex: $selectedAnnotationIndex) + selectedAnnotationIndex: $selectedAnnotationIndex, + selectedCanteen: $selectedCanteen) + Toolbar(zoomOnUser: $zoomOnUser, selectedCanteenName: $selectedCanteenName, cafeteria: $selectedCanteen) } .edgesIgnoringSafeArea(.all) .navigationTitle("Map") @@ -35,7 +38,7 @@ struct MapView: View { } } -struct MapView_Previews: PreviewProvider { +/*struct MapView_Previews: PreviewProvider { static var previews: some View { MapView(zoomOnUser: true, panelPosition: "down", @@ -43,4 +46,4 @@ struct MapView_Previews: PreviewProvider { selectedCanteenName: "", selectedAnnotationIndex: 0) } -} +}*/ diff --git a/Campus-iOS/Map/MainView/Panel.swift b/Campus-iOS/Map/MainView/Panel.swift index 2c0e30a3..facc6ecd 100644 --- a/Campus-iOS/Map/MainView/Panel.swift +++ b/Campus-iOS/Map/MainView/Panel.swift @@ -16,6 +16,7 @@ struct Panel: View { @Binding var canteens: [Cafeteria] @Binding var selectedCanteenName: String @Binding var selectedAnnotationIndex: Int + @Binding var selectedCanteen: Cafeteria var body: some View { let drag = DragGesture() @@ -29,12 +30,13 @@ struct Panel: View { panelPosition: $panelPosition, canteens: $canteens, selectedCanteenName: $selectedCanteenName, - selectedAnnotationIndex: $selectedAnnotationIndex) + selectedAnnotationIndex: $selectedAnnotationIndex, + selectedCanteen: $selectedCanteen) } .frame(height: UIScreen.main.bounds.height) .background() .cornerRadius(10.0) - .shadow(color: Color(.sRGBLinear, white: 0, opacity: 0.13), radius: 10.0) + .shadow(color: Color(.sRGBLinear, white: 0, opacity: 0.2), radius: 10.0) .offset(y: self.position.rawValue + self.dragState.translation.height) .animation(self.dragState.isDragging ? nil : .interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0)) .gesture(drag) @@ -79,6 +81,8 @@ struct Panel: View { if self.position.rawValue == PanelPosition.bottom.rawValue { panelPosition = "down" } else if self.position.rawValue == PanelPosition.middle.rawValue { + panelPosition = "mid" + } else if self.position.rawValue == PanelPosition.top.rawValue { panelPosition = "up" } } @@ -120,7 +124,7 @@ enum DragState { } } -struct Panel_Previews: PreviewProvider { +/*struct Panel_Previews: PreviewProvider { static var previews: some View { Panel(zoomOnUser: .constant(true), panelPosition: .constant("down"), @@ -128,4 +132,4 @@ struct Panel_Previews: PreviewProvider { selectedCanteenName: .constant(""), selectedAnnotationIndex: .constant(0)) } -} +}*/ diff --git a/Campus-iOS/Map/MainView/PanelContent.swift b/Campus-iOS/Map/MainView/PanelContent.swift index ce2bc850..3d2c6584 100644 --- a/Campus-iOS/Map/MainView/PanelContent.swift +++ b/Campus-iOS/Map/MainView/PanelContent.swift @@ -16,6 +16,7 @@ struct PanelContent: View { @Binding var canteens: [Cafeteria] @Binding var selectedCanteenName: String @Binding var selectedAnnotationIndex: Int + @Binding var selectedCanteen: Cafeteria @State private var searchString = "" @State private var canteenForMealPlan: Cafeteria? @@ -25,12 +26,6 @@ struct PanelContent: View { let sessionManager = Session.defaultSession var locationManager = CLLocationManager() - private static let distanceFormatter: MKDistanceFormatter = { - let formatter = MKDistanceFormatter() - formatter.unitStyle = .abbreviated - return formatter - }() - private let handleThickness = CGFloat(0) var body: some View { @@ -44,6 +39,9 @@ struct PanelContent: View { Button (action: { zoomOnUser = true selectedAnnotationIndex = 0 + if panelPosition == "up" { + panelPosition = "pushMid" + } }) { Image(systemName: "location") .font(.title2) @@ -62,44 +60,15 @@ struct PanelContent: View { ProgressView() ScrollViewReader { proxy in List { - ForEach (canteens.filter({ searchString.isEmpty ? true : $0.name.localizedCaseInsensitiveContains(searchString) }), id: \.self) { item in - VStack { - HStack { - VStack(alignment: .leading, spacing: 8) { - Spacer().frame(height: 5) - HStack { - Text(item.name) - .bold() - .font(.title3) - Spacer() - Image(systemName: "doc.plaintext") - .font(.title3) - .onTapGesture { - canteenForMealPlan = item - goToMealPlan = true - } - NavigationLink(destination: MealPlanView(canteen: canteenForMealPlan, menus: []), isActive: $goToMealPlan) { EmptyView() } .frame(width: 0, height: 0) - .hidden() - } - Spacer().frame(height: 0) - HStack { - Text(item.location.address) - .font(.subheadline) - .foregroundColor(Color.gray) - Spacer() - Text(distance(cafeteria: item)) - .font(.subheadline) - .foregroundColor(Color.gray) - } - Spacer().frame(height: 0) - } - } - } + ForEach (canteens.filter({ searchString.isEmpty ? true : $0.name.localizedCaseInsensitiveContains(searchString) }), id: \.name) { cafeteria in + PanelRow(cafeteria: cafeteria) .onTapGesture { withAnimation { - selectedCanteenName = item.name - selectedAnnotationIndex = canteens.index(of: item)! - proxy.scrollTo(item, anchor: .top) + selectedCanteenName = cafeteria.name + selectedAnnotationIndex = canteens.firstIndex(of: cafeteria)! + proxy.scrollTo(cafeteria, anchor: .top) + + selectedCanteen = cafeteria } } .task(id: selectedAnnotationIndex) { @@ -116,6 +85,9 @@ struct PanelContent: View { .searchable(text: $searchString, prompt: "Look for something") .listStyle(PlainListStyle()) } + .onChange(of: selectedCanteenName) { newValue in + print("SELECTED CANTEEN (Panelcontent): ", newValue) + } } } } @@ -130,14 +102,6 @@ struct PanelContent: View { self.canteens = cafeterias } } - - func distance(cafeteria: Cafeteria) -> String { - if let currentLocation = self.locationManager.location { - let distance = cafeteria.coordinate.location.distance(from: currentLocation) - return PanelContent.distanceFormatter.string(fromDistance: distance) - } - return "" - } } struct SearchBar: View { @@ -149,14 +113,28 @@ struct SearchBar: View { @State private var isEditing = false var body: some View { - TextField("Search ...", text: $searchString) - .padding(7) - .background(Color(.systemGray6)) - .cornerRadius(8) - .onTapGesture { - isEditing = true - panelPosition = "pushMid" + ZStack { + TextField("Search ...", text: $searchString) + .padding(7) + .background(Color(.systemGray6)) + .cornerRadius(8) + .onTapGesture { + isEditing = true + panelPosition = "pushMid" + } + HStack { + Spacer() + if self.searchString != "" { + Button(action: { + self.searchString = "" + }) { + Image(systemName: "xmark.circle.fill") + .foregroundColor(Color(UIColor.opaqueSeparator)) + } + .padding(.trailing, 8) + } } + } if isEditing { Button(action: { diff --git a/Campus-iOS/Map/MainView/PanelRow 2.swift b/Campus-iOS/Map/MainView/PanelRow 2.swift new file mode 100644 index 00000000..b3339671 --- /dev/null +++ b/Campus-iOS/Map/MainView/PanelRow 2.swift @@ -0,0 +1,62 @@ +// +// PanelRow.swift +// Campus-iOS +// +// Created by Tim Gymnich on 20.01.22. +// + +import SwiftUI +import CoreLocation +import MapKit + +struct PanelRow: View { + + @State var cafeteria: Cafeteria + private let locationManager = CLLocationManager() + private let distanceFormatter: MKDistanceFormatter = { + let formatter = MKDistanceFormatter() + formatter.unitStyle = .abbreviated + return formatter + }() + + var body: some View { + VStack { + HStack { + VStack(alignment: .leading, spacing: 5) { + Spacer().frame(height: 5) + HStack { + Text(cafeteria.name) + .bold() + .font(.title3) + } + Spacer().frame(height: 0) + HStack { + Text(cafeteria.location.address) + .font(.subheadline) + .foregroundColor(Color.gray) + Spacer() + Text(distance(cafeteria: cafeteria)) + .font(.subheadline) + .foregroundColor(Color.gray) + } + Spacer().frame(height: 0) + } + } + } + } + + private func distance(cafeteria: Cafeteria) -> String { + if let currentLocation = self.locationManager.location { + let distance = cafeteria.coordinate.location.distance(from: currentLocation) + return distanceFormatter.string(fromDistance: distance) + } + return "" + } +} + +// +//struct PanelRow_Previews: PreviewProvider { +// static var previews: some View { +// PanelRow() +// } +//} diff --git a/Campus-iOS/Map/MainView/PanelRow.swift b/Campus-iOS/Map/MainView/PanelRow.swift new file mode 100644 index 00000000..b3339671 --- /dev/null +++ b/Campus-iOS/Map/MainView/PanelRow.swift @@ -0,0 +1,62 @@ +// +// PanelRow.swift +// Campus-iOS +// +// Created by Tim Gymnich on 20.01.22. +// + +import SwiftUI +import CoreLocation +import MapKit + +struct PanelRow: View { + + @State var cafeteria: Cafeteria + private let locationManager = CLLocationManager() + private let distanceFormatter: MKDistanceFormatter = { + let formatter = MKDistanceFormatter() + formatter.unitStyle = .abbreviated + return formatter + }() + + var body: some View { + VStack { + HStack { + VStack(alignment: .leading, spacing: 5) { + Spacer().frame(height: 5) + HStack { + Text(cafeteria.name) + .bold() + .font(.title3) + } + Spacer().frame(height: 0) + HStack { + Text(cafeteria.location.address) + .font(.subheadline) + .foregroundColor(Color.gray) + Spacer() + Text(distance(cafeteria: cafeteria)) + .font(.subheadline) + .foregroundColor(Color.gray) + } + Spacer().frame(height: 0) + } + } + } + } + + private func distance(cafeteria: Cafeteria) -> String { + if let currentLocation = self.locationManager.location { + let distance = cafeteria.coordinate.location.distance(from: currentLocation) + return distanceFormatter.string(fromDistance: distance) + } + return "" + } +} + +// +//struct PanelRow_Previews: PreviewProvider { +// static var previews: some View { +// PanelRow() +// } +//} diff --git a/Campus-iOS/Map/MainView/Toolbar.swift b/Campus-iOS/Map/MainView/Toolbar.swift new file mode 100644 index 00000000..d3df97eb --- /dev/null +++ b/Campus-iOS/Map/MainView/Toolbar.swift @@ -0,0 +1,48 @@ +// +// Toolbar.swift +// Campus-iOS +// +// Created by ghjtd hbmu on 23.01.22. +// + +import SwiftUI + +struct Toolbar: View { + @Binding var zoomOnUser: Bool + @Binding var selectedCanteenName: String + @Binding var cafeteria: Cafeteria + + var body: some View { + if selectedCanteenName != "" { + HStack { + Button(action: { + print(cafeteria.name) + let latitude = cafeteria.location.latitude + let longitude = cafeteria.location.longitude + let url = URL(string: "maps://?saddr=&daddr=\(latitude),\(longitude)") + + if UIApplication.shared.canOpenURL(url!) { + UIApplication.shared.open(url!, options: [:], completionHandler: nil) + } + }) { + Image(systemName: "figure.walk").foregroundColor(Color.black) + } + + Divider().frame(width: 15) + + NavigationLink(destination: MealPlanView(viewModel: MealPlanViewModel(cafeteria: cafeteria))) { Image(systemName: "doc.text").foregroundColor(Color.black) } + } + .mask(Rectangle()) + .frame(width: 100, height: 40) + .background() + .cornerRadius(10.0) + .position(x: 8 * UIScreen.main.bounds.width/10, y: 1.2 * UIScreen.main.bounds.height/10) + } + } +} + +/*struct Toolbar_Previews: PreviewProvider { + static var previews: some View { + Toolbar() + } +}*/ diff --git a/Campus-iOS/Map/Types/Cafeteria.swift b/Campus-iOS/Map/Types/Cafeteria.swift index 24a63afe..97a27331 100644 --- a/Campus-iOS/Map/Types/Cafeteria.swift +++ b/Campus-iOS/Map/Types/Cafeteria.swift @@ -8,7 +8,7 @@ import Foundation import MapKit -struct Location: Decodable { +struct Location: Decodable, Hashable { let latitude: CLLocationDegrees let longitude: CLLocationDegrees let address: String @@ -16,7 +16,7 @@ struct Location: Decodable { var coordinate: CLLocationCoordinate2D { CLLocationCoordinate2D(latitude: latitude, longitude: longitude) } } -final class Cafeteria: NSObject, Decodable, MKAnnotation { +struct Cafeteria: Decodable, Hashable { /* "location": { "address": "Arcisstraße 17, München", diff --git a/Campus-iOS/Map/Types/Dish.swift b/Campus-iOS/Map/Types/Dish.swift index 204ffee7..11077dfe 100644 --- a/Campus-iOS/Map/Types/Dish.swift +++ b/Campus-iOS/Map/Types/Dish.swift @@ -7,7 +7,7 @@ import Foundation -struct Price: Decodable { +struct Price: Hashable, Decodable { let basePrice: Decimal? let unitPrice: Decimal? let unit: String? @@ -17,7 +17,6 @@ struct Price: Decodable { case unitPrice = "price_per_unit" case unit } - } struct Dish: Decodable, Hashable { @@ -51,7 +50,7 @@ struct Dish: Decodable, Hashable { */ let name: String - let prices: [String: Price?] + var prices: [String: Price] let labels: [String] let dishType: String @@ -70,5 +69,4 @@ struct Dish: Decodable, Hashable { { hasher.combine(name); } - } diff --git a/Campus-iOS/Map/Types/Menu.swift b/Campus-iOS/Map/Types/Menu.swift index 6da516f1..abe95fb6 100644 --- a/Campus-iOS/Map/Types/Menu.swift +++ b/Campus-iOS/Map/Types/Menu.swift @@ -7,23 +7,14 @@ import Foundation -struct Menu: Hashable, Decodable, Comparable { +struct Menu: Hashable, Decodable { /* "date": "2020-03-02", "dishes": [...] */ - let date: Date? + let date: Date let dishes: [Dish] - lazy var categories: [(name: String, dishes: [Dish])] = { - dishes.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{ return ($0,$1) } - }() enum CodingKeys: String, CodingKey { case date @@ -36,17 +27,6 @@ struct Menu: Hashable, Decodable, Comparable { self.date = try container.decode(Date.self, forKey: .date) self.dishes = try container.decode([Dish].self, forKey: .dishes) } - - static func < (lhs: Menu, rhs: Menu) -> Bool { - if let lhsDate = lhs.date, let rhsDate = rhs.date { - return lhsDate < rhsDate - } - return lhs.date == nil - } - - static func == (lhs: Menu, rhs: Menu) -> Bool { - return lhs.date == rhs.date - } } struct Category: Hashable, Decodable { @@ -57,9 +37,4 @@ struct Category: Hashable, Decodable { case name case dishes } - - init() { - self.name = "" - self.dishes = [] - } }