Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions final/RocketReserver.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
66F96FE629FC070600713B80 /* NetworkInterceptorProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F96FE529FC070600713B80 /* NetworkInterceptorProvider.swift */; };
66F96FE829FC0D7700713B80 /* View+Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F96FE729FC0D7700713B80 /* View+Alert.swift */; };
66F96FEA29FC183200713B80 /* NotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F96FE929FC183200713B80 /* NotificationView.swift */; };
E67B2DF02C7D02BC0095602B /* UserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E67B2DEF2C7D02BC0095602B /* UserView.swift */; };
E67B2DF22C7D03180095602B /* UserViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E67B2DF12C7D03180095602B /* UserViewModel.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -54,6 +56,9 @@
66F96FE729FC0D7700713B80 /* View+Alert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Alert.swift"; sourceTree = "<group>"; };
66F96FE929FC183200713B80 /* NotificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationView.swift; sourceTree = "<group>"; };
66F96FEB29FC2BF400713B80 /* RocketReserverAPI */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = RocketReserverAPI; sourceTree = "<group>"; };
E67B2DEF2C7D02BC0095602B /* UserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserView.swift; sourceTree = "<group>"; };
E67B2DF12C7D03180095602B /* UserViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserViewModel.swift; sourceTree = "<group>"; };
E67B2DF32C7D27620095602B /* Me.graphql */ = {isa = PBXFileReference; lastKnownFileType = text; path = Me.graphql; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -82,6 +87,7 @@
66D7A53F2A056886009DDB89 /* TripsBooked.graphql */,
66D7A5402A056886009DDB89 /* LaunchList.graphql */,
66D7A5412A056886009DDB89 /* CancelTrip.graphql */,
E67B2DF32C7D27620095602B /* Me.graphql */,
);
path = graphql;
sourceTree = "<group>";
Expand Down Expand Up @@ -123,6 +129,8 @@
66F96FE929FC183200713B80 /* NotificationView.swift */,
66F96F9E29FAC0D700713B80 /* Assets.xcassets */,
66F96FA029FAC0D700713B80 /* Preview Content */,
E67B2DEF2C7D02BC0095602B /* UserView.swift */,
E67B2DF12C7D03180095602B /* UserViewModel.swift */,
);
path = RocketReserver;
sourceTree = "<group>";
Expand Down Expand Up @@ -245,6 +253,8 @@
66F96F9B29FAC0D600713B80 /* RocketReserverApp.swift in Sources */,
66F96FE229FB0A9600713B80 /* LoginViewModel.swift in Sources */,
66F96FE429FC069D00713B80 /* AuthorizationInterceptor.swift in Sources */,
E67B2DF22C7D03180095602B /* UserViewModel.swift in Sources */,
E67B2DF02C7D02BC0095602B /* UserView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion final/RocketReserver/DetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ struct DetailView: View {
private let placeholderImg = Image("placeholder")

@StateObject private var viewModel: DetailViewModel

@State private var isShowingUser = false

init(launchID: RocketReserverAPI.ID) {
_viewModel = StateObject(wrappedValue: DetailViewModel(launchID: launchID))
}
Expand Down
32 changes: 29 additions & 3 deletions final/RocketReserver/LaunchListView.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import SwiftUI
import KeychainSwift

struct LaunchListView: View {

@StateObject private var viewModel = LaunchListViewModel()

@State private var isShowingLogin = false
@State private var isShowingUser = false

var body: some View {
NavigationStack {
List {
ForEach(0..<viewModel.launches.count, id: \.self) { index in
NavigationLink(destination: DetailView(launchID: viewModel.launches[index].id)) {
LaunchRow(launch: viewModel.launches[index])
LaunchRow(launch: viewModel.launches[index].fragments.launchListDetail)
}
}
if viewModel.lastConnection?.hasMore != false {
Expand All @@ -26,11 +29,34 @@ struct LaunchListView: View {
viewModel.loadMoreLaunchesIfTheyExist()
}
.navigationTitle("Rocket Launches")
.toolbar {
Button(action: {
guard self.isLoggedIn() else {
isShowingLogin = true
return
}

self.isShowingUser.toggle()
}, label: {
Image(systemName: "person.circle")
})
.sheet(isPresented: $isShowingUser) {
UserView()
}
}
.sheet(isPresented: $isShowingLogin) {
LoginView(isPresented: $isShowingLogin)
}
.appAlert($viewModel.appAlert)
}
.notificationView(message: $viewModel.notificationMessage)
}


private func isLoggedIn() -> Bool {
let keychain = KeychainSwift()
return keychain.get(LoginView.loginKeychainKey) != nil
}

}

struct LaunchListView_Previews: PreviewProvider {
Expand Down
2 changes: 1 addition & 1 deletion final/RocketReserver/LaunchRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import SDWebImageSwiftUI
import SwiftUI

struct LaunchRow: View {
let launch: LaunchListQuery.Data.Launches.Launch
let launch: LaunchListDetail
private let placeholderImg = Image("placeholder")

var body: some View {
Expand Down
4 changes: 2 additions & 2 deletions final/RocketReserver/Network.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ class Network {
let cache = InMemoryNormalizedCache()
let store = ApolloStore(cache: cache)
let provider = NetworkInterceptorProvider(client: client, store: store)
let url = URL(string: "https://apollo-fullstack-tutorial.herokuapp.com/graphql")!
let url = URL(string: "https://ios-spacex-router-1da713d90333.herokuapp.com/")!
let transport = RequestChainNetworkTransport(interceptorProvider: provider, endpointURL: url)

let webSocket = WebSocket(
url: URL(string: "wss://apollo-fullstack-tutorial.herokuapp.com/graphql")!,
url: URL(string: "wss://ios-spacex-subgraph-c17ee3a300af.herokuapp.com/graphql")!,
protocol: .graphql_ws
)

Expand Down
37 changes: 37 additions & 0 deletions final/RocketReserver/UserView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import SwiftUI

struct UserView: View {

@StateObject private var viewModel: UserViewModel

init() {
_viewModel = StateObject(wrappedValue: UserViewModel())
}

var body: some View {
NavigationStack {
List {
if let trips = viewModel.trips {
ForEach(0..<trips.count, id: \.self) { index in
NavigationLink(destination: DetailView(launchID: trips[index].id)) {
LaunchRow(launch: trips[index].fragments.launchListDetail)
}
}
}
if (viewModel.trips?.count ?? 0) == 0 {
Text("No trips booked")
}
}
.task {
viewModel.loadTrips()
}
.navigationTitle("Booked Trips")
.appAlert($viewModel.appAlert)
}
.presentationDragIndicator(.visible)
}
}

#Preview {
UserView()
}
28 changes: 28 additions & 0 deletions final/RocketReserver/UserViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Apollo
import RocketReserverAPI
import SwiftUI

class UserViewModel: ObservableObject {

@Published var trips: [MeQuery.Data.Me.Trip]?
@Published var appAlert: AppAlert?

func loadTrips() {
Network.shared.apollo.fetch(query: MeQuery(), cachePolicy: .returnCacheDataAndFetch) { [weak self] result in
guard let self = self else {
return
}

switch result {
case .success(let graphQLResult):
self.trips = graphQLResult.data?.me?.trips.compactMap({ $0 })

if let errors = graphQLResult.errors {
self.appAlert = .errors(errors: errors)
}
case .failure(let error):
self.appAlert = .errors(errors: [error])
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// @generated
// This file was automatically generated and should not be edited.

@_exported import ApolloAPI

public struct LaunchListDetail: RocketReserverAPI.SelectionSet, Fragment {
public static var fragmentDefinition: StaticString {
#"fragment LaunchListDetail on Launch { __typename id site mission { __typename name missionPatch(size: SMALL) } }"#
}

public let __data: DataDict
public init(_dataDict: DataDict) { __data = _dataDict }

public static var __parentType: any ApolloAPI.ParentType { RocketReserverAPI.Objects.Launch }
public static var __selections: [ApolloAPI.Selection] { [
.field("__typename", String.self),
.field("id", RocketReserverAPI.ID.self),
.field("site", String?.self),
.field("mission", Mission?.self),
] }

public var id: RocketReserverAPI.ID { __data["id"] }
public var site: String? { __data["site"] }
public var mission: Mission? { __data["mission"] }

/// Mission
///
/// Parent Type: `Mission`
public struct Mission: RocketReserverAPI.SelectionSet {
public let __data: DataDict
public init(_dataDict: DataDict) { __data = _dataDict }

public static var __parentType: any ApolloAPI.ParentType { RocketReserverAPI.Objects.Mission }
public static var __selections: [ApolloAPI.Selection] { [
.field("__typename", String.self),
.field("name", String?.self),
.field("missionPatch", String?.self, arguments: ["size": "SMALL"]),
] }

public var name: String? { __data["name"] }
public var missionPatch: String? { __data["missionPatch"] }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class BookTripMutation: GraphQLMutation {
public let __data: DataDict
public init(_dataDict: DataDict) { __data = _dataDict }

public static var __parentType: ApolloAPI.ParentType { RocketReserverAPI.Objects.Mutation }
public static var __parentType: any ApolloAPI.ParentType { RocketReserverAPI.Objects.Mutation }
public static var __selections: [ApolloAPI.Selection] { [
.field("bookTrips", BookTrips.self, arguments: ["launchIds": [.variable("id")]]),
] }
Expand All @@ -36,7 +36,7 @@ public class BookTripMutation: GraphQLMutation {
public let __data: DataDict
public init(_dataDict: DataDict) { __data = _dataDict }

public static var __parentType: ApolloAPI.ParentType { RocketReserverAPI.Objects.TripUpdateResponse }
public static var __parentType: any ApolloAPI.ParentType { RocketReserverAPI.Objects.TripUpdateResponse }
public static var __selections: [ApolloAPI.Selection] { [
.field("__typename", String.self),
.field("success", Bool.self),
Expand All @@ -47,4 +47,4 @@ public class BookTripMutation: GraphQLMutation {
public var message: String? { __data["message"] }
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class CancelTripMutation: GraphQLMutation {
public let __data: DataDict
public init(_dataDict: DataDict) { __data = _dataDict }

public static var __parentType: ApolloAPI.ParentType { RocketReserverAPI.Objects.Mutation }
public static var __parentType: any ApolloAPI.ParentType { RocketReserverAPI.Objects.Mutation }
public static var __selections: [ApolloAPI.Selection] { [
.field("cancelTrip", CancelTrip.self, arguments: ["launchId": .variable("launchId")]),
] }
Expand All @@ -36,7 +36,7 @@ public class CancelTripMutation: GraphQLMutation {
public let __data: DataDict
public init(_dataDict: DataDict) { __data = _dataDict }

public static var __parentType: ApolloAPI.ParentType { RocketReserverAPI.Objects.TripUpdateResponse }
public static var __parentType: any ApolloAPI.ParentType { RocketReserverAPI.Objects.TripUpdateResponse }
public static var __selections: [ApolloAPI.Selection] { [
.field("__typename", String.self),
.field("success", Bool.self),
Expand All @@ -47,4 +47,4 @@ public class CancelTripMutation: GraphQLMutation {
public var message: String? { __data["message"] }
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class LoginMutation: GraphQLMutation {
public let __data: DataDict
public init(_dataDict: DataDict) { __data = _dataDict }

public static var __parentType: ApolloAPI.ParentType { RocketReserverAPI.Objects.Mutation }
public static var __parentType: any ApolloAPI.ParentType { RocketReserverAPI.Objects.Mutation }
public static var __selections: [ApolloAPI.Selection] { [
.field("login", Login?.self, arguments: ["email": .variable("email")]),
] }
Expand All @@ -36,7 +36,7 @@ public class LoginMutation: GraphQLMutation {
public let __data: DataDict
public init(_dataDict: DataDict) { __data = _dataDict }

public static var __parentType: ApolloAPI.ParentType { RocketReserverAPI.Objects.User }
public static var __parentType: any ApolloAPI.ParentType { RocketReserverAPI.Objects.User }
public static var __selections: [ApolloAPI.Selection] { [
.field("__typename", String.self),
.field("token", String?.self),
Expand All @@ -45,4 +45,4 @@ public class LoginMutation: GraphQLMutation {
public var token: String? { __data["token"] }
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class LaunchDetailsQuery: GraphQLQuery {
public let __data: DataDict
public init(_dataDict: DataDict) { __data = _dataDict }

public static var __parentType: ApolloAPI.ParentType { RocketReserverAPI.Objects.Query }
public static var __parentType: any ApolloAPI.ParentType { RocketReserverAPI.Objects.Query }
public static var __selections: [ApolloAPI.Selection] { [
.field("launch", Launch?.self, arguments: ["id": .variable("launchId")]),
] }
Expand All @@ -36,7 +36,7 @@ public class LaunchDetailsQuery: GraphQLQuery {
public let __data: DataDict
public init(_dataDict: DataDict) { __data = _dataDict }

public static var __parentType: ApolloAPI.ParentType { RocketReserverAPI.Objects.Launch }
public static var __parentType: any ApolloAPI.ParentType { RocketReserverAPI.Objects.Launch }
public static var __selections: [ApolloAPI.Selection] { [
.field("__typename", String.self),
.field("id", RocketReserverAPI.ID.self),
Expand All @@ -59,7 +59,7 @@ public class LaunchDetailsQuery: GraphQLQuery {
public let __data: DataDict
public init(_dataDict: DataDict) { __data = _dataDict }

public static var __parentType: ApolloAPI.ParentType { RocketReserverAPI.Objects.Mission }
public static var __parentType: any ApolloAPI.ParentType { RocketReserverAPI.Objects.Mission }
public static var __selections: [ApolloAPI.Selection] { [
.field("__typename", String.self),
.field("name", String?.self),
Expand All @@ -77,7 +77,7 @@ public class LaunchDetailsQuery: GraphQLQuery {
public let __data: DataDict
public init(_dataDict: DataDict) { __data = _dataDict }

public static var __parentType: ApolloAPI.ParentType { RocketReserverAPI.Objects.Rocket }
public static var __parentType: any ApolloAPI.ParentType { RocketReserverAPI.Objects.Rocket }
public static var __selections: [ApolloAPI.Selection] { [
.field("__typename", String.self),
.field("name", String?.self),
Expand All @@ -89,4 +89,4 @@ public class LaunchDetailsQuery: GraphQLQuery {
}
}
}
}
}
Loading