-
Notifications
You must be signed in to change notification settings - Fork 47
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
[둘리] 3, 4단계 쇼핑 장바구니 제출합니다. #33
Changes from 35 commits
6f04e7e
e7af72c
6977e5f
8c85cf2
723c091
b528d57
fd660c5
e9a1b6c
7181e9b
27b2a1b
dd70d3b
e230169
15dc571
588a1ee
dc79515
7d0a2e3
8f145f4
9370658
0337194
3e7fc30
1c419ad
49e6293
3200e3a
cbcd2f4
01b5db9
57a2b4d
f6d3645
b5e1269
dc3106f
47cb4a5
e23cdba
65cade1
b3e732f
6869b1f
ebdc9bd
ba1d77f
2797d74
5cf4f06
c291ea5
508e204
b04a4af
8d09837
a9268da
9bac38d
261e924
9ec4930
1227d57
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,35 @@ | ||
# android-shopping-cart | ||
## Domain | ||
### ProductRepository | ||
- [ ] 상품 목록을 가져올 수 있다. | ||
- [x] 상품 목록을 가져올 수 있다. | ||
### CartRepository | ||
- [ ] 장바구니의 상품 목록을 가져올 수 있다. | ||
- [ ] 장바구니에 상품을 추가할 수 있다. | ||
- [ ] 장바구니에 상품을 삭제할 수 있다. | ||
### RecentViewedRepository | ||
- [ ] 사용자가 상품의 상세 정보를 조회하면 목록에 추가한다. | ||
- [ ] 만약 10개가 넘어갔을 경우 가장 오래 된 상품을 삭제한다. | ||
- [ ] 최근 본 상품 목록을 가져올 수 있다. | ||
- [x] 장바구니의 상품 목록을 가져올 수 있다. | ||
- [x] 장바구니에 상품을 추가할 수 있다. | ||
- [x] 장바구니에 상품을 삭제할 수 있다. | ||
### Product | ||
- name : 이름 | ||
- imageUrl : 이미지 URL | ||
- price : 가격 | ||
### Price | ||
- price : 가격 | ||
## View | ||
- [ ] 앱이 종료돼도 최근 본 상품 목록과 장바구니 데이터는 유지돼야 한다. | ||
- [x] 앱이 종료돼도 최근 본 상품 목록과 장바구니 데이터는 유지돼야 한다. | ||
### ProductListActivity | ||
- [ ] 상품을 클릭하면 상품 상세로 이동한다. | ||
- [ ] 최근 본 상품이 있는 경우 상품 목록 상단에서 10개까지 확인할 수 있다. | ||
- [x] 상품을 클릭하면 상품 상세로 이동한다. | ||
- [X] 툴바 안의 카트 버튼을 누르면 장바구니로 이동한다. | ||
- [x] 툴바 안의 카트 옆에 장바구니 상품 수가 노출된다. | ||
- [x] 상품 목록의 +버튼을 누르면 장바구니에 상품이 추가된다. | ||
- [x] +버튼을 누른 후 동시에 수량 선택 버튼이 노출된다. | ||
- [x] 상품 목록의 상품 수가 변화하면 장바구니에 반영된다. | ||
- [x] 장바구니 상품 수가 변화하면 상품 목록에도 반영된다. | ||
### ProductDetailActivity | ||
- [ ] 사용자는 상품을 장바구니에 추가할 수 있다. | ||
- [x] 사용자는 상품을 장바구니에 추가할 수 있다. | ||
- [x] 마지막으로 본 상품 1개를 상품 상세 페이지에서 확인할 수 있다. | ||
- [x] 마지막으로 본 상품을 선택했을 때는 마지막으로 본 상품이 보이지 않는다. | ||
- [x] 마지막으로 본 상품 페이지에서 뒤로 가기를 하면 상품 목록으로 이동한다. | ||
### CartActivity | ||
- [ ] 장바구니에서 원하는 상품을 삭제할 수 있다. | ||
- [x] 장바구니에서 원하는 상품을 삭제할 수 있다. | ||
- [X] 툴바 안의 백버튼을 누르면 뒤로 이동한다. | ||
|
||
- [x] 체크박스로 주문할 상품 범위를 조정할 할 수 있다. | ||
- [x] 전체 체크박스를 선택하면 해당 페이지 내의 상품들만 선택된다. | ||
- [x] 페이지가 바뀌어도 선택 항목은 유지된다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
package woowacourse.shopping.model | ||
|
||
import woowacourse.shopping.domain.CartProduct | ||
import woowacourse.shopping.domain.Product | ||
import woowacourse.shopping.domain.model.CartProduct | ||
import woowacourse.shopping.domain.model.Product | ||
|
||
fun CartProduct.toUiModel(product: Product): CartProductModel = | ||
CartProductModel(id, product.name, product.imageUrl, count, product.price.price * count) | ||
fun CartProduct.toUiModel(isChecked: Boolean = false, product: Product): CartProductModel = | ||
CartProductModel(isChecked, id, product.name, product.imageUrl, count, product.price.price) | ||
|
||
fun CartProductModel.toDomain(): CartProduct = CartProduct(id, count) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
package woowacourse.shopping.model | ||
|
||
data class CartProductModel(val id: Int, val name: String, val imageUrl: String, val count: Int, val totalPrice: Int) | ||
data class CartProductModel(var isChecked: Boolean, val id: Int, val name: String, val imageUrl: String, var count: Int, val price: Int) | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
package woowacourse.shopping.model | ||
|
||
import woowacourse.shopping.domain.Product | ||
import woowacourse.shopping.domain.model.Product | ||
|
||
fun Product.toUiModel() = ProductModel(id, name, imageUrl, price.price) | ||
fun Product.toUiModel(count: Int = 0) = ProductModel(id, name, imageUrl, price.price, count) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,34 +5,46 @@ import android.content.Intent | |
import android.os.Bundle | ||
import android.view.MenuItem | ||
import androidx.appcompat.app.AppCompatActivity | ||
import woowacourse.shopping.data.CartDbRepository | ||
import woowacourse.shopping.data.ProductMockRepository | ||
import woowacourse.shopping.data.repository.CartDbRepository | ||
import woowacourse.shopping.domain.repository.ProductRemoteRepository | ||
import woowacourse.shopping.databinding.ActivityCartBinding | ||
import woowacourse.shopping.domain.data.MockServer | ||
import woowacourse.shopping.model.CartProductModel | ||
import woowacourse.shopping.view.productlist.ProductListActivity | ||
|
||
class CartActivity : AppCompatActivity(), CartContract.View { | ||
private lateinit var mockWebServer: MockServer | ||
private lateinit var binding: ActivityCartBinding | ||
private lateinit var presenter: CartContract.Presenter | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
setUpMockServer() | ||
setUpPresenter() | ||
setUpBinding() | ||
setContentView(binding.root) | ||
setUpActionBar() | ||
setUpPresenter() | ||
presenter.fetchProducts() | ||
} | ||
|
||
private fun setUpMockServer() { | ||
val thread = Thread { mockWebServer = MockServer() } | ||
thread.start() | ||
thread.join() | ||
} | ||
Comment on lines
+35
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MockWebServer를 초기화하는 코드를 잘 구현해주셨네요. 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MockWebServer를 구동시키는 것이 View의 역할이 아닌 것 같다고 생각하고 있었으나, Presenter에게 MockWebServer의 url을 넘겨주어야해서 어떻게 수정해야할지 잘 모르겠습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MockWebServer의 url이 아닌 MockWebServer를 넘기도록 구현해도 되지 않을까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 지금은 MockWebServer을 사용하니까 그래도 되겠네요! |
||
|
||
private fun setUpBinding() { | ||
binding = ActivityCartBinding.inflate(layoutInflater) | ||
binding.lifecycleOwner = this | ||
binding.presenter = presenter | ||
} | ||
|
||
private fun setUpActionBar() { | ||
supportActionBar?.setDisplayHomeAsUpEnabled(true) | ||
supportActionBar?.title = TITLE | ||
} | ||
|
||
private fun setUpPresenter() { | ||
presenter = CartPresenter(this, CartDbRepository(this), ProductMockRepository) | ||
presenter = CartPresenter(this, CartDbRepository(this), ProductRemoteRepository(mockWebServer.url)) | ||
} | ||
|
||
override fun showProducts(items: List<CartViewItem>) { | ||
|
@@ -50,29 +62,37 @@ class CartActivity : AppCompatActivity(), CartContract.View { | |
override fun onPrevClick() { | ||
presenter.fetchPrevPage() | ||
} | ||
|
||
override fun onUpdateCount(id: Int, count: Int) { | ||
presenter.updateCartProductCount(id, count) | ||
} | ||
|
||
override fun onSelectProduct(product: CartProductModel) { | ||
presenter.checkProduct(product) | ||
} | ||
} | ||
) | ||
} | ||
|
||
override fun showOtherPage() { | ||
override fun showChangedItems() { | ||
binding.recyclerCart.adapter?.notifyDataSetChanged() | ||
} | ||
|
||
override fun notifyRemoveItem(position: Int) { | ||
binding.recyclerCart.adapter?.notifyItemRemoved(position) | ||
override fun showChangedItem(position: Int) { | ||
binding.recyclerCart.adapter?.notifyItemChanged(position) | ||
} | ||
|
||
override fun onOptionsItemSelected(item: MenuItem): Boolean { | ||
when (item.itemId) { | ||
android.R.id.home -> { | ||
setResult(ProductListActivity.RESULT_VISIT_CART, intent) | ||
finish() | ||
} | ||
} | ||
return super.onOptionsItemSelected(item) | ||
} | ||
|
||
companion object { | ||
private const val TITLE = "Cart" | ||
fun newIntent(context: Context): Intent = Intent(context, CartActivity::class.java) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,28 @@ | ||
package woowacourse.shopping.view.cart | ||
|
||
import androidx.lifecycle.LiveData | ||
import woowacourse.shopping.domain.cartsystem.CartPageStatus | ||
import woowacourse.shopping.domain.cartsystem.CartSystemResult | ||
import woowacourse.shopping.model.CartProductModel | ||
|
||
interface CartContract { | ||
interface View { | ||
fun showProducts(items: List<CartViewItem>) | ||
fun notifyRemoveItem(position: Int) | ||
fun showOtherPage() | ||
fun showChangedItems() | ||
fun showChangedItem(position: Int) | ||
} | ||
|
||
interface Presenter { | ||
val cartSystemResult: LiveData<CartSystemResult> | ||
val cartPageStatus: LiveData<CartPageStatus> | ||
val isCheckedAll: LiveData<Boolean> | ||
|
||
fun fetchProducts() | ||
fun removeProduct(id: Int) | ||
fun fetchNextPage() | ||
fun fetchPrevPage() | ||
fun removeProduct(id: Int) | ||
fun updateCartProductCount(id: Int, count: Int) | ||
fun checkProduct(product: CartProductModel) | ||
fun checkProductsAll() | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
data class에서 isChecked 변수를 variable로 정의하셨네요.
var로 선언하게되면 외부에서 isChecked에 접근하여 얼마든지 상태를 변경할 수 있기 때문에, isChecked 를 참조하고 있는 곳에 예상치 못한 동작이 발생할 수 있어요.
외부에서 변경하지 못하도록 개선해보면 어떨까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
valuable로 수정하고 프레젠터에서 리스트의 아이템을 복사해서 다시 넣어주도록 수정했습니다!