Skip to content

Commit

Permalink
[feat][#57] Pagination 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
enebin committed Sep 20, 2024
1 parent 0939994 commit 76ed75b
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 47 deletions.
81 changes: 43 additions & 38 deletions Targets/Mashow/Sources/RecordList/Home/RecordListVIewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Combine
class RecordListViewModel {
typealias RecordCellInformation = RecordListViewController.RecordCellInformation

let state: State
private(set) var state: State
let action: Action
private let networkManager: NetworkManager<API>

Expand All @@ -25,6 +25,9 @@ class RecordListViewModel {
let isLoading: CurrentValueSubject<Bool, Never> = .init(false)
let records: CurrentValueSubject<[RecordCellInformation], Never> = .init([])
let recordStat: CurrentValueSubject<RecordStat?, Never> = .init(nil)
var currentPage: Int = 1 // Current page being loaded
var totalPage: Int = 1 // Total pages from the API
var isFetchingNextPage: Bool = false // Flag to prevent multiple simultaneous page loads

init(nickname: String, userId: Int, fetchableDrinkTypes: [DrinkType], drinkTypeToBeShown drinkType: DrinkType) {
self.nickname = nickname
Expand Down Expand Up @@ -53,65 +56,67 @@ class RecordListViewModel {
state.currentDrinkType.send(drinkType)
}

func updateRecords(with drinkType: DrinkType) async throws {
// Pagination-aware function to update records
func updateRecords(with drinkType: DrinkType, page: Int = 1, append: Bool = false) async throws {
state.isLoading.send(true)

let recordList = try await networkManager.request(
.history(.getRecord(filters: [drinkType], userId: state.userId, page: 1, size: 5)),
.history(.getRecord(filters: [drinkType], userId: state.userId, page: page, size: 5)), // Size's fixed to max value(5)
of: RecordListResponse.self).value

let recordStat = try await networkManager.request(
.history(.getStatistics(filters: [drinkType])),
of: RecordStatResponse.self).value

let baseRecordSet = recordList.contents.flatMap {
$0.histories.flatMap { $0.toRecordCellInformation() }
$0.histories.map { $0.toRecordCellInformation() }
}

// Update the current and total page information
state.currentPage = recordList.currentPageIndex
state.totalPage = recordList.totalPageNumber

// If append is true, add the new data to the existing records
if append {
let existingRecords = state.records.value
state.records.send(existingRecords + baseRecordSet)
} else {
state.records.send(baseRecordSet)
}

self.state.recordStat.send(recordStat)
self.state.records.send(baseRecordSet)
self.state.isLoading.send(false)
}
}

struct SharedDateFormatter {
static let serverDateFormatter: DateFormatter = {
let serverDateFormatter = DateFormatter()
serverDateFormatter.locale = Locale(identifier: "en_US_POSIX") // Ensures consistent formatting
serverDateFormatter.timeZone = TimeZone(secondsFromGMT: 0) // Use UTC time zone
serverDateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS" // Format for microseconds

return serverDateFormatter
}()

static let shortDateFormmater: DateFormatter = {
let shortDateFormmater = DateFormatter()
shortDateFormmater.dateFormat = "yyyy.MM.dd"
// Function to fetch the next page of data
func fetchNextPage() async throws {
guard !state.isFetchingNextPage, state.currentPage < state.totalPage else {
return
}

return shortDateFormmater
}()
state.isFetchingNextPage = true
let nextPage = state.currentPage + 1
try await updateRecords(with: state.currentDrinkType.value, page: nextPage, append: true)
state.isFetchingNextPage = false
}
}

extension RecordListResponse.Value.Content.History {
func toRecordCellInformation() -> [RecordListViewController.RecordCellInformation] {
func toRecordCellInformation() -> RecordListViewController.RecordCellInformation {
if liquorDetailNames.isEmpty {
[
RecordListViewController.RecordCellInformation(
id: UUID(),
date: SharedDateFormatter.serverDateFormatter.date(from:drankAt),
name: "",
recordType: .record
)
]
RecordListViewController.RecordCellInformation(
id: UUID(),
date: SharedDateFormatter.serverDateFormatter.date(from:drankAt),
names: [],
recordType: .record
)
} else {
liquorDetailNames.map { history in
RecordListViewController.RecordCellInformation(
id: UUID(),
date: SharedDateFormatter.serverDateFormatter.date(from:drankAt),
name: history,
recordType: .record
)
}
RecordListViewController.RecordCellInformation(
id: UUID(),
date: SharedDateFormatter.serverDateFormatter.date(from:drankAt),
names: liquorDetailNames,
recordType: .record
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ extension RecordListViewController {

let id: UUID
let date: Date?
let name: String?
let names: [String]?
let recordType: RecordType

static func == (lhs: RecordCellInformation, rhs: RecordCellInformation) -> Bool {
Expand All @@ -261,8 +261,21 @@ extension RecordListViewController {
// MARK: - UICollectionViewDelegate

extension RecordListViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// Handle cell selection if needed
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
let height = scrollView.frame.size.height

// Trigger pagination when the user scrolls near the bottom
if offsetY > contentHeight - height - 100 {
Task {
do {
try await viewModel.fetchNextPage()
} catch {
showErrorAlert()
}
}
}
}
}

Expand Down Expand Up @@ -369,7 +382,9 @@ extension RecordListViewController {
for category in sortedCategories {
if var recordsForMonth = groupedRecords[category] {
recordsForMonth.sort { $0.date ?? Date() > $1.date ?? Date() }
snapshot.appendSections([category])
if !snapshot.sectionIdentifiers.contains(category) {
snapshot.appendSections([category])
}
snapshot.appendItems(recordsForMonth, toSection: category)
}
}
Expand All @@ -380,11 +395,6 @@ extension RecordListViewController {
private func groupRecordsByMonth(records: [RecordCellInformation]) -> [Category: [RecordCellInformation]] {
var groupedRecords = [Category: [RecordCellInformation]]()

let serverDateFormatter = DateFormatter()
serverDateFormatter.locale = Locale(identifier: "en_US_POSIX") // Ensures consistent formatting
serverDateFormatter.timeZone = TimeZone(secondsFromGMT: 0) // Use UTC time zone
serverDateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS" // Format for microseconds

for record in records {
guard let date = record.date else {
continue
Expand Down
18 changes: 18 additions & 0 deletions Targets/Mashow/Sources/Util/Date + Extention.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@

import Foundation

struct SharedDateFormatter {
static let serverDateFormatter: DateFormatter = {
let serverDateFormatter = DateFormatter()
serverDateFormatter.locale = Locale(identifier: "en_US_POSIX") // Ensures consistent formatting
serverDateFormatter.timeZone = TimeZone(secondsFromGMT: 0) // Use UTC time zone
serverDateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS" // Format for microseconds

return serverDateFormatter
}()

static let shortDateFormmater: DateFormatter = {
let shortDateFormmater = DateFormatter()
shortDateFormmater.dateFormat = "yyyy.MM.dd"

return shortDateFormmater
}()
}

extension Date {
static func todayStringWrittenInKorean() -> String {
// In M월 DD일 E요일
Expand Down

0 comments on commit 76ed75b

Please sign in to comment.