// // ContentView.swift // NowPlaying // // Created by Kovács Márk on 14/11/2023. // import SwiftUI struct ContentView: View { @StateObject var model = TheMovieClient() var body: some View { VStack { NavigationStack { List(model.movies.results ?? [], id: \.id) { m in NavigationLink { DetailView(m: m) } label: { VStack(alignment: .leading) { Text(m.title ?? "") .bold() Text(m.releaseDate ?? "") } } } .navigationTitle("Now playing") } .task { do { let data = try await TheMovieClient().getNowPlayingAsync() self.model.movies = data } catch { print(error.localizedDescription) } } } .padding() } } #Preview { ContentView() } // // DetailView.swift // NowPlaying // // Created by Kovács Márk on 14/11/2023. // import SwiftUI struct DetailView: View { var m: Result var body: some View { Form { Section { Text(m.title ?? "") .font(.title) } Section { AsyncImage(url: URL(string: "https://image.tmdb.org/t/p/w500\(m.posterPath ?? "")")) { phase in phase.image? .resizable() .scaledToFit() } } Section { Text(m.overview ?? "") } header: { Text("Overview") } } } } // // NowPlayingApp.swift // NowPlaying // // Created by Kovács Márk on 14/11/2023. // import SwiftUI @main struct NowPlayingApp: App { var body: some Scene { WindowGroup { ContentView() } } } // // NowPlayingResponse.swift // NowPlaying // // Created by Kovács Márk on 14/11/2023. // import Foundation // MARK: - NowPlayingResponse struct NowPlayingResponse: Codable { var dates: Dates? var page: Int? var results: [Result]? var totalPages, totalResults: Int? enum CodingKeys: String, CodingKey { case dates, page, results case totalPages = "total_pages" case totalResults = "total_results" } } // MARK: - Dates struct Dates: Codable { var maximum, minimum: String? } // MARK: - Result struct Result: Codable { var adult: Bool? var backdropPath: String? var genreIDS: [Int]? var id: Int? var originalLanguage: String? var originalTitle, overview: String? var popularity: Double? var posterPath, releaseDate, title: String? var video: Bool? var voteAverage: Double? var voteCount: Int? enum CodingKeys: String, CodingKey { case adult case backdropPath = "backdrop_path" case genreIDS = "genre_ids" case id case originalLanguage = "original_language" case originalTitle = "original_title" case overview, popularity case posterPath = "poster_path" case releaseDate = "release_date" case title, video case voteAverage = "vote_average" case voteCount = "vote_count" } } // // TheMovieClient.swift // NowPlaying // // Created by Kovács Márk on 14/11/2023. // import Foundation class TheMovieClient: ObservableObject { @Published var movies = NowPlayingResponse() let apiKey = "2f5144cb4383086b3f61605f5db6fecf" let baseUrl = "https://api.themoviedb.org/3/" enum NetworkError: Error { case invalidURL case requestFailed(String) } func getNowPlayingAsync() async throws -> NowPlayingResponse { //url elkészítése guard let url = URL(string: "\(baseUrl)movie/now_playing?api_key=\(apiKey)") else { throw NetworkError.invalidURL } //kérés elküldése let (data, response) = try await URLSession.shared.data(from: url) guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw NetworkError.requestFailed("Invalid response") } return try JSONDecoder().decode(NowPlayingResponse.self, from: data) } }