Untitled

 avatar
unknown
kotlin
2 years ago
27 kB
8
Indexable
package `in`.swipe.app.app.ui.customers

import `in`.swipe.app.R
import `in`.swipe.app.app.Constants
import `in`.swipe.app.app.SwipeApplication
import `in`.swipe.app.app.Utils
import `in`.swipe.app.app.Utils.hideKeyboard
import `in`.swipe.app.app.navigateTo
import `in`.swipe.app.app.ui.customers.addcustomermanually.AddCustomerManuallyActivity
import `in`.swipe.app.app.ui.document.FabExtendingOnScrollListener
import `in`.swipe.app.app.ui.home.SharedViewModel
import `in`.swipe.app.app.ui.parties.AddPartiesListener
import `in`.swipe.app.app.ui.parties.PartiesViewModel
import `in`.swipe.app.app.ui.parties.SearchQueryListener
import `in`.swipe.app.app.ui.parties.bottomsheet.SortPartiesBottomSheetFragment
import `in`.swipe.app.app.ui.parties.bottomsheet.UserDetailsBottomSheetFragment
import `in`.swipe.app.app.ui.utils.WrapContentLinearLayoutManager
import `in`.swipe.app.data.model.models.CustomerData
import `in`.swipe.app.data.model.models.Vendor
import `in`.swipe.app.data.prefs.PreferenceHelper
import `in`.swipe.app.databinding.FragmentCustomersBinding
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.*
import android.widget.AbsListView
import android.widget.LinearLayout
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.RecyclerView
import com.mancj.materialsearchbar.MaterialSearchBar
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
import kotlin.math.max

