Skip to content

Commit 3272b17

Browse files
Merge pull request #5 from Mindera/dev/ALFMOB-81_add_to_bag
[ALFMOB-81] Add to Bag
2 parents ba48c52 + aec4884 commit 3272b17

35 files changed

Lines changed: 1037 additions & 68 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package au.com.alfie.ecomm.data.bag
2+
3+
import au.com.alfie.ecomm.data.toRepositoryResult
4+
import au.com.alfie.ecomm.repository.bag.BagProduct
5+
import au.com.alfie.ecomm.repository.bag.BagRepository
6+
import au.com.alfie.ecomm.repository.result.RepositoryResult
7+
import kotlinx.coroutines.flow.Flow
8+
import kotlinx.coroutines.flow.MutableStateFlow
9+
import kotlinx.coroutines.flow.map
10+
import javax.inject.Inject
11+
12+
class BagRepositoryImpl @Inject constructor() : BagRepository {
13+
14+
// TODO consider removing this property when the products in the bag are saved on database or api
15+
private val _bag = MutableStateFlow<List<BagProduct>>(listOf())
16+
17+
// TODO change this implementation to a proper implementation using data base or api to get the products in the bag
18+
override fun getBag(): Flow<RepositoryResult<List<BagProduct>>> {
19+
return _bag.map { bag ->
20+
Result.success(bag).toRepositoryResult()
21+
}
22+
}
23+
24+
// TODO change this implementation to a proper implementation using data base or api to save the product
25+
override fun addToBag(bagProduct: BagProduct): RepositoryResult<Boolean> {
26+
_bag.value = _bag.value.toMutableList().apply { add(bagProduct) }
27+
return RepositoryResult.Success(true)
28+
}
29+
30+
override fun removeFromBag(bagProduct: BagProduct): RepositoryResult<Boolean> {
31+
_bag.value = _bag.value.toMutableList().apply { remove(bagProduct) }
32+
return RepositoryResult.Success(true)
33+
}
34+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package au.com.alfie.ecomm.data.bag.di
2+
3+
import au.com.alfie.ecomm.data.bag.BagRepositoryImpl
4+
import au.com.alfie.ecomm.repository.bag.BagRepository
5+
import dagger.Binds
6+
import dagger.Module
7+
import dagger.hilt.InstallIn
8+
import dagger.hilt.components.SingletonComponent
9+
import javax.inject.Singleton
10+
11+
@Module
12+
@InstallIn(SingletonComponent::class)
13+
internal interface BagModule {
14+
15+
@Binds
16+
@Singleton
17+
fun bindBagRepository(bagRepositoryImpl: BagRepositoryImpl): BagRepository
18+
}

designsystem/src/main/java/au/com/alfie/ecomm/designsystem/component/price/PriceType.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
package au.com.alfie.ecomm.designsystem.component.price
22

3+
import androidx.compose.runtime.Stable
4+
5+
@Stable
36
sealed interface PriceType {
47

8+
@Stable
59
data class Default(
610
val price: String
711
) : PriceType
812

13+
@Stable
914
data class Sale(
1015
val fullPrice: String,
1116
val salePrice: String
1217
) : PriceType
1318

19+
@Stable
1420
data class Range(
1521
val startPrice: String,
1622
val endPrice: String

designsystem/src/main/java/au/com/alfie/ecomm/designsystem/component/productcard/ProductCardType.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ sealed interface ProductCardType {
1616
val image: ImageUI
1717
val brand: String
1818
val name: String
19-
val price: PriceType?
19+
val price: PriceType
2020
val cardTestTag: String
2121
val imageTestTag: String
2222
val brandTestTag: String
@@ -30,6 +30,7 @@ sealed interface ProductCardType {
3030
override val price: PriceType,
3131
val color: String,
3232
val size: String,
33+
val onRemoveClick: ClickEvent? = null,
3334
override val cardTestTag: String = PRODUCT_CARD,
3435
override val imageTestTag: String = PRODUCT_IMAGE,
3536
override val brandTestTag: String = PRODUCT_DESIGNER,
@@ -43,7 +44,7 @@ sealed interface ProductCardType {
4344
override val image: ImageUI,
4445
override val brand: String,
4546
override val name: String,
46-
override val price: PriceType?,
47+
override val price: PriceType,
4748
override val cardTestTag: String = PRODUCT_CARD,
4849
override val imageTestTag: String = PRODUCT_IMAGE,
4950
override val brandTestTag: String = PRODUCT_DESIGNER,

designsystem/src/main/java/au/com/alfie/ecomm/designsystem/component/productcard/size/ProductCardXSmall.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ import androidx.compose.foundation.layout.Spacer
77
import androidx.compose.foundation.layout.fillMaxWidth
88
import androidx.compose.foundation.layout.size
99
import androidx.compose.foundation.layout.width
10+
import androidx.compose.material3.Icon
11+
import androidx.compose.material3.IconButton
1012
import androidx.compose.material3.Text
1113
import androidx.compose.runtime.Composable
1214
import androidx.compose.ui.Modifier
1315
import androidx.compose.ui.platform.testTag
16+
import androidx.compose.ui.res.painterResource
1417
import androidx.compose.ui.res.stringResource
1518
import androidx.compose.ui.text.style.TextOverflow
1619
import androidx.compose.ui.tooling.preview.Preview
@@ -137,6 +140,18 @@ internal fun ProductCardXSmall(
137140
.testTag(productCard.priceTestTag)
138141
)
139142
}
143+
if (isLoading.not() && productCard.onRemoveClick != null) {
144+
IconButton(
145+
modifier = Modifier.size(Theme.iconSize.large),
146+
onClick = productCard.onRemoveClick
147+
) {
148+
Icon(
149+
painter = painterResource(id = R.drawable.ic_action_close_dark),
150+
contentDescription = null,
151+
modifier = Modifier.size(Theme.iconSize.small)
152+
)
153+
}
154+
}
140155
}
141156
}
142157

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package au.com.alfie.ecomm.repository.bag
2+
3+
data class BagProduct(
4+
val productId: String,
5+
val variantSku: String
6+
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package au.com.alfie.ecomm.repository.bag
2+
3+
import au.com.alfie.ecomm.repository.result.RepositoryResult
4+
import kotlinx.coroutines.flow.Flow
5+
6+
interface BagRepository {
7+
8+
fun getBag(): Flow<RepositoryResult<List<BagProduct>>>
9+
10+
fun addToBag(bagProduct: BagProduct): RepositoryResult<Boolean>
11+
12+
fun removeFromBag(bagProduct: BagProduct): RepositoryResult<Boolean>
13+
}

domain/repository/src/main/java/au/com/alfie/ecomm/repository/product/model/Variant.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import au.com.alfie.ecomm.repository.shared.model.Size
77
data class Variant(
88
val attributes: List<Attribute>,
99
val color: Color?,
10-
val media: Media,
10+
val media: Media.Image,
1111
val price: Price,
1212
val size: Size?,
1313
val sku: String,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package au.com.alfie.ecomm.domain.usecase.bag
2+
3+
import au.com.alfie.ecomm.domain.UseCaseInteractor
4+
import au.com.alfie.ecomm.domain.UseCaseResult
5+
import au.com.alfie.ecomm.domain.doOnResult
6+
import au.com.alfie.ecomm.repository.bag.BagProduct
7+
import au.com.alfie.ecomm.repository.bag.BagRepository
8+
import javax.inject.Inject
9+
10+
class AddToBagUseCase @Inject constructor(
11+
private val bagRepository: BagRepository
12+
) : UseCaseInteractor {
13+
14+
suspend operator fun invoke(
15+
productId: String,
16+
variantSku: String
17+
) = run(
18+
bagRepository.addToBag(
19+
BagProduct(
20+
productId = productId,
21+
variantSku = variantSku
22+
)
23+
)
24+
).doOnResult(
25+
onSuccess = { UseCaseResult.Success(it) },
26+
onError = { UseCaseResult.Error(it) }
27+
)
28+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package au.com.alfie.ecomm.domain.usecase.bag
2+
3+
import au.com.alfie.ecomm.domain.UseCaseInteractor
4+
import au.com.alfie.ecomm.domain.UseCaseResult
5+
import au.com.alfie.ecomm.repository.bag.BagProduct
6+
import au.com.alfie.ecomm.repository.bag.BagRepository
7+
import kotlinx.coroutines.flow.Flow
8+
import kotlinx.coroutines.flow.map
9+
import javax.inject.Inject
10+
11+
class GetBagUseCase @Inject constructor(
12+
private val bagRepository: BagRepository
13+
) : UseCaseInteractor {
14+
15+
suspend operator fun invoke(): Flow<UseCaseResult<List<BagProduct>>> =
16+
bagRepository.getBag().map { repositoryResult ->
17+
run(repositoryResult)
18+
}
19+
}

0 commit comments

Comments
 (0)