[Framework] Show top words for filtered items in the Feed List (#12)

This PR contains the work done to show the top 3 words belonging to the filtered reviews  in the `FeedListViewController` view controller.

Reviewed-on: rock-n-code/app-reviews#12
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This commit was merged in pull request #12.
This commit is contained in:
2024-03-21 01:13:12 +00:00
committed by javier
parent eac34c61c1
commit d00cfceb32
10 changed files with 339 additions and 43 deletions
@@ -0,0 +1,23 @@
//
// TopWord+DTOs.swift
// ReviewsFeed
//
// Created by Javier Cicchelli on 21/03/2024.
// Copyright © 2024 Röck+Cöde. All rights reserved.
//
import Foundation
import ReviewsFilterKit
extension TopWord {
// MARK: Initialisers
init(_ dto: WordCount) {
self = .init(
id: UUID().uuidString,
term: dto.word.term,
count: dto.count
)
}
}
@@ -0,0 +1,16 @@
//
// TopWord.swift
// ReviewsFeed
//
// Created by Javier Cicchelli on 21/03/2024.
// Copyright © 2024 Röck+Cöde. All rights reserved.
//
struct TopWord: Identifiable {
// MARK: Constants
let id: String
let term: String
let count: Int
}
@@ -18,6 +18,9 @@ extension FeedListViewController {
// MARK: Constants
private let configuration: Configuration
private let filterWords: FilterWordsUseCase = .init()
private let topWords: TopWordsUseCase = .init()
// MARK: Properties
@Published var filter: FilterOption = .all
@@ -26,9 +29,11 @@ extension FeedListViewController {
@Published var isLoading: Bool = false
var items: [Review] = []
var words: [TopWord] = []
private var reviewsAll: [Review] = []
private var reviewsFiltered: FilteredReviews = [:]
private var reviewsTopWords: TopWordsReviews = [:]
lazy private var iTunesService: iTunesService = {
.init(configuration: .init(session: configuration.session))
@@ -38,6 +43,18 @@ extension FeedListViewController {
init(configuration: Configuration = .init()) {
self.configuration = configuration
}
// MARK: Computed
var itemsCount: Int {
isWordsShowing
? items.count
: items.count + 1
}
var isWordsShowing: Bool {
filter != .all
&& !words.isEmpty
}
// MARK: Functions
func fetch() {
@@ -56,6 +73,14 @@ extension FeedListViewController {
.reduce(into: FilteredReviews()) { partialResult, option in
partialResult[option] = reviewsAll.filter { $0.rating.stars == option.rawValue }
}
reviewsTopWords = reviewsFiltered
.mapValues { reviews in
reviews.map(\.comment)
.compactMap { try? filterWords($0) }
}
.mapValues {
topWords($0).map(TopWord.init)
}
items = reviewsAll
isFilterEnabled = !items.isEmpty
@@ -74,9 +99,18 @@ extension FeedListViewController {
items = option == .all
? reviewsAll
: reviewsFiltered[option] ?? []
words = reviewsTopWords[option] ?? []
filter = option
}
func item(for index: Int) -> Review? {
guard index < items.count else { return nil }
return isWordsShowing
? items[index - 1]
: items[index]
}
}
}
@@ -86,5 +120,6 @@ private extension FeedListViewController.ViewModel {
// MARK: Type aliases
typealias FilteredReviews = [FilterOption: [Review]]
typealias TopWordsReviews = [FilterOption: [TopWord]]
}