Skip to content

Commit 8f35d06

Browse files
authored
feat: checkout screen cleanup (#12)
1 parent 35e3264 commit 8f35d06

26 files changed

+695
-316
lines changed

core-sdk-samples/higgs-shop-sample-app/app/src/main/kotlin/com/mparticle/example/higgsshopsampleapp/activities/CheckoutActivity.kt

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,17 @@ import androidx.recyclerview.widget.LinearLayoutManager
1414
import com.google.android.material.snackbar.BaseTransientBottomBar
1515
import com.google.android.material.snackbar.Snackbar
1616
import com.mparticle.MParticle
17+
import com.mparticle.commerce.CommerceEvent
18+
import com.mparticle.commerce.Product
19+
import com.mparticle.commerce.TransactionAttributes
1720
import com.mparticle.example.higgsshopsampleapp.R
1821
import com.mparticle.example.higgsshopsampleapp.adapters.CheckoutItemsAdapter
1922
import com.mparticle.example.higgsshopsampleapp.databinding.ActivityCheckoutBinding
23+
import com.mparticle.example.higgsshopsampleapp.repositories.database.entities.CartItemEntity
2024
import com.mparticle.example.higgsshopsampleapp.utils.Constants
2125
import com.mparticle.example.higgsshopsampleapp.viewmodels.CheckoutViewModel
26+
import java.math.BigDecimal
27+
import java.util.Calendar
2228

2329

2430
class CheckoutActivity : AppCompatActivity() {
@@ -46,12 +52,16 @@ class CheckoutActivity : AppCompatActivity() {
4652
) { priceMap ->
4753
binding.tvPaymentSubtotalPrice.text = "$${priceMap["subTotal"]}"
4854
binding.tvPaymentTaxPrice.text = "$${priceMap["salesTax"]}"
49-
binding.tvPaymentShippingPrice.text = "$${Constants.CHECKOUT_SHIPPING_COST}"
55+
binding.tvPaymentShippingPrice.text = "$${priceMap["shipping"]}"
5056
binding.tvPaymentGrandPrice.text = "$${priceMap["grandTotal"]}"
5157

58+
var event = commerceEventConversion(priceMap, Product.CHECKOUT)
59+
MParticle.getInstance()?.logEvent(event)
60+
5261
val btnCTA = findViewById(R.id.payment_cta) as Button
5362
btnCTA.setOnClickListener {
54-
val cartItems = priceMap["cartItems"]
63+
event = commerceEventConversion(priceMap, Product.PURCHASE)
64+
MParticle.getInstance()?.logEvent(event)
5565
showPurchaseAlert()
5666
btnCTA.isEnabled = false
5767
checkoutViewModel.clearCart(this)
@@ -100,4 +110,38 @@ class CheckoutActivity : AppCompatActivity() {
100110
snackbar.animationMode = BaseTransientBottomBar.ANIMATION_MODE_FADE
101111
snackbar.show()
102112
}
113+
114+
fun commerceEventConversion(priceMap: Map<String, Any>, productAction: String): CommerceEvent {
115+
val cartItems = priceMap["cartItems"] as List<CartItemEntity>
116+
var entity = cartItems.get(0)
117+
val product = Product.Builder(entity.label, entity.id.toString(), entity.price.toDouble())
118+
.customAttributes(mapOf(
119+
"size" to entity.size,
120+
"color" to entity.color
121+
))
122+
.quantity(entity.quantity.toDouble())
123+
.build()
124+
val event = CommerceEvent.Builder(productAction, product)
125+
for (i in 1 until cartItems.size) {
126+
entity = cartItems.get(i)
127+
val product2 = Product.Builder(entity.label, entity.id.toString(), entity.price.toDouble())
128+
.customAttributes(mapOf(
129+
"size" to entity.size,
130+
"color" to entity.color
131+
))
132+
.quantity(entity.quantity.toDouble())
133+
.build()
134+
event.addProduct(product2)
135+
}
136+
137+
if(productAction == Product.PURCHASE) {
138+
val attributes: TransactionAttributes = TransactionAttributes(Calendar.getInstance().time.toString())
139+
.setRevenue(priceMap["grandTotal"].toString().toDouble())
140+
.setTax(priceMap["salesTax"].toString().toDouble())
141+
.setShipping(BigDecimal(Constants.CHECKOUT_SHIPPING_COST).toDouble())
142+
event.transactionAttributes(attributes)
143+
}
144+
145+
return event.build()
146+
}
103147
}

core-sdk-samples/higgs-shop-sample-app/app/src/main/kotlin/com/mparticle/example/higgsshopsampleapp/activities/ProductDetailActivity.kt

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@ import android.graphics.drawable.ColorDrawable
55
import android.net.Uri
66
import android.os.Bundle
77
import android.util.Log
8-
import android.view.Gravity
98
import android.view.View
109
import android.widget.ArrayAdapter
10+
import android.widget.AutoCompleteTextView
1111
import android.widget.TextView
1212
import androidx.appcompat.app.AppCompatActivity
1313
import androidx.lifecycle.Observer
1414
import androidx.lifecycle.ViewModelProvider
15-
import androidx.navigation.Navigation
1615
import com.bumptech.glide.Glide
1716
import com.google.android.material.snackbar.BaseTransientBottomBar
1817
import com.google.android.material.snackbar.Snackbar
@@ -80,54 +79,78 @@ class ProductDetailActivity : AppCompatActivity() {
8079
.centerCrop()
8180
.into(binding.ivDetailImage)
8281

82+
val dropdownColors = binding.dropdownColors.editText as? AutoCompleteTextView
8383
if(productItem.variants?.colors?.isNotEmpty() ?: false) {
84-
val arrayAdapter: ArrayAdapter<*>
85-
arrayAdapter = ArrayAdapter(
84+
val colorAdapter: ArrayAdapter<*>
85+
colorAdapter = ArrayAdapter(
8686
this,
87-
R.layout.shop_detail_spinner_item,
87+
R.layout.shop_detail_spinner_item_popup,
8888
productItem.variants?.colors ?: listOf()
8989
)
90-
arrayAdapter.setDropDownViewResource(R.layout.shop_detail_spinner_item_popup)
91-
binding.spinnerColors.visibility = View.VISIBLE
92-
binding.spinnerColors.adapter = arrayAdapter
90+
dropdownColors?.setAdapter(colorAdapter)
91+
dropdownColors?.setOnClickListener {
92+
dropdownColors.showDropDown()
93+
}
94+
dropdownColors?.setOnItemClickListener { _, _, position, _ ->
95+
detailViewModel.color = colorAdapter.getItem(position).toString()
96+
}
97+
detailViewModel.color = colorAdapter.getItem(0).toString()
98+
dropdownColors?.setText(detailViewModel.color, false)
99+
binding.dropdownColors.visibility = View.VISIBLE
93100
} else {
94-
binding.spinnerColors.visibility = View.GONE
101+
binding.dropdownColors.visibility = View.GONE
95102
}
96103

104+
val dropdownSizes = binding.dropdownSizes.editText as? AutoCompleteTextView
97105
if(productItem.variants?.sizes?.isNotEmpty() ?: false) {
98-
val arrayAdapter: ArrayAdapter<*>
99-
arrayAdapter = ArrayAdapter(
106+
val sizeAdapter: ArrayAdapter<*>
107+
sizeAdapter = ArrayAdapter(
100108
this,
101-
R.layout.shop_detail_spinner_item,
109+
R.layout.shop_detail_spinner_item_popup,
102110
productItem.variants?.sizes ?: listOf()
103111
)
104-
arrayAdapter.setDropDownViewResource(R.layout.shop_detail_spinner_item_popup)
105-
binding.spinnerSizes.visibility = View.VISIBLE
106-
binding.spinnerSizes.adapter = arrayAdapter
112+
dropdownSizes?.setAdapter(sizeAdapter)
113+
dropdownSizes?.setOnClickListener {
114+
dropdownSizes.showDropDown()
115+
}
116+
dropdownSizes?.setOnItemClickListener { _, _, position, _ ->
117+
detailViewModel.size = sizeAdapter.getItem(position).toString()
118+
}
119+
detailViewModel.size = sizeAdapter.getItem(0).toString()
120+
dropdownSizes?.setText(detailViewModel.size, false)
121+
binding.dropdownSizes.visibility = View.VISIBLE
107122
} else {
108-
binding.spinnerSizes.visibility = View.GONE
123+
binding.dropdownSizes.visibility = View.GONE
109124
}
110125

111-
val arrayAdapter: ArrayAdapter<*>
112-
arrayAdapter = ArrayAdapter(
126+
val quantityAdapter: ArrayAdapter<*>
127+
quantityAdapter = ArrayAdapter(
113128
this,
114-
R.layout.shop_detail_spinner_item,
129+
R.layout.shop_detail_spinner_item_popup,
115130
listOf("1","2","3","4","5","6","7","8")
116131
)
117-
arrayAdapter.setDropDownViewResource(R.layout.shop_detail_spinner_item_popup)
118-
binding.spinnerQty.adapter = arrayAdapter
132+
val dropdownQuantity = binding.dropdownQuantity.editText as? AutoCompleteTextView
133+
dropdownQuantity?.setAdapter(quantityAdapter)
134+
dropdownQuantity?.setOnClickListener {
135+
dropdownQuantity.showDropDown()
136+
}
137+
dropdownQuantity?.setOnItemClickListener { _, _, position, _ ->
138+
detailViewModel.quantity = Integer.parseInt(quantityAdapter.getItem(position).toString())
139+
}
140+
detailViewModel.quantity = Integer.parseInt(quantityAdapter.getItem(0).toString())
141+
dropdownQuantity?.setText(detailViewModel.quantity.toString(), false)
119142

120143
binding.detailCta.setOnClickListener {
121-
val sku = "${productItem.id}-${binding.spinnerColors.selectedItem}-${binding.spinnerSizes.selectedItem}"
144+
val sku = "${productItem.id}-${detailViewModel.color}-${detailViewModel.size}"
122145
val entity = CartItemEntity(
123146
sku = sku,
124147
id = productItem.id,
125148
label = productItem.label,
126149
imageUrl = productItem.imageUrl,
127-
color = binding.spinnerColors.selectedItem?.toString(),
128-
size = binding.spinnerSizes.selectedItem?.toString(),
150+
color = detailViewModel.color,
151+
size = detailViewModel.size,
129152
price = productItem.price,
130-
quantity = Integer.parseInt(binding.spinnerQty.selectedItem.toString())
153+
quantity = detailViewModel.quantity
131154
)
132155
detailViewModel.addToCart(this.applicationContext, entity)
133156
}

core-sdk-samples/higgs-shop-sample-app/app/src/main/kotlin/com/mparticle/example/higgsshopsampleapp/adapters/CartItemsAdapter.kt

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ class CartItemsAdapter() :
4848
viewHolder.tvPrice.text = "$${BigDecimal(list[position].price)
4949
.setScale(2, BigDecimal.ROUND_HALF_UP)}"
5050

51-
var quantity = "Qty: ${list[position].quantity}"
52-
list[position].color?.apply { quantity += ", Color: ${list[position].color}" }
53-
list[position].size?.apply { quantity += ", Size: ${list[position].size}" }
54-
viewHolder.tvQuantity.text = quantity
51+
var line1 = "Qty: ${list[position].quantity}"
52+
list[position].color?.apply { line1 += ", Color: ${list[position].color}" }
53+
list[position].size?.apply { line1 += ", Size: ${list[position].size}" }
54+
viewHolder.tvLine1.text = line1
5555

5656
Glide.with(viewHolder.itemView.context)
5757
.load(
@@ -66,19 +66,17 @@ class CartItemsAdapter() :
6666
inner class CartItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
6767
val intent: Intent? = null
6868
var ivImage: ImageView
69-
var tvSku: TextView
7069
var tvLabel: TextView
7170
var tvPrice: TextView
72-
var tvQuantity: TextView
73-
var tvRemove: TextView
71+
var tvLine1: TextView
72+
var tvLine2: TextView
7473

7574
init {
7675
ivImage = itemView.findViewById(R.id.iv_cart_item_picture)
77-
tvSku = itemView.findViewById(R.id.tv_cart_item_sku)
7876
tvLabel = itemView.findViewById(R.id.tv_cart_item_label)
7977
tvPrice = itemView.findViewById(R.id.tv_cart_item_price)
80-
tvQuantity = itemView.findViewById(R.id.tv_cart_item_quantity)
81-
tvRemove = itemView.findViewById(R.id.tv_cart_item_remove)
78+
tvLine1 = itemView.findViewById(R.id.tv_cart_item_line1)
79+
tvLine2 = itemView.findViewById(R.id.tv_cart_item_line2)
8280

8381
itemView.setOnClickListener {
8482
onItemClicked?.invoke(list[absoluteAdapterPosition], absoluteAdapterPosition)
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,52 @@
11
package com.mparticle.example.higgsshopsampleapp.adapters
22

3-
import com.mparticle.example.higgsshopsampleapp.repositories.CartRepository
43
import com.mparticle.example.higgsshopsampleapp.repositories.database.entities.CartItemEntity
54

65
import android.content.Intent
76
import android.net.Uri
87
import android.view.LayoutInflater
98
import android.view.View
109
import android.view.ViewGroup
11-
import android.widget.Button
1210
import android.widget.ImageView
1311
import android.widget.TextView
14-
import androidx.lifecycle.viewModelScope
1512
import androidx.recyclerview.widget.RecyclerView
1613
import com.bumptech.glide.Glide
1714
import com.mparticle.example.higgsshopsampleapp.R
1815
import java.math.BigDecimal
19-
import java.math.RoundingMode
20-
import java.text.DecimalFormat
2116

2217

2318
class CheckoutItemsAdapter() :
24-
RecyclerView.Adapter<CheckoutItemsAdapter.CartItemViewHolder>() {
19+
RecyclerView.Adapter<CheckoutItemsAdapter.CheckoutItemViewHolder>() {
2520

2621
var list = mutableListOf<CartItemEntity>()
2722
set(value) {
2823
field = value
2924
notifyDataSetChanged()
3025
}
3126

32-
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CartItemViewHolder {
27+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CheckoutItemsAdapter.CheckoutItemViewHolder {
3328
val view = LayoutInflater.from(parent.context)
34-
.inflate(R.layout.cart_product_item, parent, false)
35-
return CartItemViewHolder(view)
29+
.inflate(R.layout.checkout_product_item, parent, false)
30+
return CheckoutItemViewHolder(view)
3631
}
3732

3833
override fun getItemCount(): Int {
3934
return list.size
4035
}
4136

42-
override fun onBindViewHolder(viewHolder: CartItemViewHolder, position: Int) {
37+
override fun onBindViewHolder(viewHolder: CheckoutItemsAdapter.CheckoutItemViewHolder, position: Int) {
4338
viewHolder.tvLabel.text = list[position].label
4439

4540
viewHolder.tvPrice.text = "$${BigDecimal(list[position].price)
4641
.setScale(2, BigDecimal.ROUND_HALF_UP)}"
47-
var quantity = "Qty: ${list[position].quantity}"
48-
list[position].color?.apply { quantity += ", Color: ${list[position].color}" }
49-
list[position].size?.apply { quantity += ", Size: ${list[position].size}" }
50-
viewHolder.tvQuantity.text = quantity
42+
viewHolder.tvLine1.text = "Qty: ${list[position].quantity}"
43+
var line2 = ""
44+
list[position].color?.apply { line2 += "Color: ${list[position].color}" }
45+
list[position].size?.apply {
46+
if(line2.isNotEmpty()) { line2 += ", " }
47+
line2 += " Size: ${list[position].size}"
48+
}
49+
viewHolder.tvLine2.text = line2
5150

5251
Glide.with(viewHolder.itemView.context)
5352
.load(
@@ -56,26 +55,22 @@ class CheckoutItemsAdapter() :
5655
.override(100,56)
5756
.centerCrop()
5857
.into(viewHolder.ivImage)
59-
60-
viewHolder.tvRemove.visibility = View.INVISIBLE
6158
}
6259

63-
inner class CartItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
60+
inner class CheckoutItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
6461
val intent: Intent? = null
6562
var ivImage: ImageView
66-
var tvSku: TextView
6763
var tvLabel: TextView
6864
var tvPrice: TextView
69-
var tvQuantity: TextView
70-
var tvRemove: TextView
65+
var tvLine1: TextView
66+
var tvLine2: TextView
7167

7268
init {
73-
ivImage = itemView.findViewById(R.id.iv_cart_item_picture)
74-
tvSku = itemView.findViewById(R.id.tv_cart_item_sku)
75-
tvLabel = itemView.findViewById(R.id.tv_cart_item_label)
76-
tvPrice = itemView.findViewById(R.id.tv_cart_item_price)
77-
tvQuantity = itemView.findViewById(R.id.tv_cart_item_quantity)
78-
tvRemove = itemView.findViewById(R.id.tv_cart_item_remove)
69+
ivImage = itemView.findViewById(R.id.iv_checkout_item_picture)
70+
tvLabel = itemView.findViewById(R.id.tv_checkout_item_label)
71+
tvPrice = itemView.findViewById(R.id.tv_checkout_item_price)
72+
tvLine1 = itemView.findViewById(R.id.tv_checkout_item_line1)
73+
tvLine2 = itemView.findViewById(R.id.tv_checkout_item_line2)
7974
}
8075
}
8176
}

core-sdk-samples/higgs-shop-sample-app/app/src/main/kotlin/com/mparticle/example/higgsshopsampleapp/fragments/AccountFragment.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package com.mparticle.example.higgsshopsampleapp.fragments
22

3+
import android.app.ActionBar
34
import android.os.Bundle
45
import android.view.LayoutInflater
56
import android.view.View
67
import android.view.ViewGroup
78
import android.widget.Button
9+
import android.widget.TextView
810
import androidx.fragment.app.Fragment
911
import androidx.lifecycle.ViewModelProvider
12+
import com.google.android.material.snackbar.BaseTransientBottomBar
13+
import com.google.android.material.snackbar.Snackbar
1014
import com.mparticle.MParticle
1115
import com.mparticle.example.higgsshopsampleapp.R
1216
import com.mparticle.example.higgsshopsampleapp.activities.MainActivity
@@ -44,9 +48,11 @@ class AccountFragment : Fragment() {
4448
when(loggedIn) {
4549
false -> {
4650
btnCTA.text = getString(R.string.account_cta_login)
51+
showIdentityAlert("Logout Successful")
4752
}
4853
true -> {
4954
btnCTA.text = getString(R.string.account_cta_logout)
55+
showIdentityAlert("Login Successful")
5056
}
5157
}
5258
})
@@ -69,7 +75,24 @@ class AccountFragment : Fragment() {
6975
accountViewModel.logout()
7076
}
7177
}
78+
else -> {}
7279
}
7380
}
7481
}
82+
83+
fun showIdentityAlert(message: String) {
84+
val parentLayout: View = requireActivity().findViewById(android.R.id.content)
85+
val snackbar = Snackbar.make(parentLayout, message, Snackbar.LENGTH_SHORT)
86+
val layoutParams = ActionBar.LayoutParams(snackbar.view.layoutParams)
87+
88+
val tv = (snackbar.view.findViewById<TextView>(R.id.snackbar_text))
89+
tv?.textAlignment = View.TEXT_ALIGNMENT_CENTER
90+
91+
snackbar.setBackgroundTint(requireContext().getColor(R.color.blue_4079FE))
92+
snackbar.setTextColor(requireContext().getColor(R.color.white))
93+
snackbar.view.layoutParams = layoutParams
94+
snackbar.view.setPadding(0, 10, 0, 0)
95+
snackbar.animationMode = BaseTransientBottomBar.ANIMATION_MODE_FADE
96+
snackbar.show()
97+
}
7598
}

0 commit comments

Comments
 (0)