Skip to content
Open
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
@@ -0,0 +1,16 @@
package au.com.alfie.ecomm.data.database

import androidx.room.Database
import androidx.room.RoomDatabase
import au.com.alfie.ecomm.data.database.wishlist.WishlistDao
import au.com.alfie.ecomm.data.database.wishlist.model.WishlistEntity

@Database(
entities = [WishlistEntity::class],
version = 1,
exportSchema = true
)
internal abstract class WishlistDatabase : RoomDatabase() {

abstract fun wishlistDao(): WishlistDao
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import androidx.room.Room
import au.com.alfie.ecomm.data.database.FeatureToggleDatabase
import au.com.alfie.ecomm.data.database.InMemoryDatabase
import au.com.alfie.ecomm.data.database.PersistentDatabase
import au.com.alfie.ecomm.data.database.WishlistDatabase
import au.com.alfie.ecomm.data.database.navigation.NavigationEntryDao
import au.com.alfie.ecomm.data.database.search.FeatureToggleDao
import au.com.alfie.ecomm.data.database.search.RecentSearchDao
import au.com.alfie.ecomm.data.database.wishlist.WishlistDao
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand Down Expand Up @@ -47,6 +49,15 @@ internal object DatabaseModule {
name = "feature-toggle-database"
).build()

@Provides
@Singleton
fun provideWishlistDatabase(@ApplicationContext context: Context): WishlistDatabase =
Room.databaseBuilder(
context = context,
klass = WishlistDatabase::class.java,
name = "wishlist-database"
).build()

@Provides
fun provideRecentSearchDao(database: PersistentDatabase): RecentSearchDao = database.recentSearchDao()

Expand All @@ -55,4 +66,7 @@ internal object DatabaseModule {

@Provides
fun provideFeatureToggleDao(database: FeatureToggleDatabase): FeatureToggleDao = database.featureToggleDao()

@Provides
fun provideWishlistDao(database: WishlistDatabase): WishlistDao = database.wishlistDao()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package au.com.alfie.ecomm.data.database.wishlist

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import au.com.alfie.ecomm.data.database.wishlist.model.WishlistEntity
import kotlinx.coroutines.flow.Flow

@Dao
interface WishlistDao {

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun addToWishlist(product: WishlistEntity)

@Query("DELETE FROM wishlist WHERE id = :productId")
suspend fun removeFromWishlist(productId: String)

@Query("SELECT * FROM wishlist")
fun getWishlistIds(): Flow<List<WishlistEntity>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package au.com.alfie.ecomm.data.database.wishlist.model

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "wishlist")
data class WishlistEntity(
@PrimaryKey
val id: String
)
Original file line number Diff line number Diff line change
@@ -1,40 +1,35 @@
package au.com.alfie.ecomm.data.wishlist

import au.com.alfie.ecomm.data.database.wishlist.WishlistDao
import au.com.alfie.ecomm.data.database.wishlist.model.WishlistEntity
import au.com.alfie.ecomm.data.toRepositoryResult
import au.com.alfie.ecomm.repository.product.model.Product
import au.com.alfie.ecomm.repository.result.RepositoryResult
import au.com.alfie.ecomm.repository.wishlist.WishlistRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.map
import timber.log.Timber
import javax.inject.Inject

class WishlistRepositoryImpl @Inject constructor() : WishlistRepository {
class WishlistRepositoryImpl @Inject constructor(
private val wishlistDao: WishlistDao
) : WishlistRepository {

// TODO consider removing this property when the wishlist of product is saved on database or api
private val _wishlist = MutableStateFlow<List<Product>>(listOf())

// TODO change this implementation to a proper implementation using data base or api to save the products on wishlist
override fun addToWishlist(product: Product): RepositoryResult<Boolean> {
if (_wishlist.value.none { it.id == product.id }) {
_wishlist.value = buildList {
addAll(_wishlist.value)
add(product)
}
override fun getWishlist(): Flow<List<String>> =
wishlistDao.getWishlistIds().map { wishlist ->
Timber.tag("WishlistTesting").d("Fetching wishlist: $wishlist")
wishlist.map { it.id }
}
return RepositoryResult.Success(true)
}

// TODO change this implementation to a proper implementation using data base or api to save the products on wishlist
override fun removeFromWishlist(product: Product): RepositoryResult<Boolean> {
_wishlist.value = _wishlist.value.filter { it.id != product.id }.toMutableList()
return RepositoryResult.Success(true)
}
override suspend fun addToWishlist(productId: String) =
runCatching {
Timber.tag("WishlistTesting").d("Adding to wishlist: $productId")
wishlistDao.addToWishlist(WishlistEntity(productId))
}
.toRepositoryResult()

// TODO change this implementation to a proper implementation using data base or api to get the wishlist
override fun getWishlist(): Flow<RepositoryResult<List<Product>>> {
return _wishlist.map { list ->
Result.success(list).toRepositoryResult()
override suspend fun removeFromWishlist(productId: String) =
runCatching {
Timber.tag("WishlistTesting").d("Removing from wishlist: $productId")
wishlistDao.removeFromWishlist(productId)
}
}
.toRepositoryResult()
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ private const val PAGES_COUNT_MINIMUM = 1
@Composable
internal fun EndlessGallery(
gallery: GalleryUI,
isWishlisted: Boolean = false,
startPosition: Int,
isZoomable: Boolean,
onPositionChange: (Int) -> Unit,
Expand Down Expand Up @@ -65,13 +66,15 @@ internal fun EndlessGallery(
pagerState = pagerState,
itemsCount = itemsCount,
gallery = gallery,
isWishlisted = isWishlisted,
content = content
)
} else {
NonZoomableEndlessGallery(
pagerState = pagerState,
itemsCount = itemsCount,
gallery = gallery,
isWishlisted = isWishlisted,
onFavoriteClick = onFavoriteClick,
content = content
)
Expand All @@ -84,6 +87,7 @@ private fun ZoomableEndlessGallery(
pagerState: PagerState,
itemsCount: Int,
gallery: GalleryUI,
isWishlisted: Boolean = false,
content: @Composable EndlessGalleryScope.() -> Unit
) {
Box(
Expand All @@ -94,6 +98,7 @@ private fun ZoomableEndlessGallery(
pagerState = pagerState,
itemsCount = itemsCount,
gallery = gallery,
isWishlisted = isWishlisted,
content = content
)
if (itemsCount > 1) {
Expand All @@ -112,6 +117,7 @@ private fun NonZoomableEndlessGallery(
pagerState: PagerState,
itemsCount: Int,
gallery: GalleryUI,
isWishlisted: Boolean = false,
onFavoriteClick: ClickEvent,
content: @Composable EndlessGalleryScope.() -> Unit
) {
Expand All @@ -120,6 +126,7 @@ private fun NonZoomableEndlessGallery(
pagerState = pagerState,
itemsCount = itemsCount,
gallery = gallery,
isWishlisted = isWishlisted,
onFavoriteClick = onFavoriteClick,
content = content
)
Expand All @@ -138,6 +145,7 @@ private fun ZoomablePager(
pagerState: PagerState,
itemsCount: Int,
gallery: GalleryUI,
isWishlisted: Boolean = false,
content: @Composable EndlessGalleryScope.() -> Unit
) {
HorizontalPager(state = pagerState) { index ->
Expand Down Expand Up @@ -165,6 +173,7 @@ private fun NonZoomablePager(
pagerState: PagerState,
itemsCount: Int,
gallery: GalleryUI,
isWishlisted: Boolean = false,
onFavoriteClick: ClickEvent,
content: @Composable EndlessGalleryScope.() -> Unit
) {
Expand Down Expand Up @@ -197,8 +206,11 @@ private fun NonZoomablePager(
.size(Theme.iconSize.xLarge),
onClick = onFavoriteClick
) {
val iconRes = if(isWishlisted) R.drawable.ic_action_heart_fill else
R.drawable.ic_action_heart_outline

Icon(
painter = painterResource(id = R.drawable.ic_action_heart_outline),
painter = painterResource(id = iconRes),
contentDescription = null,
modifier = Modifier.size(Theme.iconSize.medium)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import kotlin.math.roundToInt
@Composable
fun Gallery(
gallery: GalleryUI,
isWishlisted: Boolean = false,
ratio: Ratio,
constraint: DimensionConstraint,
modifier: Modifier = Modifier,
Expand Down Expand Up @@ -87,6 +88,7 @@ fun Gallery(

EndlessGallery(
gallery = gallery,
isWishlisted = isWishlisted,
startPosition = selectedIndex,
isZoomable = false,
onPositionChange = onPositionChange,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ fun ProductCard(
productCardType: ProductCardType,
onClick: ClickEvent,
modifier: Modifier = Modifier,
isLoading: Boolean = false
isLoading: Boolean = false,
isWishlisted: Boolean = false
) {
when (productCardType) {
is ProductCardType.XSmall -> ProductCardXSmall(
Expand All @@ -35,13 +36,15 @@ fun ProductCard(
productCard = productCardType,
onClick = onClick,
modifier = modifier,
isLoading = isLoading
isLoading = isLoading,
isWishlisted = isWishlisted
)
is ProductCardType.Large -> ProductCardLarge(
productCard = productCardType,
onClick = onClick,
modifier = modifier,
isLoading = isLoading
isLoading = isLoading,
isWishlisted = isWishlisted
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ internal fun ProductCardLarge(
productCard: ProductCardType.Large,
onClick: ClickEvent,
modifier: Modifier = Modifier,
isLoading: Boolean = false
isLoading: Boolean = false,
isWishlisted: Boolean = false
) {
Column(
modifier = modifier then Modifier
Expand All @@ -49,7 +50,8 @@ internal fun ProductCardLarge(
) {
ProductImage(
productCard = productCard,
isLoading = isLoading
isLoading = isLoading,
isWishlisted = isWishlisted
)
Spacer(modifier = Modifier.size(Theme.spacing.spacing16))
ProductDescription(
Expand All @@ -62,7 +64,8 @@ internal fun ProductCardLarge(
@Composable
private fun ProductImage(
productCard: ProductCardType.Large,
isLoading: Boolean
isLoading: Boolean,
isWishlisted: Boolean
) {
Box(
contentAlignment = Alignment.TopEnd
Expand All @@ -80,8 +83,10 @@ private fun ProductImage(
modifier = Modifier.size(Theme.iconSize.large),
onClick = productCard.onFavoriteClick
) {
val iconRes =
if (isWishlisted) R.drawable.ic_action_heart_fill else R.drawable.ic_action_heart_outline
Icon(
painter = painterResource(id = R.drawable.ic_action_heart_outline),
painter = painterResource(iconRes),
contentDescription = null,
modifier = Modifier.size(Theme.iconSize.medium)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ internal fun ProductCardMedium(
productCard: ProductCardType.Medium,
onClick: ClickEvent,
modifier: Modifier = Modifier,
isLoading: Boolean = false
isLoading: Boolean = false,
isWishlisted: Boolean = false
) {
Column(
modifier = modifier then Modifier
Expand All @@ -50,7 +51,8 @@ internal fun ProductCardMedium(
) {
ProductImage(
productCard = productCard,
isLoading = isLoading
isLoading = isLoading,
isWishlisted = isWishlisted
)
Spacer(modifier = Modifier.size(Theme.spacing.spacing12))
ProductDescription(
Expand All @@ -63,7 +65,8 @@ internal fun ProductCardMedium(
@Composable
private fun ProductImage(
productCard: ProductCardType.Medium,
isLoading: Boolean
isLoading: Boolean,
isWishlisted: Boolean
) {
Box(
contentAlignment = Alignment.TopEnd
Expand All @@ -77,10 +80,13 @@ private fun ProductImage(
ratio = Ratio.RATIO3x4
)
if (isLoading.not()) {
val iconRes =
if (isWishlisted) R.drawable.ic_action_heart_fill else R.drawable.ic_action_heart_outline

if (productCard.onFavoriteClick != null) {
ActionIconButton(
productCard.onFavoriteClick,
R.drawable.ic_action_heart_outline
iconRes
)
} else if (productCard.onRemoveClick != null) {
ActionIconButton(
Expand Down Expand Up @@ -186,7 +192,9 @@ private fun ActionIconButton(
) {
onClick?.let {
IconButton(
modifier = Modifier.padding(8.dp).size(Theme.iconSize.large),
modifier = Modifier
.padding(8.dp)
.size(Theme.iconSize.large),
onClick = it
) {
Icon(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ enum class ErrorType {
INVALID_REQUEST,
BAD_REQUEST,
UN_PROCESSABLE_ENTITY,
METHOD_NOT_ALLOWED
METHOD_NOT_ALLOWED,
DATABASE_ERROR
}
Loading
Loading