ashalva/ios.memenator

[Epic] Implement Cat List page

Opened this issue · 2 comments

Cat List

We need to implement totally new page about cat as a service.

The API: https://cataas.com/

  • Add new list item in main page
  • Once user clicks on the item redirect to CatList page
  • Cat List page should have list with all possible tags
  • Once user taps on tag we open new page where we show all cats within the tag.
  • If user taps on any cat we show the image with concrete tag, the request.

Technical Implementation

UI

  • Create new files CatTagsListView and CatTagsListViewModel
  • Add new list item in main page which will open empty CatTagsListView

CatTagsListView has the simple list of cat tags which must be fetched from https://cataas.com/api/tags. See section API for more details. Once user taps on any tag we need to open the detail page, so:

  • Create the CatTagsDetailView and CatTagsDetailViewModel
  • We are showing each each cat category as a separate section. Each section should contain: owner information and all tags within the category.
  • Tapping on tag we show the image with concrete tag

Models

DTOs

  • Create CatTagDetailDTO under Services/DTOs
struct CatTagDetailDTO: Codable {
    let id: String
    let tags: [String]
    let owner: String
    let createdAt: String
    let updatedAt: String

    enum CodingKeys: String, CodingKey {
        case id = "_id"
        case tags, owner, createdAt, updatedAt
    }
}

Business Models

  • Create new model named CatTagDetail under Services/BusinessModels. The model should have basic properties.
struct CatTagDetail {
  let owner: String?
  let tags: [String]
  let createdAt: String
  let updatedAt: String
}

API

  • Create CatListService in Network/Services folder
  • Create CatTagMapper under Network/Mappers
  • Create endpoint getCatTags() -> AnyPublisher<[String], Error> it should return the array of tags. The url: https://cataas.com/api/tags
  • Create endpoint getCatTagsDetail(tag: String) -> Future<CatTag, Error>. The url: https://cataas.com/api/cats?tags=cute
  • Whenever user taps on each cat details tag we need to use ImageLoader to load the image in the app

1st Sprint

1st PR

  1. Create new files CatTagsListView and CatTagsListViewModel
  2. Add new list item in main page which will open empty CatTagsListView

2nd PR

  1. Create model CatTag with name property
  2. Create array of models in viewmodel
  3. Show this array in view

Sprint 2

Sprint goal 🎯

We need to show real cat tags which are fetched from the server. Whenever user opens the cat tag list we need to show loading view and after that show tags. If request fails, we need to show error view.

Leftovers from previous sprint:

  1. Rename CatTagDetail to CatTag

Pull Request 1 - Create service

You can always check RedditService for references.

  1. Create CatListService file, we will need one protocol CatListServing and class CatListService. It can be in the same file.
  2. Add function in CatListServing, func getCatTags() -> AnyPublisher<[CatTag], Error>
  3. Define catTagApiURL constant which will have a value https://cataas.com/api/
  4. Implement same function in CatListService 👇
func getCatTags() -> AnyPublisher<[CatTag], Error> {
    let request = Endpoint<[String]>(baseURL: catTagApiURL)
        .appendingPathParameter("tags")
        .usingDefaultParameters()
    
    return try! request
        .usingMethod(.GET)
        .build()
        .asFuture()
        .map {
             $0.map { tag in CatTag(name: tag) }
         }
        .eraseToAnyPublisher()
}

Pull Request 2 - Show real cat tags

  1. Add service property in viewmodel
  2. Remove fake data from array of CatTag
  3. Create function getCatTags() in viewmodel and call CatListService's new function you have implemented above.
  4. Check how RedditViewModel calls service function. You will need to change receiveCompletion and receiveValue callbacks.

Pull Request 3 - Show loading and error states

  1. Add new @published properties in viewmodel: isLoading, hasError
  2. Whenever getCatTags() is called we need to set isLoading to true
  3. Whenever we receive the response (receiveCompletion or receiveValue is called) we need to set it back to false
  4. Whenever error happens we need to set hasError to true, otherwise false.