Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/coordinator restaurant detail #56

Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,23 @@ import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?
private var coordinator: AppCoordinator?


func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

guard let windowScene = (scene as? UIWindowScene) else { return }

self.window = UIWindow(frame: UIScreen.main.bounds)
let viewModel = HomeViewModel(service: DeliveryApi())
self.window?.rootViewController = UINavigationController(rootViewController: HomeViewController(viewModel: viewModel))
self.window?.windowScene = windowScene
self.window?.makeKeyAndVisible()
window = UIWindow(frame: UIScreen.main.bounds)

let navigationController = UINavigationController()

coordinator = AppCoordinator(presenter: navigationController)
coordinator?.start()

window?.rootViewController = navigationController
window?.windowScene = windowScene
window?.makeKeyAndVisible()
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import UIKit

final class HomeCoordinator: Coordinator {

var childCoordinators: [Coordinator] = []
var presenter: UINavigationController
weak var parentCoordinator: AppCoordinator?

Expand All @@ -22,4 +22,15 @@ final class HomeCoordinator: Coordinator {
let viewController = HomeViewController(viewModel: viewModel)
presenter.pushViewController(viewController, animated: true)
}

func onFinish() {
parentCoordinator?.childDidFinish(self)
}

func goToDetails() {
let child = RestaurantDetailsCoordinator(presenter: presenter)
child.parentCoordinator = parentCoordinator
childCoordinators.append(child)
child.start()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// RestaurantDetailsCoordinator.swift
// DeliveryAppChallenge
//
// Created by pedro tres on 27/05/22.
//

import Foundation
import UIKit

final class RestaurantDetailsCoordinator: Coordinator {

var presenter: UINavigationController
weak var parentCoordinator: AppCoordinator?

init(presenter: UINavigationController) {
self.presenter = presenter
}

func start() {
let viewModel = RestaurantDetailsViewModel(service: DeliveryApi())
viewModel.coordinator = self
let viewController = RestaurantDetailsViewController(viewModel: viewModel)
presenter.pushViewController(viewController, animated: true)
}

func onFinish() {
parentCoordinator?.childDidFinish(self)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,20 @@ struct RestaurantDetail: Codable {
let name, category: String
let deliveryTime: DeliveryTime
let reviews: Reviews
let menu: [MenuItem]
let menu: [Menu]
}

struct Reviews: Codable {
let score: Double
let count: Int
}

struct Menu: Codable {
let category: String
let name: String
let price: Int

func formattedPrice() -> String {
return "R$ \(price)"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@

import UIKit

protocol MenuListViewDataSource {
func getData(at: Int) -> Menu
func getItemCount() -> Int
}

class MenuListView: UIView {

static let cellSize = CGFloat(96)

private let cellIdentifier = "MenuCellIdentifier"
public var dataSource: MenuListViewDataSource?

lazy var tableView: UITableView = {

Expand Down Expand Up @@ -60,13 +66,21 @@ extension MenuListView {
extension MenuListView: UITableViewDataSource {

public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return 10

guard let datasource = dataSource else {
return 0
}
return datasource.getItemCount()
}

public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! MenuCellView

if let data = dataSource?.getData(at: indexPath.row) {
cell.itemNameLabel.text = data.name
cell.itemPriceLabel.text = data.formattedPrice()
}

return cell
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ protocol RestaurantListViewDataSource {
func getItemCount() -> Int
}

protocol RestaurantListDelegate: AnyObject {
func didSelectGoToRestaurantDetails()
}

class RestaurantListView: UIView {

static let cellSize = CGFloat(82)

private let cellIdentifier = "RestaurantCellIdentifier"
weak var delegate: RestaurantListDelegate?
public var dataSource: RestaurantListViewDataSource?

lazy var tableView: UITableView = {
Expand Down Expand Up @@ -88,6 +93,6 @@ extension RestaurantListView: UITableViewDelegate {
}

public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

self.delegate?.didSelectGoToRestaurantDetails()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class HomeViewController: UIViewController {

override func loadView() {
let homeView = HomeView()
homeView.restaurantListView.delegate = self
self.view = homeView

homeView.restaurantListView.dataSource = viewModel
Expand All @@ -43,3 +44,9 @@ class HomeViewController: UIViewController {
}
}
}

extension HomeViewController: RestaurantListDelegate {
func didSelectGoToRestaurantDetails() {
viewModel.coordinator?.goToDetails()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,37 @@
import UIKit

class RestaurantDetailsViewController: UIViewController {


private let detailsView: RestaurantDetailsView = RestaurantDetailsView()

var viewModel: RestaurantDetailsViewModel

init(viewModel: RestaurantDetailsViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}


override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
viewModel.getRestaurantDetails {
DispatchQueue.main.async {
self.detailsView.menuListView.tableView.reloadData()
}
}
}

override func loadView() {
self.view = RestaurantDetailsView()
self.view = detailsView
detailsView.menuListView.dataSource = viewModel
}

override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
viewModel.coordinator?.onFinish()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// RestaurantDetailsViewModel.swift
// DeliveryAppChallenge
//
// Created by pedro tres on 26/05/22.
//

import Foundation

final class RestaurantDetailsViewModel {

private let service: DeliveryApiProtocol
var coordinator: RestaurantDetailsCoordinator?

public var restaurantsDetailMenu: [Menu] = []

init(service: DeliveryApiProtocol) {
self.service = service
}

func getRestaurantDetails (completion: @escaping () -> Void) {
service.fetchRestaurantDetails { (resut: Result<RestaurantDetail, DeliveryApiError>) in
switch resut {
case .success(let restaurants):
self.restaurantsDetailMenu = restaurants.menu
completion()
case .failure(let error):
print(error)
}
}
}
}

extension RestaurantDetailsViewModel: MenuListViewDataSource {
func getData(at: Int) -> Menu {
return restaurantsDetailMenu[at]
}

func getItemCount() -> Int {
return restaurantsDetailMenu.count
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ enum Endpoints {
protocol DeliveryApiProtocol {
func fetchRestaurants(_ completion: @escaping (Result<[Restaurant], DeliveryApiError>) -> Void)
func searchAddresses(_ completion: @escaping (Result<[Address], DeliveryApiError>) -> Void)
func fetchRestaurantDetails(_ completion: @escaping (Result<[RestaurantDetail], DeliveryApiError>) -> Void)
func fetchRestaurantDetails(_ completion: @escaping (Result<RestaurantDetail, DeliveryApiError>) -> Void)
func fetchMenuItem(_ completion: @escaping (Result<MenuItem, DeliveryApiError>) -> Void)
}

Expand All @@ -31,7 +31,7 @@ struct DeliveryApi: DeliveryApiProtocol {
self.request(Endpoints.searchList, completion: completion)
}

func fetchRestaurantDetails(_ completion: @escaping (Result<[RestaurantDetail], DeliveryApiError>) -> Void) {
func fetchRestaurantDetails(_ completion: @escaping (Result<RestaurantDetail, DeliveryApiError>) -> Void) {
self.request(Endpoints.restaurantDetail, completion: completion)
}

Expand Down