Added UserRepository and ExpenseShareRepository
Implemented `UserRepository` and `ExpenseShareRepository` to handle data fetching with a caching strategy (local DAO + remote API). Specific changes include: - Added `getUserById` to `UserDao` and updated `getShareById` in `ExpenseShareDao` to support nullable returns. - Updated `APIService` and `ComDataTypes` to include endpoints and data models for User info, Expense Shares, and pluralized Expense responses. - Refactored `ExpenseRepository` to use the updated API naming conventions and removed debug print statements.
This commit is contained in:
@@ -24,7 +24,7 @@ interface ExpenseShareDao {
|
|||||||
fun getAllShares(): Flow<List<ExpenseShare>>
|
fun getAllShares(): Flow<List<ExpenseShare>>
|
||||||
|
|
||||||
@Query("SELECT * FROM expense_shares WHERE id = :shareId")
|
@Query("SELECT * FROM expense_shares WHERE id = :shareId")
|
||||||
fun getShareById(shareId: UUID): Flow<ExpenseShare>
|
fun getShareById(shareId: UUID): Flow<ExpenseShare?>
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
suspend fun insertShare(share: ExpenseShare)
|
suspend fun insertShare(share: ExpenseShare)
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ interface UserDao {
|
|||||||
@Query("SELECT * FROM users")
|
@Query("SELECT * FROM users")
|
||||||
fun getAllUsers(): Flow<List<User>>
|
fun getAllUsers(): Flow<List<User>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM users WHERE id = :userId")
|
||||||
|
fun getUserById(userId: UUID): Flow<User?>
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
suspend fun insertUser(user: User)
|
suspend fun insertUser(user: User)
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ interface APIService {
|
|||||||
|
|
||||||
// Expenses
|
// Expenses
|
||||||
@GET("api/expenses")
|
@GET("api/expenses")
|
||||||
suspend fun expenseGet(@Header("Authorization") token: String): Response<ExpenseResponse>
|
suspend fun expensesGet(@Header("Authorization") token: String): Response<ExpensesResponse>
|
||||||
@POST("api/expenses")
|
@POST("api/expenses")
|
||||||
suspend fun expenseCreate(@Header("Authorization") token: String)
|
suspend fun expenseCreate(@Header("Authorization") token: String)
|
||||||
@PUT("api/expenses")
|
@PUT("api/expenses")
|
||||||
@@ -29,7 +29,13 @@ interface APIService {
|
|||||||
@DELETE("api/expenses")
|
@DELETE("api/expenses")
|
||||||
suspend fun expenseDelete(@Header("Authorization") token: String)
|
suspend fun expenseDelete(@Header("Authorization") token: String)
|
||||||
|
|
||||||
|
// Shares
|
||||||
|
@GET("api/shares")
|
||||||
|
suspend fun sharesGet(@Header("Authorization") token: String): Response<ExpenseSharesResponse>
|
||||||
|
@GET("api/shares")
|
||||||
|
suspend fun shareGet(@Header("Authorization") token: String, @Query("id") shareId: UUID): Response<ExpenseShareResponse>
|
||||||
|
|
||||||
// User
|
// User
|
||||||
@GET("api/userinfo")
|
@GET("api/userinfo")
|
||||||
suspend fun userinfo(@Header("Authorization") token: String, @Query("id") userId: UUID)
|
suspend fun userinfo(@Header("Authorization") token: String, @Query("id") userId: UUID): Response<UserinfoResponse>
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package de.miaurizius.shap_planner.network
|
package de.miaurizius.shap_planner.network
|
||||||
|
|
||||||
import de.miaurizius.shap_planner.entities.Expense
|
import de.miaurizius.shap_planner.entities.Expense
|
||||||
|
import de.miaurizius.shap_planner.entities.ExpenseShare
|
||||||
|
import de.miaurizius.shap_planner.entities.User
|
||||||
|
|
||||||
// Login
|
// Login
|
||||||
data class LoginRequest(val username: String, val password: String)
|
data class LoginRequest(val username: String, val password: String)
|
||||||
@@ -12,4 +14,11 @@ data class RefreshRequest(val refresh_token: String)
|
|||||||
data class RefreshResponse(val access_token: String, val refresh_token: String)
|
data class RefreshResponse(val access_token: String, val refresh_token: String)
|
||||||
|
|
||||||
// Expenses
|
// Expenses
|
||||||
data class ExpenseResponse(val expenses: List<Expense>)
|
data class ExpensesResponse(val expenses: List<Expense>)
|
||||||
|
|
||||||
|
// ExpenseShares
|
||||||
|
data class ExpenseSharesResponse(val shares: List<ExpenseShare>)
|
||||||
|
data class ExpenseShareResponse(val share: ExpenseShare)
|
||||||
|
|
||||||
|
// User
|
||||||
|
data class UserinfoResponse(val user: User)
|
||||||
@@ -13,18 +13,15 @@ class ExpenseRepository(
|
|||||||
) {
|
) {
|
||||||
fun getExpenses(token: String, forceRefresh: Boolean = false): Flow<Resource<List<Expense>>> = flow {
|
fun getExpenses(token: String, forceRefresh: Boolean = false): Flow<Resource<List<Expense>>> = flow {
|
||||||
val cachedExpense = dao.getAllExpenses().first()
|
val cachedExpense = dao.getAllExpenses().first()
|
||||||
println("CachedExpense: $cachedExpense")
|
|
||||||
emit(Resource.Loading(cachedExpense))
|
emit(Resource.Loading(cachedExpense))
|
||||||
|
|
||||||
if(cachedExpense.isEmpty() || forceRefresh) {
|
if(cachedExpense.isEmpty() || forceRefresh) {
|
||||||
try {
|
try {
|
||||||
val response = api.expenseGet("Bearer $token")
|
val response = api.expensesGet("Bearer $token")
|
||||||
if(response.isSuccessful) {
|
if(response.isSuccessful) {
|
||||||
val remoteExpense = response.body()?.expenses ?: emptyList()
|
val remoteExpense = response.body()?.expenses ?: emptyList()
|
||||||
println("Fetched expenses: $remoteExpense")
|
|
||||||
remoteExpense.forEach {
|
remoteExpense.forEach {
|
||||||
dao.insertExpense(it)
|
dao.insertExpense(it)
|
||||||
println("Added $it")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(e: Exception) {
|
} catch(e: Exception) {
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package de.miaurizius.shap_planner.repository
|
||||||
|
|
||||||
|
import de.miaurizius.shap_planner.entities.ExpenseShare
|
||||||
|
import de.miaurizius.shap_planner.entities.ExpenseShareDao
|
||||||
|
import de.miaurizius.shap_planner.network.APIService
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class ExpenseShareRepository(
|
||||||
|
private val dao: ExpenseShareDao,
|
||||||
|
private val api: APIService
|
||||||
|
) {
|
||||||
|
fun getShares(token: String, forceRefresh: Boolean = false): Flow<Resource<List<ExpenseShare>>> = flow {
|
||||||
|
val cachedData = dao.getAllShares().first()
|
||||||
|
emit(Resource.Loading(cachedData))
|
||||||
|
|
||||||
|
if(cachedData.isEmpty() || forceRefresh) {
|
||||||
|
try {
|
||||||
|
val response = api.sharesGet("Bearer $token")
|
||||||
|
if(response.isSuccessful) {
|
||||||
|
val remoteShare = response.body()?.shares ?: emptyList()
|
||||||
|
remoteShare.forEach {
|
||||||
|
dao.insertShare(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(e: Exception) {
|
||||||
|
emit(Resource.Error("Network Error: ${e.localizedMessage}", cachedData))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dao.getAllShares().collect { emit(Resource.Success(it)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getShareById(token: String, shareId: UUID, forceRefresh: Boolean = false): Flow<Resource<ExpenseShare>> = flow {
|
||||||
|
val cached = dao.getShareById(shareId).first()
|
||||||
|
emit(Resource.Loading(cached))
|
||||||
|
if(cached == null || forceRefresh) {
|
||||||
|
try {
|
||||||
|
val response = api.shareGet("Bearer $token", shareId)
|
||||||
|
if(response.isSuccessful) {
|
||||||
|
response.body()?.share?.let { remoteShare -> dao.insertShare(remoteShare) }
|
||||||
|
}
|
||||||
|
} catch(e: Exception) {
|
||||||
|
emit(Resource.Error("Network-Error: ${e.localizedMessage}", cached))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dao.getShareById(shareId).collect { share ->
|
||||||
|
if(share != null) emit(Resource.Success(share))
|
||||||
|
else emit(Resource.Error("Share nicht gefunden", null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package de.miaurizius.shap_planner.repository
|
||||||
|
|
||||||
|
import de.miaurizius.shap_planner.entities.User
|
||||||
|
import de.miaurizius.shap_planner.entities.UserDao
|
||||||
|
import de.miaurizius.shap_planner.network.APIService
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class UserRepository(
|
||||||
|
private val dao: UserDao,
|
||||||
|
private val api: APIService
|
||||||
|
) {
|
||||||
|
fun getUser(token: String, userId: UUID, forceRefresh: Boolean = false): Flow<Resource<User>> = flow {
|
||||||
|
val cached = dao.getUserById(userId).first()
|
||||||
|
emit(Resource.Loading(cached))
|
||||||
|
if(cached == null || forceRefresh) {
|
||||||
|
try {
|
||||||
|
val response = api.userinfo("Bearer $token", userId)
|
||||||
|
if(response.isSuccessful) {
|
||||||
|
response.body()?.user?.let { remoteUser -> dao.insertUser(remoteUser) }
|
||||||
|
}
|
||||||
|
} catch(e: Exception) {
|
||||||
|
emit(Resource.Error("Network-Error: ${e.localizedMessage}", cached))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dao.getUserById(userId).collect { user -> if(user != null) emit(Resource.Success(user)) else emit(
|
||||||
|
Resource.Error("User nicht gefunden", null)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user