From 8507c23612ab61015a65db4b1040539a17ab9a51 Mon Sep 17 00:00:00 2001 From: hnfnfl Date: Thu, 19 Sep 2024 21:40:16 +0700 Subject: [PATCH] feat:+ - add new titik tiang feature - code refactoring and clean up --- app/build.gradle | 1 + app/src/main/AndroidManifest.xml | 5 +- .../jmnetwork/e_jartas/model/GeneralClass.kt | 6 +- .../jmnetwork/e_jartas/model/TiangModel.kt | 37 +++++ .../repository/InterfaceRepository.kt | 3 + .../ManajemenTiangRepositoryImpl.kt | 33 +++++ .../jmnetwork/e_jartas/utils/Deserializer.kt | 47 +++--- .../com/jmnetwork/e_jartas/utils/Utils.kt | 10 +- .../jmnetwork/e_jartas/view/HomeFragment.kt | 10 +- .../manajemenJalan/AddRuasJalanFragment.kt | 2 +- .../manajemenJalan/EditRuasJalanFragment.kt | 6 +- .../provider/AddProviderFragment.kt | 2 +- .../provider/EditProviderFragment.kt | 2 +- .../provider/ListProviderFragment.kt | 4 +- .../provider/ProviderActivity.kt | 14 +- .../titikTiang/ListTitikTiangFragment.kt | 114 +++++++++++++++ .../titikTiang/TitikTiangActivity.kt | 35 +++++ .../titikTiang/TitikTiangAdapter.kt | 137 ++++++++++++++++++ .../viewModel/ManajemenTiangViewModel.kt | 37 +++-- app/src/main/res/layout/activity_provider.xml | 2 +- .../main/res/layout/activity_titik_tiang.xml | 9 ++ app/src/main/res/layout/form_provider.xml | 2 +- .../res/layout/fragment_list_provider.xml | 2 +- .../res/layout/fragment_list_titik_tiang.xml | 91 ++++++++++++ app/src/main/res/layout/item_tiang.xml | 82 +++++++++++ .../main/res/layout/item_tiang_provider.xml | 76 ++++++++++ app/src/main/res/values/strings.xml | 9 +- 27 files changed, 711 insertions(+), 67 deletions(-) create mode 100644 app/src/main/java/com/jmnetwork/e_jartas/model/TiangModel.kt create mode 100644 app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/titikTiang/ListTitikTiangFragment.kt create mode 100644 app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/titikTiang/TitikTiangActivity.kt create mode 100644 app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/titikTiang/TitikTiangAdapter.kt create mode 100644 app/src/main/res/layout/activity_titik_tiang.xml create mode 100644 app/src/main/res/layout/fragment_list_titik_tiang.xml create mode 100644 app/src/main/res/layout/item_tiang.xml create mode 100644 app/src/main/res/layout/item_tiang_provider.xml diff --git a/app/build.gradle b/app/build.gradle index 6f531d9..bfa7fa3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,6 +66,7 @@ dependencies { implementation 'com.google.android.gms:play-services-location:21.3.0' implementation 'com.google.code.gson:gson:2.10.1' implementation 'com.google.android.material:material:1.12.0' + implementation 'androidx.activity:activity:1.9.2' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8821575..713bf8b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -30,7 +30,10 @@ android:theme="@style/Theme.Ejartas" tools:targetApi="tiramisu"> + , + @SerializedName("data_tabel") val dataTabel: String, + @SerializedName("limit") val limit: String, + @SerializedName("message") val message: String, + @SerializedName("status") val status: String, + @SerializedName("totalData") val totalData: TotalData +) + +data class TiangData( + @SerializedName("createddate") val createddate: String, + @SerializedName("idtiang") val idtiang: Int, + @SerializedName("idtiang_cetak_qrcode") val idtiangCetakQrcode: Int, + @SerializedName("json_provider") val tiangProvider: TiangProvider, + @SerializedName("jumlah_tiang") val jumlahTiang: String, + @SerializedName("lastupdate") val lastupdate: String, + @SerializedName("latlong") val latlong: Location, + @SerializedName("oleh") val oleh: Int, + @SerializedName("petugas_scan") val petugasScan: Any?, + @SerializedName("qrcode") val qrcode: String, +) + +class TiangProvider : ArrayList() + +data class TiangProviderItem( + @SerializedName("catatan") val catatan: String, + @SerializedName("id") val id: Int, + @SerializedName("idprovider") val idprovider: String, + @SerializedName("layak") val layak: String, + @SerializedName("provider") val provider: String, + @SerializedName("utilitas") val utilitas: String +) \ No newline at end of file diff --git a/app/src/main/java/com/jmnetwork/e_jartas/repository/InterfaceRepository.kt b/app/src/main/java/com/jmnetwork/e_jartas/repository/InterfaceRepository.kt index 5695a9e..722f6f8 100644 --- a/app/src/main/java/com/jmnetwork/e_jartas/repository/InterfaceRepository.kt +++ b/app/src/main/java/com/jmnetwork/e_jartas/repository/InterfaceRepository.kt @@ -11,6 +11,7 @@ import com.jmnetwork.e_jartas.model.ProviderResponse import com.jmnetwork.e_jartas.model.RuasJalanRequest import com.jmnetwork.e_jartas.model.RuasJalanResponse import com.jmnetwork.e_jartas.model.SpinnerResponse +import com.jmnetwork.e_jartas.model.TiangResponse interface BaseRepository { fun login(context: Context, loginRequest: LoginRequest, deviceID: String, tokenAuth: String): LiveData @@ -31,4 +32,6 @@ interface ManajemenTiangRepository { fun blacklistProvider(context: Context, idadmin: Int, iddata: Int, isBlacklist: Boolean, tokenAuth: String): LiveData fun editProvider(context: Context, idadmin: Int, iddata: Int, requestData: ProviderRequest, tokenAuth: String): LiveData fun deleteProvider(context: Context, idadmin: Int, iddata: Int, tokenAuth: String): LiveData + + fun getTitikTiang(context: Context, limit: Int, page: Int, tokenAuth: String): LiveData } \ No newline at end of file diff --git a/app/src/main/java/com/jmnetwork/e_jartas/repository/ManajemenTiangRepositoryImpl.kt b/app/src/main/java/com/jmnetwork/e_jartas/repository/ManajemenTiangRepositoryImpl.kt index f11358b..c9c21ad 100644 --- a/app/src/main/java/com/jmnetwork/e_jartas/repository/ManajemenTiangRepositoryImpl.kt +++ b/app/src/main/java/com/jmnetwork/e_jartas/repository/ManajemenTiangRepositoryImpl.kt @@ -7,10 +7,15 @@ import com.google.gson.Gson import com.google.gson.GsonBuilder import com.jmnetwork.e_jartas.model.Additional import com.jmnetwork.e_jartas.model.DefaultResponse +import com.jmnetwork.e_jartas.model.Location import com.jmnetwork.e_jartas.model.ProviderRequest import com.jmnetwork.e_jartas.model.ProviderResponse +import com.jmnetwork.e_jartas.model.TiangProvider +import com.jmnetwork.e_jartas.model.TiangResponse import com.jmnetwork.e_jartas.utils.AdditionalDeserializer import com.jmnetwork.e_jartas.utils.CustomHandler +import com.jmnetwork.e_jartas.utils.LocationDeserializer +import com.jmnetwork.e_jartas.utils.TiangProviderDeserializer import okhttp3.ResponseBody import org.json.JSONObject import retrofit2.Call @@ -174,4 +179,32 @@ class ManajemenTiangRepositoryImpl : ManajemenTiangRepository { return result } + + override fun getTitikTiang(context: Context, limit: Int, page: Int, tokenAuth: String): LiveData { + val result = MutableLiveData() + + apiService.getAllData(limit, page, "tiang", tokenAuth).enqueue(object : retrofit2.Callback { + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful) { + val gson = GsonBuilder() + .registerTypeAdapter(TiangProvider::class.java, TiangProviderDeserializer()) + .registerTypeAdapter(Location::class.java, LocationDeserializer()) + .create() + val responseString = response.body()?.string() + val data = gson.fromJson(responseString, TiangResponse::class.java) + result.postValue(data) + } else { + val errorBody = response.errorBody()?.string() + val errorMsg = errorBody?.let { JSONObject(it).getString("message") } ?: "Unknown error" + CustomHandler().responseHandler(context, "getTitikTiang|onResponse", errorMsg, response.code()) + } + } + + override fun onFailure(call: Call, t: Throwable) { + CustomHandler().responseHandler(context, "getTitikTiang|onFailure", t.message.toString()) + } + }) + + return result + } } \ No newline at end of file diff --git a/app/src/main/java/com/jmnetwork/e_jartas/utils/Deserializer.kt b/app/src/main/java/com/jmnetwork/e_jartas/utils/Deserializer.kt index 6ba0231..9783db5 100644 --- a/app/src/main/java/com/jmnetwork/e_jartas/utils/Deserializer.kt +++ b/app/src/main/java/com/jmnetwork/e_jartas/utils/Deserializer.kt @@ -5,24 +5,26 @@ import com.google.gson.JsonDeserializer import com.google.gson.JsonElement import com.google.gson.JsonParser import com.jmnetwork.e_jartas.model.Additional -import com.jmnetwork.e_jartas.model.AdditionalItem import com.jmnetwork.e_jartas.model.Location -import com.jmnetwork.e_jartas.model.LocationItem +import com.jmnetwork.e_jartas.model.TiangProvider import java.lang.reflect.Type +inline fun parseJsonArray(json: JsonElement?, context: JsonDeserializationContext?, list: MutableList): MutableList { + if (json != null && json.isJsonPrimitive) { + val jsonString = json.asString + val jsonArray = JsonParser.parseString(jsonString).asJsonArray + jsonArray.forEach { jsonElement -> + val item = context?.deserialize(jsonElement, T::class.java) + item?.let { list.add(it) } + } + } + return list +} + class AdditionalDeserializer : JsonDeserializer { override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): Additional { val additional = Additional() - // Check if json is not null and is a JSON array string - if (json != null && json.isJsonPrimitive) { - val jsonString = json.asString - // Parse the string-escaped JSON into a list of AdditionalItems - val jsonArray = JsonParser.parseString(jsonString).asJsonArray - jsonArray.forEach { it -> - val item = context?.deserialize(it, AdditionalItem::class.java) - item?.let { additional.add(it) } - } - } + parseJsonArray(json, context, additional) // Reuse the generic function return additional } } @@ -30,16 +32,15 @@ class AdditionalDeserializer : JsonDeserializer { class LocationDeserializer : JsonDeserializer { override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): Location { val location = Location() - // Check if json is not null and is a JSON array string - if (json != null && json.isJsonPrimitive) { - val jsonString = json.asString - // Parse the string-escaped JSON into a list of LocationItems - val jsonArray = JsonParser.parseString(jsonString).asJsonArray - jsonArray.forEach { it -> - val item = context?.deserialize(it, LocationItem::class.java) - item?.let { location.add(it) } - } - } + parseJsonArray(json, context, location) // Reuse the generic function return location } -} \ No newline at end of file +} + +class TiangProviderDeserializer : JsonDeserializer { + override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): TiangProvider { + val tiangProvider = TiangProvider() + parseJsonArray(json, context, tiangProvider) // Reuse the generic function + return tiangProvider + } +} diff --git a/app/src/main/java/com/jmnetwork/e_jartas/utils/Utils.kt b/app/src/main/java/com/jmnetwork/e_jartas/utils/Utils.kt index 9c14cfa..c22d3b1 100644 --- a/app/src/main/java/com/jmnetwork/e_jartas/utils/Utils.kt +++ b/app/src/main/java/com/jmnetwork/e_jartas/utils/Utils.kt @@ -12,12 +12,18 @@ class Utils { } } - fun latLongConverter(latLong: Location): LatLng? { - if (latLong.isEmpty()) return null + fun latLongConverter(latLong: Location?): LatLng? { + if (latLong.isNullOrEmpty()) return null val rawLatLng = latLong[0] val lat = rawLatLng.lat.toDouble() val lng = rawLatLng.lng.toDouble() return LatLng(lat, lng) } + + fun formatDate(date: String): String { + val dateArray = date.split(" ") + val dateArray2 = dateArray[0].split("-") + return "${dateArray2[2]}-${dateArray2[1]}-${dateArray2[0]}" + } } \ No newline at end of file diff --git a/app/src/main/java/com/jmnetwork/e_jartas/view/HomeFragment.kt b/app/src/main/java/com/jmnetwork/e_jartas/view/HomeFragment.kt index 6b78381..3c1a362 100644 --- a/app/src/main/java/com/jmnetwork/e_jartas/view/HomeFragment.kt +++ b/app/src/main/java/com/jmnetwork/e_jartas/view/HomeFragment.kt @@ -10,7 +10,8 @@ import androidx.lifecycle.ViewModelProvider import com.jmnetwork.e_jartas.R import com.jmnetwork.e_jartas.databinding.FragmentHomeBinding import com.jmnetwork.e_jartas.view.manajemenJalan.RuasJalanActivity -import com.jmnetwork.e_jartas.view.manajemenTiang.ProviderActivity +import com.jmnetwork.e_jartas.view.manajemenTiang.provider.ProviderActivity +import com.jmnetwork.e_jartas.view.manajemenTiang.titikTiang.TitikTiangActivity import com.jmnetwork.e_jartas.viewModel.HomeViewModel import com.jmnetwork.e_jartas.viewModel.ViewModelFactory import java.util.Locale @@ -54,11 +55,14 @@ class HomeFragment : Fragment() { btnProvider.setOnClickListener { activity?.startActivity( Intent(requireContext(), ProviderActivity::class.java) - .putExtra(ProviderActivity.DESTINATION, "list") ) } - btnTitikTiang.setOnClickListener { } + btnTitikTiang.setOnClickListener { + activity?.startActivity( + Intent(requireContext(), TitikTiangActivity::class.java) + ) + } } return binding.root diff --git a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenJalan/AddRuasJalanFragment.kt b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenJalan/AddRuasJalanFragment.kt index e21193a..95d73ba 100644 --- a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenJalan/AddRuasJalanFragment.kt +++ b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenJalan/AddRuasJalanFragment.kt @@ -148,7 +148,7 @@ class AddRuasJalanFragment : Fragment(), OnMapReadyCallback { val inputFungsi = spinnerFungsi.selectedItem.takeIf { it != null }?.toString().orEmpty() val location = Location().apply { - add(LocationItem(latLng?.latitude.toString(), latLng?.longitude.toString())) + add(LocationItem(latLng?.latitude.toString(), latLng?.longitude.toString(), "")) } val validate = viewModel.setRequestData( diff --git a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenJalan/EditRuasJalanFragment.kt b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenJalan/EditRuasJalanFragment.kt index 2670af8..c3bbfa4 100644 --- a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenJalan/EditRuasJalanFragment.kt +++ b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenJalan/EditRuasJalanFragment.kt @@ -94,9 +94,7 @@ class EditRuasJalanFragment : Fragment(), OnMapReadyCallback { viewModel.apply { if (ruasJalanData != null) { - if (ruasJalanData.latLong != null) { - latLng = Utils().latLongConverter(ruasJalanData.latLong) - } + latLng = Utils().latLongConverter(ruasJalanData.latLong) inputNomorRuasJalan.setText(ruasJalanData.noRuas) inputNamaRuasJalan.setText(ruasJalanData.namaRuasJalan) @@ -193,7 +191,7 @@ class EditRuasJalanFragment : Fragment(), OnMapReadyCallback { val inputFungsi = spinnerFungsi.selectedItem.takeIf { it != null }?.toString().orEmpty() val location = Location().apply { - add(LocationItem(latLng?.latitude.toString(), latLng?.longitude.toString())) + add(LocationItem(latLng?.latitude.toString(), latLng?.longitude.toString(), "")) } val validate = viewModel.setRequestData( diff --git a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/AddProviderFragment.kt b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/AddProviderFragment.kt index 0faae3c..d053f4f 100644 --- a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/AddProviderFragment.kt +++ b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/AddProviderFragment.kt @@ -66,7 +66,7 @@ class AddProviderFragment : Fragment() { val namaProvider = inputNamaProvider.text.toString() val alamatProvider = inputAlamatProvider.text.toString() - val validate = viewModel.setRequestData( + val validate = viewModel.setRequestDataProvider( Additional(), alamatProvider, namaProvider diff --git a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/EditProviderFragment.kt b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/EditProviderFragment.kt index ec217e6..b894896 100644 --- a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/EditProviderFragment.kt +++ b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/EditProviderFragment.kt @@ -84,7 +84,7 @@ class EditProviderFragment : Fragment() { btnProvider.attachTextChangeAnimator() btnProvider.showProgress() - val validate = viewModel.setRequestData( + val validate = viewModel.setRequestDataProvider( additional, alamatProvider, namaProvider diff --git a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/ListProviderFragment.kt b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/ListProviderFragment.kt index dacb46d..a86dcd4 100644 --- a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/ListProviderFragment.kt +++ b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/ListProviderFragment.kt @@ -75,8 +75,8 @@ class ListProviderFragment : Fragment() { if (it != null) { adapter.setItem(it.values.toList()) progressBar.visibility = View.GONE - totalPage = totalData.value?.div(limit) ?: 0 - totalPage += if (totalData.value?.rem(limit) != 0) 1 else 0 + totalPage = totalDataProvider.value?.div(limit) ?: 0 + totalPage += if (totalDataProvider.value?.rem(limit) != 0) 1 else 0 } else { adapter.setItem(emptyList()) } diff --git a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/ProviderActivity.kt b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/ProviderActivity.kt index 98ee53f..4f9c8a5 100644 --- a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/ProviderActivity.kt +++ b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/provider/ProviderActivity.kt @@ -14,10 +14,6 @@ class ProviderActivity : AppCompatActivity() { private lateinit var binding: ActivityProviderBinding lateinit var viewModel: ManajemenTiangViewModel - companion object { - const val DESTINATION = "destination" - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityProviderBinding.inflate(layoutInflater) @@ -26,15 +22,7 @@ class ProviderActivity : AppCompatActivity() { viewModel = ViewModelProvider(this@ProviderActivity, factory)[ManajemenTiangViewModel::class.java] viewModel.getProvider(5, 1) // Get Provider data from API - if (intent.hasExtra(DESTINATION)) { - when (intent.getStringExtra(DESTINATION)) { - "list" -> { - loadFragment(ListProviderFragment()) - } - } - } else { - loadFragment(ListProviderFragment()) - } + loadFragment(ListProviderFragment()) } private fun loadFragment(fragment: Fragment) { diff --git a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/titikTiang/ListTitikTiangFragment.kt b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/titikTiang/ListTitikTiangFragment.kt new file mode 100644 index 0000000..696ce2b --- /dev/null +++ b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/titikTiang/ListTitikTiangFragment.kt @@ -0,0 +1,114 @@ +package com.jmnetwork.e_jartas.view.manajemenTiang.titikTiang + +import android.content.Intent +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.activity.OnBackPressedCallback +import androidx.appcompat.widget.SearchView +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.jmnetwork.e_jartas.R +import com.jmnetwork.e_jartas.databinding.FragmentListTitikTiangBinding +import com.jmnetwork.e_jartas.view.MainActivity +import com.jmnetwork.e_jartas.viewModel.ManajemenTiangViewModel +import com.jmnetwork.e_jartas.viewModel.ViewModelFactory + +class ListTitikTiangFragment : Fragment() { + + private var _binding: FragmentListTitikTiangBinding? = null + private val binding get() = _binding!! + private lateinit var viewModel: ManajemenTiangViewModel + private lateinit var adapter: TitikTiangAdapter + + private var currentSearchQuery: String? = null + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentListTitikTiangBinding.inflate(inflater, container, false) + val factory = ViewModelFactory.getInstance(requireActivity().application) + viewModel = ViewModelProvider(requireActivity(), factory)[ManajemenTiangViewModel::class.java] + adapter = TitikTiangAdapter() + + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + if (requireActivity().supportFragmentManager.backStackEntryCount > 0) { + requireActivity().supportFragmentManager.popBackStack() + } else { + val intent = Intent(requireContext(), MainActivity::class.java) + startActivity(intent) + requireActivity().finish() + } + } + }) + + var page = 1 + val limit = 10 + var totalPage = 0 + + binding.apply { + btnBack.setOnClickListener { + requireActivity().onBackPressedDispatcher.onBackPressed() + } + + viewModel.apply { + tiangData.observe(viewLifecycleOwner) { + if (it != null) { + adapter.setItem(it.values.toList()) + progressBar.visibility = View.GONE + totalPage = totalDataTiang.value?.div(limit) ?: 0 + totalPage += if (totalDataTiang.value?.rem(limit) != 0) 1 else 0 + } else { + adapter.setItem(emptyList()) + } + } + } + + rvTiang.apply { + layoutManager = LinearLayoutManager(requireContext()) + setHasFixedSize(false) + adapter = this@ListTitikTiangFragment.adapter + addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + val layoutManager = recyclerView.layoutManager as LinearLayoutManager + val lastVisibleItem = layoutManager.findLastVisibleItemPosition() + val totalItemCount = layoutManager.itemCount + + if (lastVisibleItem == totalItemCount - 1 && page < totalPage) { + progressBar.visibility = View.VISIBLE + page += 1 + viewModel.getTitikTiang(limit, page) + currentSearchQuery?.let { this@ListTitikTiangFragment.adapter.filter.filter(it) } + } + } + }) + } + + searchView.setOnClickListener { + searchView.isIconified = false + } + searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(query: String?): Boolean { + return false + } + + override fun onQueryTextChange(newText: String?): Boolean { + currentSearchQuery = newText + adapter.filter.filter(newText) + return false + } + }) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/titikTiang/TitikTiangActivity.kt b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/titikTiang/TitikTiangActivity.kt new file mode 100644 index 0000000..8eea89e --- /dev/null +++ b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/titikTiang/TitikTiangActivity.kt @@ -0,0 +1,35 @@ +package com.jmnetwork.e_jartas.view.manajemenTiang.titikTiang + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelProvider +import com.jmnetwork.e_jartas.R +import com.jmnetwork.e_jartas.databinding.ActivityTitikTiangBinding +import com.jmnetwork.e_jartas.viewModel.ManajemenTiangViewModel +import com.jmnetwork.e_jartas.viewModel.ViewModelFactory + +class TitikTiangActivity : AppCompatActivity() { + + private lateinit var binding: ActivityTitikTiangBinding + lateinit var viewModel: ManajemenTiangViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityTitikTiangBinding.inflate(layoutInflater) + setContentView(binding.root) + val factory = ViewModelFactory.getInstance(this@TitikTiangActivity.application) + viewModel = ViewModelProvider(this@TitikTiangActivity, factory)[ManajemenTiangViewModel::class.java] + viewModel.getTitikTiang(5, 1) // Get Titik Tiang data from API + + loadFragment(ListTitikTiangFragment()) + } + + private fun loadFragment(fragment: Fragment) { + supportFragmentManager.beginTransaction() + .setReorderingAllowed(true) + .replace(R.id.titik_tiang_fragment_container, fragment) + .setTransition(androidx.fragment.app.FragmentTransaction.TRANSIT_FRAGMENT_FADE) + .commit() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/titikTiang/TitikTiangAdapter.kt b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/titikTiang/TitikTiangAdapter.kt new file mode 100644 index 0000000..ff964dc --- /dev/null +++ b/app/src/main/java/com/jmnetwork/e_jartas/view/manajemenTiang/titikTiang/TitikTiangAdapter.kt @@ -0,0 +1,137 @@ +package com.jmnetwork.e_jartas.view.manajemenTiang.titikTiang + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Filter +import android.widget.Filterable +import android.widget.LinearLayout +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.constraintlayout.widget.ConstraintSet +import androidx.recyclerview.widget.RecyclerView +import com.jmnetwork.e_jartas.R +import com.jmnetwork.e_jartas.databinding.ItemTiangBinding +import com.jmnetwork.e_jartas.model.TiangData +import com.jmnetwork.e_jartas.model.TiangProvider +import com.jmnetwork.e_jartas.utils.Utils + +class TitikTiangAdapter : RecyclerView.Adapter(), Filterable { + + private var list = ArrayList() + private var listFiltered = ArrayList() + + fun setItem(item: List?) { + if (item == null) return + this.list.clear() + this.listFiltered.clear() + val prevSize = list.size + this.list.addAll(item) + this.listFiltered = ArrayList(this.list) // Make a copy of the original list + notifyItemRangeChanged(prevSize, item.size) + } + + inner class ItemHolder(private val binding: ItemTiangBinding) : RecyclerView.ViewHolder(binding.root) { + private var linearLayout: LinearLayout? = null + + fun bind(item: TiangData) { + binding.apply { + tvIdTiang.text = itemView.context.getString(R.string.id_tiang, item.idtiang) + tvlTglBuat.text = itemView.context.getString(R.string.tanggal_buat, Utils().formatDate(item.createddate)) + tvTglData.text = itemView.context.getString(R.string.tanggal_data, Utils().formatDate(item.lastupdate)) + + if (item.tiangProvider != TiangProvider()) { + linearLayout = LinearLayout(itemView.context).apply { + id = View.generateViewId() + orientation = LinearLayout.VERTICAL + layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + } + + for (tiangProvider in item.tiangProvider) { + val inflater = LayoutInflater.from(itemView.context) + val tiangProviderView = inflater.inflate(R.layout.item_tiang_provider, linearLayout, false) + + val number = tiangProviderView.findViewById(R.id.tv_no_provider) + val provider = tiangProviderView.findViewById(R.id.tv_provider) + val utilitas = tiangProviderView.findViewById(R.id.tv_utilitas) + val catatan = tiangProviderView.findViewById(R.id.tv_catatan) + + number.text = itemView.context.getString(R.string.tiang_provider_number, item.tiangProvider.indexOf(tiangProvider) + 1) + provider.text = itemView.context.getString(R.string.tiang_provider, tiangProvider.provider) + utilitas.text = itemView.context.getString(R.string.tiang_utilitas, tiangProvider.utilitas) + catatan.text = itemView.context.getString(R.string.tiang_catatan, tiangProvider.catatan) + + linearLayout!!.addView(tiangProviderView) + } + + (tvListProvider.parent as ConstraintLayout).addView(linearLayout) + ConstraintSet().apply { + clone(tvListProvider.parent as ConstraintLayout) + connect(linearLayout!!.id, ConstraintSet.TOP, tvListProvider.id, ConstraintSet.BOTTOM) + connect(linearLayout!!.id, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START) + applyTo(tvListProvider.parent as ConstraintLayout) + } + } + + } + } + + fun clearLinearLayout() { + // Remove all views from the LinearLayout when the view is recycled + linearLayout?.removeAllViews() + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder { + val itemBinding = ItemTiangBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return ItemHolder(itemBinding) + } + + override fun onBindViewHolder(holder: ItemHolder, position: Int) { + val item = listFiltered[position] // Use the filtered list + holder.bind(item) + } + + override fun onViewRecycled(holder: ItemHolder) { + super.onViewRecycled(holder) + // Call the clearLinearLayout method when the view is recycled + holder.clearLinearLayout() + } + + override fun getItemCount(): Int = listFiltered.size // Return the size of the filtered list + + override fun getFilter(): Filter { + return object : Filter() { + override fun performFiltering(constraint: CharSequence?): FilterResults { + val filterResults = FilterResults() + if (constraint == null || constraint.length < 0) { + filterResults.count = list.size + filterResults.values = ArrayList(list) // Make a copy of the original list + } else { + val charSearch = constraint.toString() + val resultList = ArrayList() + for (row in list) { // Filter the original list + for (tiangProvider in row.tiangProvider) { + if (tiangProvider.provider.lowercase().contains(charSearch.lowercase())) { + resultList.add(row) + } + } + } + filterResults.count = resultList.size + filterResults.values = resultList + } + return filterResults + } + + @SuppressLint("NotifyDataSetChanged") + override fun publishResults(constraint: CharSequence?, results: FilterResults?) { + listFiltered = results?.values as? ArrayList ?: arrayListOf() + notifyDataSetChanged() + } + } + } +} diff --git a/app/src/main/java/com/jmnetwork/e_jartas/viewModel/ManajemenTiangViewModel.kt b/app/src/main/java/com/jmnetwork/e_jartas/viewModel/ManajemenTiangViewModel.kt index bce8e22..55dce0f 100644 --- a/app/src/main/java/com/jmnetwork/e_jartas/viewModel/ManajemenTiangViewModel.kt +++ b/app/src/main/java/com/jmnetwork/e_jartas/viewModel/ManajemenTiangViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.ViewModel import com.jmnetwork.e_jartas.model.Additional import com.jmnetwork.e_jartas.model.ProviderData import com.jmnetwork.e_jartas.model.ProviderRequest +import com.jmnetwork.e_jartas.model.TiangData import com.jmnetwork.e_jartas.repository.ManajemenTiangRepositoryImpl import com.jmnetwork.e_jartas.utils.Constants import com.jmnetwork.e_jartas.utils.MySharedPreferences @@ -19,11 +20,13 @@ class ManajemenTiangViewModel(application: Application) : ViewModel() { private val idAdmin = myPreferences.getValueInteger(Constants.USER_IDADMIN) val providerData: MutableLiveData> = MutableLiveData(mapOf()) - val totalData: MutableLiveData = MutableLiveData(0) + val tiangData: MutableLiveData> = MutableLiveData(mapOf()) + val totalDataProvider: MutableLiveData = MutableLiveData(0) + val totalDataTiang: MutableLiveData = MutableLiveData(0) fun getProvider(limit: Int, page: Int) { repository.getProvider(appContext, limit, page, tokenAuth).observeForever { - totalData.postValue(it.totalData.totalData) + totalDataProvider.postValue(it.totalData.totalData) val currentData = providerData.value?.toMutableMap() ?: mutableMapOf() val updatedData = currentData.toMutableMap() @@ -37,11 +40,27 @@ class ManajemenTiangViewModel(application: Application) : ViewModel() { } } - private var requestData: ProviderRequest = ProviderRequest( + fun getTitikTiang(limit: Int, page: Int) { + repository.getTitikTiang(appContext, limit, page, tokenAuth).observeForever { + totalDataTiang.postValue(it.totalData.totalTiang) + val currentData = tiangData.value?.toMutableMap() ?: mutableMapOf() + val updatedData = currentData.toMutableMap() + + it.data.forEach { data -> + if (updatedData[data.idtiang] == null) { + updatedData[data.idtiang] = data + } + } + + tiangData.postValue(updatedData) + } + } + + private var requestDataProvider: ProviderRequest = ProviderRequest( Additional(), "", "" ) - fun setRequestData( + fun setRequestDataProvider( additional: Additional, alamat: String, provider: String @@ -55,7 +74,7 @@ class ManajemenTiangViewModel(application: Application) : ViewModel() { if (field.isEmpty()) return "$message tidak boleh kosong" } - requestData = ProviderRequest( + requestDataProvider = ProviderRequest( additional, alamat, provider @@ -65,7 +84,7 @@ class ManajemenTiangViewModel(application: Application) : ViewModel() { } fun addProvider(callback: (String, String) -> Unit) { - repository.addProvider(appContext, idAdmin, requestData, tokenAuth).observeForever { + repository.addProvider(appContext, idAdmin, requestDataProvider, tokenAuth).observeForever { callback(it.status, it.message) } } @@ -86,15 +105,15 @@ class ManajemenTiangViewModel(application: Application) : ViewModel() { } fun editProvider(idProvider: Int, callback: (String, String) -> Unit) { - repository.editProvider(appContext, idAdmin, idProvider, requestData, tokenAuth).observeForever { it -> + repository.editProvider(appContext, idAdmin, idProvider, requestDataProvider, tokenAuth).observeForever { it -> if (it.status == "success") { val currentData = providerData.value?.toMutableMap() ?: mutableMapOf() val updatedData = currentData.toMutableMap() updatedData[idProvider]?.let { updatedData[idProvider] = it.copy( - alamat = requestData.alamat, - provider = requestData.provider + alamat = requestDataProvider.alamat, + provider = requestDataProvider.provider ) } providerData.postValue(updatedData) diff --git a/app/src/main/res/layout/activity_provider.xml b/app/src/main/res/layout/activity_provider.xml index 09fd822..ce38b76 100644 --- a/app/src/main/res/layout/activity_provider.xml +++ b/app/src/main/res/layout/activity_provider.xml @@ -4,6 +4,6 @@ android:id="@+id/provider_fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".view.manajemenTiang.ProviderActivity"> + tools:context=".view.manajemenTiang.provider.ProviderActivity"> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_titik_tiang.xml b/app/src/main/res/layout/activity_titik_tiang.xml new file mode 100644 index 0000000..0310683 --- /dev/null +++ b/app/src/main/res/layout/activity_titik_tiang.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/form_provider.xml b/app/src/main/res/layout/form_provider.xml index c8cbedf..35620ca 100644 --- a/app/src/main/res/layout/form_provider.xml +++ b/app/src/main/res/layout/form_provider.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".view.manajemenTiang.AddProviderFragment"> + tools:context=".view.manajemenTiang.provider.AddProviderFragment"> + tools:context=".view.manajemenTiang.provider.ListProviderFragment"> + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_tiang.xml b/app/src/main/res/layout/item_tiang.xml new file mode 100644 index 0000000..9285d4f --- /dev/null +++ b/app/src/main/res/layout/item_tiang.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_tiang_provider.xml b/app/src/main/res/layout/item_tiang_provider.xml new file mode 100644 index 0000000..949ece9 --- /dev/null +++ b/app/src/main/res/layout/item_tiang_provider.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 907a5c3..e17432c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -78,7 +78,12 @@ Titik Tiang Blacklist Buka Blacklist - - Hello blank fragment Edit Provider + Tanggal Pembuatan: %1$s + Tanggal Pendataan: %1$s + Provider: %1$s + %1$d. + Utilitas: %1$s + Catatan: %1$s + ID: %1$d \ No newline at end of file