Skip to content

Commit

Permalink
Merge pull request #35 from dead8309/master
Browse files Browse the repository at this point in the history
Add Pagination to for Showing Reviews
  • Loading branch information
dead8309 committed Apr 6, 2024
2 parents 49f1ca4 + 965ef6d commit 9ef5ebb
Show file tree
Hide file tree
Showing 12 changed files with 303 additions and 381 deletions.
6 changes: 5 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ android {

defaultConfig {
applicationId = "in.iot.lab.teacherreview"
minSdk = 24
minSdk = 26
targetSdk = 34
versionCode = 1
versionName = "1.0"
Expand Down Expand Up @@ -128,6 +128,10 @@ dependencies {

//Implementing the design module
implementation(project(":core:design"))

// Paging 3
implementation(libs.paging.runtime)
implementation(libs.paging.compose)
}

fun getBaseUrlInCIEnvironment(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ object Constants {
const val LOGIN_AUTHENTICATION_ENDPOINT = "authentication"
const val TEACHER_LIST_ENDPOINT = "faculties"
const val POST_TEACHER_REVIEW_ENDPOINT = "reviews"

const val ITEMS_PER_PAGE = 10
const val PREFETCH_DISTANCE = 3
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package `in`.iot.lab.teacherreview.feature_teacherlist.data.paging_source

import androidx.paging.PagingSource
import androidx.paging.PagingState
import `in`.iot.lab.teacherreview.core.utils.Constants
import `in`.iot.lab.teacherreview.feature_authentication.domain.repository.AuthRepository
import `in`.iot.lab.teacherreview.feature_teacherlist.data.remote.ReviewsApi
import `in`.iot.lab.teacherreview.feature_teacherlist.domain.models.remote.IndividualReviewData
class ReviewsSource (
private val facultyId: String,
private val authRepository: AuthRepository,
private val reviewsApi: ReviewsApi
) : PagingSource<Int, IndividualReviewData>() {
override fun getRefreshKey(state: PagingState<Int, IndividualReviewData>): Int? {
return state.anchorPosition
}

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, IndividualReviewData> {
return try {
val page = params.key ?: 0
val skip = page * Constants.ITEMS_PER_PAGE

val response = reviewsApi.getIndividualTeacherReviews(
token = authRepository.getUserIdToken().getOrDefault(""),
facultyId = facultyId,
limitValue = Constants.ITEMS_PER_PAGE,
skip = skip
)

val data = response.body()!!.individualReviewData ?: emptyList()

LoadResult.Page(
data = data,
prevKey = if (page == 0) null else page - 1,
nextKey = if (data.isEmpty()) null else page + 1
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import retrofit2.http.POST
import retrofit2.http.Query

interface ReviewsApi {
@GET("reviews?${"$"}populate=faculty&${"$"}populate=createdBy")
// TODO: expose the sort query parameter as function parameter to make it more flexible
@GET("reviews?${"$"}populate=faculty&${"$"}populate=createdBy&${"$"}sort[createdAt]=-1")
suspend fun getIndividualTeacherReviews(
@Header("Authorization") token: String,
@Query("faculty") facultyId: String,
@Query("${"$"}limit") limitValue: Int
@Query("${"$"}limit") limitValue: Int,
@Query("${"$"}skip") skip: Int = 0
): Response<ReviewData>


Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package `in`.iot.lab.teacherreview.feature_teacherlist.data.repository

import android.util.Log
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import `in`.iot.lab.teacherreview.core.utils.Constants
import `in`.iot.lab.teacherreview.feature_authentication.domain.repository.AuthRepository
import `in`.iot.lab.teacherreview.feature_teacherlist.data.paging_source.ReviewsSource
import `in`.iot.lab.teacherreview.feature_teacherlist.data.remote.ReviewsApi
import `in`.iot.lab.teacherreview.feature_teacherlist.domain.models.remote.IndividualReviewData
import `in`.iot.lab.teacherreview.feature_teacherlist.domain.models.remote.ReviewData
import `in`.iot.lab.teacherreview.feature_teacherlist.domain.models.remote.ReviewPostData
import `in`.iot.lab.teacherreview.feature_teacherlist.domain.repository.ReviewRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class ReviewRepositoryImpl @Inject constructor(
Expand Down Expand Up @@ -34,36 +41,22 @@ class ReviewRepositoryImpl @Inject constructor(
}
}

override suspend fun getTeacherReviews(facultyId: String, limitValue: Int): Result<ReviewData> {
override suspend fun getTeacherReviews(facultyId: String): Result<Flow<PagingData<IndividualReviewData>>> {
try {
val response = reviewsApi.getIndividualTeacherReviews(
limitValue = limitValue,
facultyId = facultyId,
token = getToken()
)
Log.d(TAG, response.toString())
if (!response.isSuccessful) {
throw Exception("Error Connecting to the Server")
}

// TODO: Maybe cache the response here
val reviewData = response.body()!!

val sortedReviews = reviewData.individualReviewData?.sortedByDescending {
it.createdAt
}

val sortedResponse = ReviewData(
avgAttendanceRating = reviewData.avgAttendanceRating,
avgMarkingRating = reviewData.avgMarkingRating,
avgTeachingRating = reviewData.avgTeachingRating,
total = reviewData.total,
limit = reviewData.limit,
skip = reviewData.skip,
individualReviewData = sortedReviews
)
val pager = Pager(
config = PagingConfig(
pageSize = Constants.ITEMS_PER_PAGE,
prefetchDistance = Constants.PREFETCH_DISTANCE,
)
) {
ReviewsSource(
facultyId = facultyId,
authRepository = authRepository,
reviewsApi = reviewsApi
)
}.flow

return Result.success(sortedResponse)
return Result.success(pager)
} catch (e: Exception) {
e.printStackTrace()
return Result.failure(e)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package `in`.iot.lab.teacherreview.feature_teacherlist.domain.repository

import androidx.paging.PagingData
import `in`.iot.lab.teacherreview.feature_teacherlist.domain.models.remote.IndividualReviewData
import `in`.iot.lab.teacherreview.feature_teacherlist.domain.models.remote.ReviewData
import `in`.iot.lab.teacherreview.feature_teacherlist.domain.models.remote.ReviewPostData
import kotlinx.coroutines.flow.Flow

interface ReviewRepository {
suspend fun postReview(review: ReviewPostData): Result<ReviewPostData>
suspend fun getTeacherReviews(facultyId: String, limitValue: Int): Result<ReviewData>
suspend fun getTeacherReviews(facultyId: String): Result<Flow<PagingData<IndividualReviewData>>>
suspend fun getStudentsReviewHistory(studentId: String, limitValue: Int): Result<ReviewData>

// TODO: To be added in the next release (maybe ?)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.paging.compose.collectAsLazyPagingItems
import `in`.iot.lab.teacherreview.feature_bottom_navigation.navigation.BottomNavRoutes
import `in`.iot.lab.teacherreview.feature_teacherlist.ui.screen.HomeScreenControl
import `in`.iot.lab.teacherreview.feature_teacherlist.ui.screen.IndividualTeacherControl
Expand Down Expand Up @@ -46,12 +47,14 @@ fun TeacherListNavGraph(
TeacherListRoutes.IndividualTeacherRoute.route,
content = {
val currentUserId by teacherListViewModel.currentUserId.collectAsStateWithLifecycle()
val lazyPagingItems = teacherListViewModel.pagingFlow.collectAsLazyPagingItems()

IndividualTeacherControl(
navController = navController,
selectedTeacher = teacherListViewModel.selectedTeacher!!,
action = teacherListViewModel::action,
individualTeacherReviewApiCall = teacherListViewModel.individualTeacherReviewApiCall,
currentUserId = currentUserId,
lazyPagingItems = lazyPagingItems,
action = teacherListViewModel::action
)
}
)
Expand Down

0 comments on commit 9ef5ebb

Please sign in to comment.