Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.emptyPreferences
import com.troves.data.source.local.preferenceses.DATA_STORE_FILE_NAME
import okio.Path.Companion.toPath

// Android needs a Context to locate filesDir, so the platform Koin module
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.troves.data.repository

import com.troves.data.source.local.preferenceses.AppPreferencesDataSource
import com.troves.data.local.preferenceses.AppPreferencesDataSource

actual fun createAuthenticationRepository(
preferences: AppPreferencesDataSource
Expand Down
8 changes: 4 additions & 4 deletions data/src/commonMain/kotlin/com/troves/data/di/DataModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ package com.troves.data.di

import com.troves.data.local.database.DatabaseFactory
import com.troves.data.local.database.TrovesDatabase
import com.troves.data.local.preferenceses.AppPreferencesDataSource
import com.troves.data.local.preferenceses.AppPreferencesDataSourceImpl
import com.troves.data.network.provideHttpClient
import com.troves.data.repository.CartRepositoryImpl
import com.troves.data.repository.PaymentRepositoryImpl
import com.troves.data.repository.TrovesRepositoryImpl
import com.troves.data.repository.WishlistRepositoryImpl
import com.troves.data.repository.createAuthenticationRepository
import com.troves.data.source.local.preferenceses.AppPreferencesDataSource
import com.troves.data.source.local.preferenceses.AppPreferencesDataSourceImpl
import com.troves.data.source.remote.RemoteDatasource
import com.troves.data.source.remote.RemoteDatasourceImpl
import com.troves.data.source.remote.service.TrovesApiService
import com.troves.data.source.remote.service.TrovesApiServiceImpl
import com.troves.domain.repository.AuthenticationRepository
import com.troves.domain.AuthenticationRepository
import com.troves.domain.repository.CartRepository
import com.troves.domain.repository.PaymentRepository
import com.troves.domain.repository.TrovesRepository
import com.troves.data.repository.WishlistRepositoryImpl
import com.troves.domain.repository.WishlistRepository
import dev.gitlive.firebase.Firebase
import dev.gitlive.firebase.firestore.FirebaseFirestore
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package com.troves.data.source.local.preferenceses
package com.troves.data.local.preferenceses

import kotlinx.io.IOException

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.emptyPreferences
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.map
Expand Down Expand Up @@ -81,7 +80,7 @@ class AppPreferencesDataSourceImpl(
}
private fun Flow<Preferences>.catchIOException() =
catch { e ->
if (e is IOException) emit(emptyPreferences())
if (e is IOException) emit(androidx.datastore.preferences.core.emptyPreferences())
else throw e
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.troves.data.source.local.preferenceses
package com.troves.data.local.preferenceses

import kotlinx.coroutines.flow.Flow

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.troves.data.source.local.preferenceses
package com.troves.data.local.preferenceses

import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.intPreferencesKey
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package com.troves.data.source.local.preferenceses
package com.troves.data.local.preferenceses

internal const val DATA_STORE_FILE_NAME = "app_preferences.preferences_pb"
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.troves.data.repository

import com.troves.data.source.local.preferenceses.AppPreferencesDataSource
import com.troves.domain.utils.Result
import com.troves.domain.repository.AuthenticationRepository
import com.troves.data.local.preferenceses.AppPreferencesDataSource
import com.troves.domain.AuthenticationRepository
import com.troves.domain.Result
import dev.gitlive.firebase.Firebase
import dev.gitlive.firebase.auth.GoogleAuthProvider
import dev.gitlive.firebase.auth.auth
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,18 @@ import com.troves.data.mapper.toBrand
import com.troves.data.mapper.toCategory
import com.troves.data.mapper.toDomain
import com.troves.data.source.remote.RemoteDatasource
import com.troves.domain.Result
import com.troves.domain.entity.Ad
import com.troves.domain.entity.Brand
import com.troves.domain.entity.Category
import com.troves.domain.entity.Product
import com.troves.domain.entity.ProductSearchParams
import com.troves.domain.fold
import com.troves.domain.map
import com.troves.domain.repository.TrovesRepository
import com.troves.domain.utils.Result
import com.troves.domain.utils.fold
import com.troves.domain.utils.getOrElse
import com.troves.domain.utils.map
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.withContext
import kotlinx.io.IOException

class TrovesRepositoryImpl(
private val remoteDataSource: RemoteDatasource,
Expand All @@ -29,37 +26,13 @@ class TrovesRepositoryImpl(
return withContext(coroutineDispatcher) {
remoteDataSource.getAllProducts().map { response ->
response.products
?.filterNotNull()
?.map { it.toDomain() }
.orEmpty()
}
}
}

override suspend fun getProductsByQuery(queryMap: Map<String, String>): Result<List<Product>> {
return withContext(coroutineDispatcher) {
remoteDataSource.getProductsByQuery(queryMap = queryMap).map { response ->
response.products?.map { it.toDomain() }.orEmpty()
}
}
}

override suspend fun searchProducts(params: ProductSearchParams): Result<List<Product>> {
return try {
withContext(coroutineDispatcher) {
var products =
remoteDataSource.searchProducts(params = params).getOrElse { emptyList() }
if (!params.query.isNullOrBlank()) {
products = products.filter {
it.title.contains(params.query ?: "", ignoreCase = true)
}
}
Result.Success(products)
}
} catch (e: IOException) {
Result.Error(e)
}
}

override suspend fun getProductById(productId: String): Result<Product> {
return withContext(coroutineDispatcher) {
remoteDataSource.getProductById(productId = productId).fold(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.troves.data.local.database.WishlistDao
import com.troves.data.local.database.WishlistEntity
import com.troves.data.source.remote.RemoteDatasource
import com.troves.data.source.remote.dto.WishlistDto
import com.troves.domain.utils.Result
import com.troves.domain.Result
import com.troves.domain.entity.Product
import com.troves.domain.repository.WishlistRepository
import kotlinx.coroutines.flow.Flow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,13 @@ import com.troves.data.source.remote.dto.MarketingEventsResponse
import com.troves.data.source.remote.dto.ProductResponse
import com.troves.data.source.remote.dto.ProductDto
import com.troves.data.source.remote.dto.SingleProductResponse
import com.troves.domain.entity.Product
import com.troves.domain.entity.ProductSearchParams
import com.troves.domain.utils.Result
import com.troves.data.source.remote.dto.WishlistDto
import com.troves.domain.Result

interface RemoteDatasource {
//region product
suspend fun createProduct(productDto: ProductDto): Result<ProductDto>
suspend fun getAllProducts(): Result<ProductResponse>
suspend fun getProductsByQuery(queryMap: Map<String, String>): Result<ProductResponse>
suspend fun searchProducts(params: ProductSearchParams): Result<List<Product>>


suspend fun getProductImages(productId: String):Result<List<CollectionImage>>
suspend fun getProductById(productId: String): Result<SingleProductResponse>
suspend fun updateProduct(productId: String)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ import com.troves.data.source.remote.dto.Collection
import com.troves.data.source.remote.dto.CollectionImage
import com.troves.data.source.remote.dto.CustomCollectionResponse
import com.troves.data.source.remote.dto.MarketingEventsResponse
import com.troves.data.source.remote.dto.ProductDto
import com.troves.data.source.remote.dto.ProductResponse
import com.troves.data.source.remote.dto.ProductDto
import com.troves.data.source.remote.dto.SingleProductResponse
import com.troves.data.source.remote.dto.WishlistDto
import com.troves.data.source.remote.service.TrovesApiService
import com.troves.domain.entity.Product
import com.troves.domain.entity.ProductSearchParams
import com.troves.domain.utils.Result
import com.troves.domain.Result
import dev.gitlive.firebase.firestore.FirebaseFirestore

class RemoteDatasourceImpl(
Expand All @@ -25,14 +23,6 @@ class RemoteDatasourceImpl(
return trovesApiService.getAllProducts()
}

override suspend fun getProductsByQuery(queryMap: Map<String, String>): Result<ProductResponse> {
return trovesApiService.getProductsByQuery(queryMap = queryMap)
}

override suspend fun searchProducts(params: ProductSearchParams): Result<List<Product>> {
return trovesApiService.searchProducts(params = params)
}

override suspend fun getProductImages(productId: String): Result<List<CollectionImage>> {
return trovesApiService.getProductImages(productId = productId)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.request
import io.ktor.client.statement.bodyAsText
import io.ktor.http.HttpStatusCode
import com.troves.domain.utils.Result
import com.troves.domain.Result

suspend inline fun <reified T> HttpClient.getResults(
block: HttpRequestBuilder.() -> Unit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,27 @@
package com.troves.data.source.remote.service

import com.troves.data.source.remote.dto.Collection
import com.troves.data.source.remote.dto.CollectionImage
import com.troves.data.source.remote.dto.CustomCollectionResponse
import com.troves.data.source.remote.dto.MarketingEventsResponse
import com.troves.data.source.remote.dto.ProductDto
import com.troves.data.source.remote.dto.ProductResponse
import com.troves.data.source.remote.dto.SingleProductResponse
import com.troves.domain.entity.Product
import com.troves.domain.entity.ProductSearchParams
import com.troves.domain.utils.Result

interface TrovesApiService {
//region products
suspend fun createProduct(productDto: ProductDto): Result<ProductDto>
suspend fun getAllProducts(): Result<ProductResponse>
suspend fun getProductsByQuery(queryMap: Map<String, String>): Result<ProductResponse>
suspend fun searchProducts(params: ProductSearchParams): Result<List<Product>>

suspend fun getProductImages(productId: String): Result<List<CollectionImage>>
suspend fun getProductById(productId: String): Result<SingleProductResponse>
suspend fun createProduct(productDto: ProductDto): com.troves.domain.Result<ProductDto>
suspend fun getAllProducts(): com.troves.domain.Result<ProductResponse>
suspend fun getProductImages(productId: String): com.troves.domain.Result<List<CollectionImage>>
suspend fun getProductById(productId: String): com.troves.domain.Result<SingleProductResponse>
suspend fun updateProduct(productId: String)
suspend fun deleteProduct(productDto: ProductDto)
// endregion


//region brands

suspend fun getAllBrands(): Result<Collection>
suspend fun getCategory(): Result<CustomCollectionResponse>
suspend fun getAllBrands(): com.troves.domain.Result<Collection>
suspend fun getCategory(): com.troves.domain.Result<CustomCollectionResponse>

//endregion

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package com.troves.data.source.remote.service

import com.troves.data.source.remote.RemoteDatasource
import com.troves.data.source.remote.dto.Collection
import com.troves.data.source.remote.dto.CollectionImage
import com.troves.data.source.remote.dto.CustomCollectionResponse
import com.troves.data.source.remote.dto.MarketingEventsResponse
import com.troves.data.source.remote.dto.ProductDto
import com.troves.data.source.remote.dto.ProductResponse
import com.troves.data.source.remote.dto.SingleProductResponse
import com.troves.domain.entity.Product
import com.troves.domain.entity.ProductSearchParams
import com.troves.domain.Result
import io.ktor.client.HttpClient
import io.ktor.http.HttpMethod
import io.ktor.http.parameters
import io.ktor.http.path
import com.troves.domain.utils.Result
import io.ktor.client.request.parameter

class TrovesApiServiceImpl(
private val ktorClient: HttpClient
Expand All @@ -29,32 +26,10 @@ class TrovesApiServiceImpl(
url { path("products.json") }
}

override suspend fun getProductsByQuery(queryMap: Map<String, String>): Result<ProductResponse> =
ktorClient.getResults {
method = HttpMethod.Get
url {
path("products.json")
queryMap.entries.forEach {
parameter(it.key, it.value)
}
}
}

override suspend fun searchProducts(params: ProductSearchParams): Result<List<Product>> {
return ktorClient.getResults {
method = HttpMethod.Get
params.vendor?.let { parameter("vendor", it) }
params.productType?.let { parameter("product_type", it) }
params.collectionId?.let { parameter("collection_id", it) }
params.status?.let { parameter("status", it.restValue) }
parameter("limit", params.limit)
}
}

override suspend fun getProductImages(productId: String): Result<List<CollectionImage>> {
return ktorClient.getResults {
method = HttpMethod.Get
url {
url{
path("products/$productId/images.json")
}
}
Expand All @@ -63,7 +38,7 @@ class TrovesApiServiceImpl(
override suspend fun getProductById(productId: String): Result<SingleProductResponse> {
return ktorClient.getResults {
method = HttpMethod.Get
url {
url{
path("products/$productId.json")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.emptyPreferences
import com.troves.data.source.local.preferenceses.DATA_STORE_FILE_NAME
import okio.Path.Companion.toPath
import platform.Foundation.NSHomeDirectory

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.troves.data.repository

import com.troves.data.source.local.preferenceses.AppPreferencesDataSource
import com.troves.data.local.preferenceses.AppPreferencesDataSource

actual fun createAuthenticationRepository(
preferences: AppPreferencesDataSource
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,4 @@
package com.troves.domain.utils

/**
* Copyright (c) 2026 Wahid Ali Wahid Hussien.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Author: Wahid Ali Wahid Hussien
* Created: 30/06/2026
*/
package com.troves.domain

sealed interface Result<out R> {
data class Success<out T>(val value: T) : Result<T>
Expand All @@ -29,7 +8,7 @@ sealed interface Result<out R> {


inline fun <T, R> Result<T>.map(transform: (value:T) -> R): Result<R> =
when (this) {
when (this) {
is Result.Loading -> Result.Loading
is Result.Success -> Result.Success(transform(value))
is Result.Error -> Result.Error(throwable)
Expand Down
Loading