class CustomersFragment : Fragment(), SearchQueryListener, AddPartiesListener,
    MenuItem.OnMenuItemClickListener, MaterialSearchBar.OnSearchActionListener,
    Toolbar.OnMenuItemClickListener, SortPartiesBottomSheetFragment.OnItemClickListener,
    CustomerAdapter.OnItemClickListener {
    private lateinit var binding: FragmentCustomersBinding
    private lateinit var parentActivity: AppCompatActivity
    private lateinit var navHostFragment: NavHostFragment
    private lateinit var navController: NavController
    private var isCustomerAccess = PreferenceHelper.getCustomersAccess()
    private var customerAdapter: CustomerAdapter? = null
    private lateinit var linearLayoutManager: WrapContentLinearLayoutManager
    private var newInvoiceLayout = false
    private var isSelectCustomer = false
    private val viewModel by sharedViewModel<CustomersViewModel>()
    private lateinit var sortBottomSheet: SortPartiesBottomSheetFragment
    private lateinit var userDetailsBottomSheet: UserDetailsBottomSheetFragment
    private var radioButtonValue = "Default"
    private var sortNetBalanceBy = ""
    private lateinit var resultLauncher: ActivityResultLauncher<Intent>
    private var selectedCustomerId = -1

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            if (it.containsKey("newInvoiceLayout")) {
                newInvoiceLayout = it.getBoolean("newInvoiceLayout")
            }
            if (it.containsKey(Constants.BUNDLE_IS_SELECT_CUSTOMER)) {
                isSelectCustomer = it.getBoolean(Constants.BUNDLE_IS_SELECT_CUSTOMER)
            }
        }

        resultLauncher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == Activity.RESULT_OK) {
                    // There are no request codes
                    val data: Intent? = result.data
                    data?.let {
                        if (isVisible) {
                            selectedCustomerId = it.getIntExtra(Constants.NEW_CUSTOMER_ID, -1)
                        }
                    }
                }
            }

        setHasOptionsMenu(true)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentCustomersBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        parentActivity = activity as AppCompatActivity
        logFragment("onViewCreated called")
        setupNavigationComponent()
        setListeners()
        observeData()

        if (isCustomerAccess == 1) {
            viewModel.getAllCustomers(sortNetBalanceBy)
            startShimmer()
        }

        if (isCustomerAccess == 1) {
            binding.noAccess.visibility = View.GONE
            binding.recyclerview.visibility = View.VISIBLE
        } else {
            binding.noAccess.visibility = View.VISIBLE
            customerAdapter?.resetDiffer()
            binding.recyclerview.visibility = View.GONE
        }
        if (isSelectCustomer) {
            binding.includeTool.visibility = View.VISIBLE
            binding.btnCreateCustomer.visibility = View.GONE
            binding.searchBarCustomer.visibility = View.GONE
            binding.sortCustomer.visibility = View.GONE
            searchCustomers()
        } else {
            binding.includeTool.visibility = View.GONE
            binding.btnCreateCustomer.visibility = View.VISIBLE
            binding.sortCustomer.visibility = View.VISIBLE
            binding.searchBarCustomer.addTextChangedListener(object : TextWatcher {
                override fun beforeTextChanged(
                    s: CharSequence?,
                    start: Int,
                    count: Int,
                    after: Int
                ) {

                }

                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                    if (s.isNullOrEmpty().not() || s.isNullOrBlank().not()) {
                        viewModel.searchCustomer(s.toString())
                    } else {
                        if (PreferenceHelper.getCustomersAccess() == 1) {
                            viewModel.getAllCustomers(sortNetBalanceBy)
                            binding.recyclerview.visibility = View.VISIBLE
                        } else {
                            binding.noDataMessage.visibility = View.GONE
                            binding.noAccess.visibility = View.VISIBLE
                            customerAdapter?.resetDiffer()
                            binding.recyclerview.visibility = View.GONE
                        }
                    }
                }

                override fun afterTextChanged(s: Editable?) {

                }

            })
        }

        binding.btnCreateCustomer.setOnClickListener {
            logFragment("btnCreateCustomer clicked")
            val addCustomerManuallyIntent =
                Intent(parentActivity, AddCustomerManuallyActivity::class.java)
            resultLauncher.launch(addCustomerManuallyIntent)
            requireActivity().overridePendingTransition(
                R.anim.activity_slide_in_right_trans,
                R.anim.activity_slide_out_left_trans
            )
        }

        binding.addCust.setOnClickListener {
            logFragment("addCust clicked")
            val addCustomerManuallyIntent =
                Intent(parentActivity, AddCustomerManuallyActivity::class.java)
            resultLauncher.launch(addCustomerManuallyIntent)
            requireActivity().overridePendingTransition(
                R.anim.activity_slide_in_right_trans,
                R.anim.activity_slide_out_left_trans
            )
        }

        binding.btnAddCustomer.setOnClickListener {
            logFragment("btnCreateCustomer clicked")
            binding.btnCreateCustomer.visibility = View.VISIBLE
            binding.addCustomerLayout.visibility = View.GONE

            val addCustomerManuallyIntent =
                Intent(parentActivity, AddCustomerManuallyActivity::class.java)
            resultLauncher.launch(addCustomerManuallyIntent)
            requireActivity().overridePendingTransition(
                R.anim.activity_slide_in_right_trans,
                R.anim.activity_slide_out_left_trans
            )
        }
        setupToolBar()

        binding.customerFragmentToolbar.setOnMenuItemClickListener(this@CustomersFragment)
        binding.sortCustomer.setOnClickListener {
            sortBottomSheet = SortPartiesBottomSheetFragment(this, radioButtonValue)
            val fm = childFragmentManager
            sortBottomSheet.show(fm, tag)
        }
    }

    private fun setupToolBar() {
        //parentActivity.setSupportActionBar(binding.customerFragmentToolbar)
        binding.customerFragmentToolbar.title = "Customers"
        binding.customerFragmentToolbar.navigationIcon =
            ContextCompat.getDrawable(requireActivity(), R.drawable.ic_back_black)
        binding.customerFragmentToolbar.setNavigationOnClickListener {
            activity?.onBackPressed()
        }
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        menu.clear()
        inflater.inflate(R.menu.parties_toolbar_menu, menu)
        val searchItem = menu.findItem(R.id.menuItemSearch)
        searchItem.setOnMenuItemClickListener(this)
        super.onCreateOptionsMenu(menu, inflater)
    }

    private fun searchCustomers() {
        binding.searchBarCust.addTextChangeListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if (s.isNullOrEmpty().not() || s.isNullOrBlank().not())
                    viewModel.searchCustomer(s.toString())
                else
                    viewModel.getAllCustomers(sortNetBalanceBy)
            }

            override fun afterTextChanged(s: Editable?) {

            }

        })

        binding.searchBarCust.setOnSearchActionListener(this@CustomersFragment)

    }

    override fun onResume() {
        super.onResume()
        if (isAdded && isSelectCustomer) {
            if (isCustomerAccess == 1) {
                viewModel.getAllCustomers(sortNetBalanceBy)
                startShimmer()
            }
        }
    }

    private fun setupNavigationComponent() {
        logFragment("setupNavigationComponent clicked")
        navHostFragment =
            parentActivity.supportFragmentManager.findFragmentById(R.id.navHostFragmentContainer) as NavHostFragment
        navController = navHostFragment.navController
    }

    private fun setListeners() {

        val dividerItemDecoration =
            DividerItemDecoration(parentActivity, LinearLayout.VERTICAL)
        linearLayoutManager = WrapContentLinearLayoutManager(parentActivity)

        customerAdapter = CustomerAdapter(
            parentActivity,
            navController,
            newInvoiceLayout,
            this
        )

        binding.recyclerview.layoutManager = linearLayoutManager
        binding.recyclerview.addItemDecoration(dividerItemDecoration)
        binding.recyclerview.setHasFixedSize(true)
        binding.recyclerview.adapter = customerAdapter

        binding.swipeRefreshLayout.setOnRefreshListener {
            logFragment("swipeRefreshLayout.setOnRefreshListener clicked")
            if(PreferenceHelper.getCustomersAccess() == 1) {
                if (viewModel.searchingState.value == PartiesViewModel.IDLE) {
                    viewModel.getAllCustomers(sortNetBalanceBy)
                    startShimmer()
                } else {
                    stopShimmer()
                    binding.swipeRefreshLayout.isRefreshing = false
                }
                binding.recyclerview.visibility = View.VISIBLE
            } else {
                binding.swipeRefreshLayout.isRefreshing = false
                binding.noDataMessage.visibility = View.GONE
                binding.noAccess.visibility = View.VISIBLE
                binding.recyclerview.visibility = View.GONE
                customerAdapter?.resetDiffer()
            }
        }

        binding.recyclerview.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
                if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
                    viewModel.isScrolling.value = true
                }
            }

            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                val currentItems = linearLayoutManager.childCount
                val totalItems = linearLayoutManager.itemCount
                val scrollOutItems = linearLayoutManager.findFirstVisibleItemPosition()

                if (viewModel.isScrolling.value == true && dy >= 0 && (currentItems + scrollOutItems == totalItems && viewModel.searchingState.value == PartiesViewModel.IDLE)) {
                    if (viewModel.getCanLoadNewData().value == true) {
                        logFragment("viewModel.getMoreData() called")
                        viewModel.isScrolling.value = false
                        viewModel.currentPage.value = viewModel.currentPage.value?.plus(1)
                        viewModel.getMoreData(sortNetBalanceBy)
                    }
                }
            }
        })

        binding.recyclerview.addOnScrollListener(FabExtendingOnScrollListener(binding.btnCreateCustomer))
    }

    private fun observeData() {
        viewModel.getDataFetched().observe(viewLifecycleOwner) {
            it?.let {
                when (it) {
                    true -> {
                        if (binding.recyclerview.adapter == null) {
                            logFragment("setting up customers adapter")
                            stopShimmer()

                            val dividerItemDecoration =
                                DividerItemDecoration(parentActivity, LinearLayout.VERTICAL)
                            linearLayoutManager = WrapContentLinearLayoutManager(parentActivity)

                            customerAdapter = CustomerAdapter(
                                parentActivity,
                                navController,
                                newInvoiceLayout,
                                this
                            )

                            binding.recyclerview.layoutManager = linearLayoutManager
                            binding.recyclerview.addItemDecoration(dividerItemDecoration)
                            binding.recyclerview.adapter = customerAdapter
                        }

                        if (viewModel.searchingState.value != PartiesViewModel.IDLE) {
                            viewModel.searchingState.value = PartiesViewModel.IDLE
                        }

                        binding.swipeRefreshLayout.isRefreshing = false
                    }

                    false -> {

                        stopShimmer()
                        logFragment("error fetching customers")
                        binding.swipeRefreshLayout.isRefreshing = false
                        Toast.makeText(
                            parentActivity,
                            R.string.error_fetching_customers,
                            Toast.LENGTH_LONG
                        ).show()
                    }
                }
            }
        }

        viewModel.searchingState.observe(viewLifecycleOwner) {
            it?.let {
                when (it) {
                    PartiesViewModel.IDLE -> {
                        binding.progressBar.visibility = View.GONE
                    }

                    PartiesViewModel.IS_SEARCHING -> {
                        binding.progressBar.visibility = View.VISIBLE
                    }

                    PartiesViewModel.SEARCHING_COMPLETED -> {
                        customerAdapter?.updateCustomersData(viewModel.newCustomers.value!!)
                        binding.progressBar.visibility = View.GONE
                    }

                    PartiesViewModel.SEARCHING_GOT_ERROR -> {
                        Toast.makeText(activity, R.string.error_getting_search, Toast.LENGTH_LONG)
                            .show()
                        binding.progressBar.visibility = View.GONE
                    }
                }
            }
        }

        viewModel.newCustomers.observe(viewLifecycleOwner) {
            it?.let {
                logFragment("newCustomers observer called", it.toString())
                stopShimmer()
                if (selectedCustomerId != -1 && isSelectCustomer) {
                    if (it.size > 0) {
                        ViewModelProvider(context as AppCompatActivity)[SharedViewModel::class.java].selectedCustomer.value =
                            Pair(it.findLast { it.customer_id == selectedCustomerId },true)
                        selectedCustomerId = -1
                        requireActivity().onBackPressed()
                    } else {
                        Toast.makeText(
                            requireActivity(),
                            "Something went wrong!!",
                            Toast.LENGTH_SHORT
                        ).show()
                    }
                }

                if (viewModel.searchingState.value != null && viewModel.searchingState.value != PartiesViewModel.SEARCHING_COMPLETED) {

                    if (it.size == 0 && viewModel.currentPage.value == 0) {
                        customerAdapter?.updateCustomersData(it)
                        binding.noDataMessage.visibility = View.VISIBLE
                        binding.noAccess.visibility = View.GONE
                        if (viewModel.searchingState.value == -1) {
                            binding.btnCreateCustomer.visibility = View.GONE
                            binding.noDataMessage.visibility = View.GONE
                            binding.addCustomerLayout.visibility = View.VISIBLE
                            binding.addCustomerText.visibility = View.GONE
                            binding.btnAddCustomer.visibility = View.VISIBLE
                        } else {
                            binding.btnCreateCustomer.visibility = View.VISIBLE
                            binding.addCustomerLayout.visibility = View.GONE
                        }
                        if (isSelectCustomer) {
                            binding.addCust.visibility = View.VISIBLE
                            if (viewModel.searchingState.value != PartiesViewModel.IS_SEARCHING) {
                                if (isVisible) {
                                    binding.searchBarCust.visibility = View.INVISIBLE
                                    activity?.currentFocus?.hideKeyboard()
                                }
                            }
                        }
                    } else {
                        binding.noAccess.visibility = View.GONE
                        binding.recyclerview.visibility = View.VISIBLE
                        binding.swipeRefreshLayout.visibility = View.VISIBLE
                        binding.customersList.visibility = View.VISIBLE
                        if (isSelectCustomer) {
                            binding.addCust.visibility = View.VISIBLE
                            binding.searchBarCust.visibility = View.VISIBLE
                            binding.searchBarCust.setHint("Search Customers")
                            binding.searchBarCust.openSearch()
                            if (isVisible) {
                                Utils.showKeyboard(binding.searchBarCust.searchEditText)
                            }
                        }
                        binding.addCustomerLayout.visibility = View.GONE
                        binding.noDataMessage.visibility = View.GONE
                        if (!isSelectCustomer)
                            binding.btnCreateCustomer.visibility = View.VISIBLE
                    }

                    if (viewModel.currentPage.value == 0) {
                        customerAdapter?.updateCustomersData(it)
                    } else {
                        customerAdapter?.updateData(it)
                    }
                }
            }
        }

        viewModel.getIsLoadingNewData().observe(viewLifecycleOwner) {
            it?.let {
                logFragment("getIsLoadingNewData observer called")
                if (it) {

                } else {
                    stopShimmer()
                }
            }
        }

        viewModel.getCanLoadNewData().observe(viewLifecycleOwner) {
            it?.let {
                logFragment("getCanLoadNewData observer called")
                if (!it) {
                    Toast.makeText(parentActivity, R.string.no_more_data, Toast.LENGTH_LONG).show()
                    customerAdapter?.lastPage = true
                    customerAdapter?.notifyItemChanged(
                        customerAdapter?.differ?.currentList?.lastIndex ?: 0
                    )
                }
            }
        }

        viewModel.dataFetched.observe(viewLifecycleOwner) {
            if (!it) {
                binding.noAccess.visibility = View.VISIBLE
                customerAdapter?.resetDiffer()
                binding.addCustomerLayout.visibility = View.GONE
                binding.recyclerview.visibility = View.GONE
            }
        }
    }

    private fun startShimmer() {
        binding.shimmerLayout.startShimmer()
        binding.shimmerLayout.visibility = View.VISIBLE
        binding.swipeRefreshLayout.visibility = View.GONE
        binding.recyclerview.visibility = View.GONE
    }

    private fun stopShimmer() {
        binding.shimmerLayout.stopShimmer()
        binding.shimmerLayout.visibility = View.GONE
        binding.swipeRefreshLayout.visibility = View.VISIBLE
        binding.recyclerview.visibility = View.VISIBLE
    }

    override fun onSearchQuerySubmit(query: String) {
        if (isVisible) {
            if (query.isNullOrEmpty().not()) {
                viewModel.searchCustomer(query)
            }
        }
    }

    override fun onSearchBarClosed() {
        if (isAdded) {
            viewModel.getAllCustomers(sortNetBalanceBy)
            logFragment("onSearchBarClosed called")
        }
    }

    override fun onDestroy() {
        if (customerAdapter != null)
            customerAdapter!!.resetDiffer()
        super.onDestroy()
    }

    override fun add() {
        logFragment("action_navBarMenuParties_to_addNewCustFragment called")
        navController.currentDestination?.getAction(R.id.action_navBarMenuParties_to_addNewCustFragment)
            ?.let {
                navController.navigateTo(
                    R.id.action_navBarMenuParties_to_addNewCustFragment
                )
            } ?: run {
            navController.navigateTo(R.id.action_createInvoiceParties_to_addNewCustFragment)
        }
    }

    fun logFragment(methodName: String, methodParameter: String = "None") {
        val bundle = Bundle()
        bundle.putString(Constants.FRAGMENT_NAME, "customers_fragment")
        bundle.putString(Constants.FRAGMENT_METHOD, methodName)
        bundle.putString(Constants.FRAGMENT_METHOD_PARAMETER, methodParameter)
        if (activity != null)
            (activity?.applicationContext as SwipeApplication).logFragment(bundle)
    }

    override fun onMenuItemClick(item: MenuItem?): Boolean {
        val cx = binding.searchBarCust.measuredWidth / 2
        val cy = binding.searchBarCust.measuredHeight / 2

        if (isVisible){
            val finalRadius = max(binding.searchBarCust.width, binding.searchBarCust.height) / 2

            val anim = ViewAnimationUtils.createCircularReveal(
                binding.searchBarCust, cx, cy, 0F,
                finalRadius.toFloat()
            )
            binding.searchBarCust.visibility = View.VISIBLE
            binding.searchBarCust.performClick()
            anim.start()
        }

        return true
    }

    override fun onSearchStateChanged(enabled: Boolean) {
        if (!enabled) {
            activity?.onBackPressed()
//            val cx = binding.searchBarCust.measuredWidth / 2
//            val cy = binding.searchBarCust.measuredHeight / 2
//
//            val finalRadius =
//                max(binding.searchBarCust.width, binding.searchBarCust.height) / 2
//
//            val anim = ViewAnimationUtils.createCircularReveal(
//                binding.searchBarCust, cx, cy,
//                finalRadius.toFloat(), 0F
//            )
//            binding.searchBarCust.visibility = View.VISIBLE
//            anim.addListener(object : Animator.AnimatorListener {
//                override fun onAnimationStart(animation: Animator?) {
//                }
//
//                override fun onAnimationEnd(animation: Animator?) {
//                    binding.searchBarCust.visibility = View.INVISIBLE
//                }
//
//                override fun onAnimationCancel(animation: Animator?) {
//                }
//
//                override fun onAnimationRepeat(animation: Animator?) {
//                }
//            })
//            anim.start()
        }
    }

    fun getAllCustomers() {
//        if (isVisible) {
//            viewModel.getAllCustomers()
//        }
    }

    override fun onSearchConfirmed(text: CharSequence?) {

    }

    override fun onButtonClicked(buttonCode: Int) {

    }

    override fun onRadioItemSelected(selectedRadioValue: String) {
        radioButtonValue = selectedRadioValue
        sortNetBalanceBy = when (selectedRadioValue) {
            "Net Balance - Low to High" -> "asc"
            "Net Balance - High to Low" -> "desc"
            else -> ""
        }
        viewModel.getAllCustomers(sortNetBalanceBy)
    }

    override fun onMoreDetailsClick(customer: CustomerData) {
        userDetailsBottomSheet = UserDetailsBottomSheetFragment("customer",customer)
        val fm = childFragmentManager
        userDetailsBottomSheet.show(fm,tag)
    }

}
Editor is loading...