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

Add Pagination to for Showing Reviews #35

Merged
merged 5 commits into from
Apr 6, 2024
Merged
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
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
Loading
Loading