Skip to content

Instantly share code, notes, and snippets.

@photizzo
Created August 24, 2022 16:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save photizzo/4839e03a21ac158592bc12023b671fc7 to your computer and use it in GitHub Desktop.
Save photizzo/4839e03a21ac158592bc12023b671fc7 to your computer and use it in GitHub Desktop.
package co.tractionapp.traction.main.pages.products
import android.app.Activity.RESULT_OK
import android.app.Dialog
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.*
import co.tractionapp.data.room.objects.TractionProductCategory
import co.tractionapp.data.room.objects.TractionProductVariants
import co.tractionapp.data.room.objects.TractionProducts
import co.tractionapp.domain.states.*
import co.tractionapp.traction.R
import co.tractionapp.traction.exts.message
import co.tractionapp.traction.exts.observe
import co.tractionapp.traction.exts.withViewModel
import co.tractionapp.traction.factory.interfaces.FactoryEventsAdapter
import co.tractionapp.traction.factory.models.UIField
import co.tractionapp.traction.factory.models.uiFields.*
import co.tractionapp.traction.factory.pageFactory.ProductFactory
import co.tractionapp.traction.factory.pageFactory.ProductFactory.Keys.CategoryKey
import co.tractionapp.traction.factory.pageFactory.ProductFactory.Keys.HasVariationKey
import co.tractionapp.traction.factory.pageFactory.ProductFactory.Keys.ItemNameKey
import co.tractionapp.traction.factory.pageFactory.ProductFactory.Keys.PriceKey
import co.tractionapp.traction.main.Constants
import co.tractionapp.traction.main.Constants.ITEM_NAME
import co.tractionapp.traction.main.Constants.SELLING_PRICE
import co.tractionapp.traction.main.pages.products.interfaces.CreateProductCallback
import co.tractionapp.traction.main.pages.products.vms.ProductCreateItemVM
import co.tractionapp.traction.main.pages.products.vms.ProductCreateVMFactory
import co.tractionapp.traction.main.pages.settings.enums.TourGuideEnum
import co.tractionapp.traction.main.pages.settings.support.TourGuideMap
import co.tractionapp.traction.main.sharedScreens.PagesFragment
import it.sephiroth.android.library.xtooltip.ClosePolicy
import it.sephiroth.android.library.xtooltip.Tooltip
import kotlinx.android.synthetic.main.dialog_barcode_action.view.*
import kotlinx.android.synthetic.main.item_contained_outline_button.*
import kotlinx.android.synthetic.main.page_item_preview.*
import kotlinx.android.synthetic.main.page_product_create.*
import pub.devrel.easypermissions.EasyPermissions
open class ProductCreateItem : PagesFragment(), EasyPermissions.PermissionCallbacks {
private var productsVM: ProductCreateItemVM? = null
private var tractionProducts: TractionProducts? = null
private var isEditProduct: Boolean = false
lateinit var variantInEdit: ProductVariantField
private var itemListener: CreateProductCallback? = null
private var handler: Handler? = null
private var productName: String? = null
private var productSellingPrice: String? = null
private var isCreateProductTour = false
companion object {
fun newInstance(tractionProducts: TractionProducts?, listener: CreateProductCallback): ProductCreateItem {
val arg = Bundle().apply {
putSerializable(Constants.DATA_KEY, tractionProducts)
}
return ProductCreateItem().apply {
setCreateProductListener(listener)
arguments = arg
}
}
}
val RC_STORAGE = 1
override fun onPermissionsDenied(requestCode: Int, perms: MutableList<String>) {
activity?.onBackPressed()
}
override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) {
ui()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.page_product_create, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
EasyPermissions.requestPermissions(
this, getString(R.string.rationale_storage),
RC_STORAGE, android.Manifest.permission.READ_EXTERNAL_STORAGE
, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.CAMERA
)
}
private fun ui() {
arguments?.getSerializable("data")?.let {
tractionProducts = it as TractionProducts
isEditProduct = true
}
itemListener?.onSaveProductItem(factoryItemsAdapter)
isCreateProductTour = TourGuideMap.isKeyedTourActive(TourGuideEnum.PRODUCT_TOUR.name)
updateProductFromRecordSalesOrExistingProductList()
productsVM = withViewModel(ProductCreateVMFactory(tractionProducts)) {
observe(productsData, ::update)
observe(productCreate, ::productCreationUpdate)
observe(enableSaveBtn, ::saveBtnStateObs)
}
clickListeners()
recyclerAdapterListener()
}
private fun updateProductFromRecordSalesOrExistingProductList() {
activity?.let {
productName = it.intent.getStringExtra(ITEM_NAME)
productSellingPrice = it.intent.getStringExtra(SELLING_PRICE)
}
if(isEditProduct) {
tractionProducts = TractionProducts(
name = productName ?: tractionProducts!!.name,
price = productSellingPrice?.toDouble() ?: tractionProducts!!.price,
category = tractionProducts?.category ?: "",
costPrice = tractionProducts?.costPrice ?: 0.0,
description = tractionProducts?.description ?: "",
image = tractionProducts?.image ?: "",
stock = tractionProducts?.stock,
manage_stock = tractionProducts?.manage_stock ?: false,
in_stock = tractionProducts?.in_stock ?: false,
sku = tractionProducts?.sku,
variations = tractionProducts?.variations ?: false,
varieties = tractionProducts?.varieties ?: mutableListOf(),
combo = tractionProducts?.combo ?: false,
combos = tractionProducts?.combos ?: mutableListOf(),
store_stock = tractionProducts?.store_stock ?: mutableListOf()
)
}
}
private fun saveBtnStateObs(shouldEnableSaveBtn: Boolean?) {
shouldEnableSaveBtn?.let {
val createMain = this@ProductCreateItem.parentFragment as? ProductCreateMain
createMain?.btn_action_field?.let { btn ->
btn.isEnabled = it
}
}
}
private fun recyclerAdapterListener() {
factory_recycler.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (isCreateProductTour) {
startProductItemCreateTour()
}
val itemInd = factoryItemsAdapter.fieldIndexWithKey(ItemNameKey)
val categoryInd = factoryItemsAdapter.fieldIndexWithKey(CategoryKey)
val priceInd = factoryItemsAdapter.fieldIndexWithKey(PriceKey)
if (itemInd != -1 && categoryInd != -1 && priceInd != -1) {
productsVM?.validCreateItemEnableSaveBtn(factoryItemsAdapter)
factory_recycler.viewTreeObserver.removeOnGlobalLayoutListener(this)
}
}
})
}
private fun startProductItemCreateTour() {
val adcView = factoryItemsAdapter.fieldWithKey(ItemNameKey)?.fieldItemView()
adcView?.let {
showToolTip(it, R.string.enter_product_name_with_example,
closePolicy = ClosePolicy.TOUCH_ANYWHERE_CONSUME)
}
}
private fun clickListeners() {
setAdapterEvent(object : FactoryEventsAdapter() {
override fun onActionFieldClicked(uiFieldKey: String, checked: Boolean) {
when (uiFieldKey) {
HasVariationKey -> {
if (!factoryItemsAdapter.isOnBind()) {
productsVM?.switchFormBasedOnVariations(
factoryItemsAdapter,
tractionProducts,
checked
)
productsVM?.deleteCachedVariants()
}
productsVM?.validCreateItemEnableSaveBtn(factoryItemsAdapter)
}
ItemNameKey -> {
if (isCreateProductTour) {
val categoryIndex = factoryItemsAdapter.fieldIndexWithKey(CategoryKey)
val categoryView = factoryItemsAdapter.fieldWithKey(CategoryKey)?.fieldItemView()
factory_recycler.scrollToPosition(categoryIndex)
// tour tooltip
categoryView?.let {
showToolTip(it, R.string.select_item_category)
}
}
}
PriceKey -> {
if (isCreateProductTour) {
val lastIndex = factoryItemsAdapter.items().lastIndex
factory_recycler.scrollToPosition(lastIndex)
val createMain =
this@ProductCreateItem.parentFragment as? ProductCreateMain
createMain?.include8?.let {
showToolTip(it, R.string.click_on_save, Tooltip.Gravity.TOP)
}
}
}
}
}
override fun onItemClicked(uiField: UIField, params: Any) {
when (uiField) {
is ProductImageField -> {
showCameraSelectDialog()
}
is OutlineTextInputField -> {
tooltip?.dismiss()
selectCategory()
}
is RoundedCornerInputField -> {
productsVM?.validCreateItemEnableSaveBtn(factoryItemsAdapter)
}
is AmountRoundInputField -> {
productsVM?.validCreateItemEnableSaveBtn(factoryItemsAdapter)
}
is AddItemField -> {
if (uiField.key == ProductFactory.Keys.AddVariationItemKey) {
addProductVariant()
} else {
selectProduct()
}
}
is BarcodeField -> {
showBarcodeDialog()
}
is ProductVariantField -> {
variantInEdit = uiField
editProductVariant(variantInEdit.dataSource as TractionProductVariants)
}
}
}
})
}
private fun showBarcodeDialog() {
val dialog = Dialog(requireContext(), android.R.style.Theme_Translucent).also {
it.requestWindowFeature(Window.FEATURE_NO_TITLE)
val view = LayoutInflater.from(context).inflate(R.layout.dialog_barcode_action, null, false).apply {
btn_generate_code.setOnClickListener { _ ->
showProgress()
productsVM?.generateBarcode()
it.dismiss()
}
btn_scan_code.setOnClickListener { _ ->
it.dismiss()
scanBarcode()
}
container.setOnClickListener { _ ->
it.dismiss()
}
}
it.setContentView(view)
}
dialog.show()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CAPTURE_IMAGE && resultCode == RESULT_OK) {
handler = Handler(Looper.getMainLooper())
itemListener?.onSaveProductItem(factoryItemsAdapter) ?: kotlin.run {
itemListener = this.parentFragment as ProductCreateMain
itemListener?.onSaveProductItem(factoryItemsAdapter)
}
handler?.postDelayed(
{
productsVM?.updateProductImage(factoryItemsAdapter, photoPathUri.toString())
}, 1000
)
} else {
data?.let {
it.data?.let {
activity?.grantUriPermission(requireContext().packageName, it, Intent.FLAG_GRANT_READ_URI_PERMISSION)
val takeFlags = data.flags and Intent.FLAG_GRANT_READ_URI_PERMISSION
context?.contentResolver?.takePersistableUriPermission(it, takeFlags)
productsVM?.updateProductImage(factoryItemsAdapter, it.toString())
}
}
}
if (requestCode == ADD_PRODUCT_VARIANT && resultCode == RESULT_OK) {
(data?.getSerializableExtra("data") as TractionProductVariants).let {
productsVM?.addProductVariantItemToList(factoryItemsAdapter, it)
}
}
if (requestCode == EDIT_PRODUCT_VARIANT && resultCode == RESULT_OK) {
(data?.getSerializableExtra("data") as TractionProductVariants).let {
val editedId = (variantInEdit.dataSource as TractionProductVariants).id
productsVM?.editProductVariantItemToList(factoryItemsAdapter, it, editedId)
}
}
if (requestCode == PICK_CATEGORY && resultCode == RESULT_OK) {
(data?.getSerializableExtra("data") as TractionProductCategory).let {
productsVM?.updateCategoryName(factoryItemsAdapter, it.name)
productsVM?.validCreateItemEnableSaveBtn(factoryItemsAdapter)
if (isCreateProductTour) {
val sellingPriceIndex = factoryItemsAdapter.fieldIndexWithKey(PriceKey)
val sellingPriceView = factoryItemsAdapter.fieldWithKey(PriceKey)?.fieldItemView()
factory_recycler.scrollToPosition(sellingPriceIndex)
sellingPriceView?.let {
showToolTip(it, R.string.enter_item_price, closePolicy = ClosePolicy.TOUCH_ANYWHERE_CONSUME)
}
}
}
}
if (requestCode == SCAN_BARCODE && resultCode == RESULT_OK) {
passBarcodeToView(data?.getStringExtra("data")!!)
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
}
private fun productCreationUpdate(state: DataStates?) {
state?.let {
dismissProgress()
when (it) {
is ProductCreated -> activity?.onBackPressed()
is FailedNoBusiness -> context?.message("you do not have an active registered business")
is DataResponseError -> {
it.cause?.message?.let {
context?.message(it)
}
}
is BarcodeGenerated -> {
passBarcodeToView(it.data!!)
}
is FailedOperation -> {
context?.message(it.message)
}
else -> {}
}
}
}
private fun passBarcodeToView(barcode: String) {
productsVM?.updateBarcodeField(factoryItemsAdapter, barcode)
}
override fun onDestroyView() {
super.onDestroyView()
productsVM?.productsData?.removeObservers(this)
productsVM?.productCreate?.removeObservers(this)
tooltip?.dismiss()
handler?.removeCallbacksAndMessages(this)
handler = null
}
fun setCreateProductListener(listener: CreateProductCallback) {
itemListener = listener
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment