diff --git a/app/build.gradle.kts b/app/build.gradle.kts index bf187d0..ca1146f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -59,6 +59,7 @@ dependencies { implementation(libs.okhttp) implementation(libs.logging.interceptor) implementation(libs.androidx.swiperefreshlayout) + implementation(libs.glide) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 34aa121..f177105 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,7 +4,11 @@ + + + + @@ -29,10 +34,24 @@ + android:exported="true" + android:screenOrientation="portrait" + /> + android:exported="true" + android:screenOrientation="portrait" + /> + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/fieldagent/data/apis/WebService.kt b/app/src/main/java/com/example/fieldagent/data/apis/WebService.kt index 71a269d..e40064e 100644 --- a/app/src/main/java/com/example/fieldagent/data/apis/WebService.kt +++ b/app/src/main/java/com/example/fieldagent/data/apis/WebService.kt @@ -1,17 +1,11 @@ package com.example.fieldagent.data.apis -import com.example.fieldagent.data.models.responses.UserData -import com.example.fieldagent.data.network.responseUtil.ApiResponse -import retrofit2.http.FieldMap -import retrofit2.http.FormUrlEncoded -import retrofit2.http.POST +import com.example.fieldagent.data.models.responses.* +import com.example.fieldagent.data.network.responseUtil.ApiResponse +import okhttp3.RequestBody import retrofit2.Call -import retrofit2.http.DELETE -import retrofit2.http.GET -import retrofit2.http.PUT -import retrofit2.http.Path -import retrofit2.http.QueryMap +import retrofit2.http.* interface WebService { companion object { @@ -125,15 +119,16 @@ interface WebService { /*POST APIS*/ @FormUrlEncoded @POST(LOGIN) - fun login(@FieldMap hashMap: HashMap): Call> + fun login(@FieldMap hashMap: HashMap): Call @GET(INSPECTIONS_LIST) - fun inspectionsList(@QueryMap hashMap: Map): Call> + fun inspectionsList(@QueryMap hashMap: Map): Call + @Multipart @POST(CREATE_INSPECTION) - fun createInspections(@QueryMap hashMap: Map): Call> + fun createInspections(@PartMap map: HashMap): Call @GET(DAMAGES) @@ -141,7 +136,7 @@ interface WebService { @POST(DAMAGES) - fun createDamage(@QueryMap hashMap: Map): Call> + fun createDamage(@FieldMap hashMap: Map): Call> @DELETE("$DELETE_INSPECTIONS/{id}") diff --git a/app/src/main/java/com/example/fieldagent/data/models/responses/InspectionData.kt b/app/src/main/java/com/example/fieldagent/data/models/responses/InspectionData.kt new file mode 100644 index 0000000..78036a1 --- /dev/null +++ b/app/src/main/java/com/example/fieldagent/data/models/responses/InspectionData.kt @@ -0,0 +1,43 @@ +package com.example.fieldagent.data.models.responses + + +data class InspectionData ( + val status: Long? = null, + val success: Boolean? = null, + val message: String? = null, + val data: ListData? = null +) + +data class ListData ( + val inspections: List? = null, + val pagination: Pagination? = null +) + +data class InspectionList ( + val id: Long? = null, + val userID: Long? = null, + val name: String? = null, + val location: String? = null, + val supervisorName: String? = null, + val supervisorPhoneNumber: String? = null, + val siteCondition: String? = null, + val area: Long? = null, + val womenPrayerArea: Boolean? = null, + val totalCapacity: Long? = null, + val totalRestrooms: Long? = null, + val isCompleted: Boolean? = null, + val isDeleted: Boolean? = null, + val createdAt: String? = null, + val updatedAt: String? = null, + val damages: List? = null +) + +data class Pagination ( + val total: Long? = null, + val page: Long? = null, + val limit: Long? = null, + val totalPages: Long? = null, + val hasNextPage: Boolean? = null, + val hasPrevPage: Boolean? = null +) + diff --git a/app/src/main/java/com/example/fieldagent/data/models/responses/UserData.kt b/app/src/main/java/com/example/fieldagent/data/models/responses/UserData.kt index ff93771..47fe443 100644 --- a/app/src/main/java/com/example/fieldagent/data/models/responses/UserData.kt +++ b/app/src/main/java/com/example/fieldagent/data/models/responses/UserData.kt @@ -1,11 +1,13 @@ package com.example.fieldagent.data.models.responses +import java.io.Serializable + data class UserData ( val status: Long? = null, val success: Boolean? = null, val message: String? = null, val data: Data? = null -) +):Serializable data class Data ( val id: Long? = null, @@ -16,9 +18,9 @@ data class Data ( val createdAt: String? = null, val updatedAt: String? = null, val tokens: Tokens? = null -) +):Serializable data class Tokens ( val accessToken: String? = null, val refreshToken: String? = null -) +):Serializable diff --git a/app/src/main/java/com/example/fieldagent/di/NetworkModule.kt b/app/src/main/java/com/example/fieldagent/di/NetworkModule.kt index 1188694..4aec1cf 100644 --- a/app/src/main/java/com/example/fieldagent/di/NetworkModule.kt +++ b/app/src/main/java/com/example/fieldagent/di/NetworkModule.kt @@ -1,9 +1,11 @@ package com.example.fieldagent.di +import android.util.Log import com.example.fieldagent.data.apis.WebService import com.example.fieldagent.data.models.responses.UserData import com.example.fieldagent.data.network.Config import com.example.fieldagent.utils.PrefsManager +import com.example.fieldagent.utils.TOKEN import com.example.fieldagent.utils.USER_DATA import com.google.gson.Gson import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory @@ -53,13 +55,18 @@ object NetworkModule { .build() } + private fun getNetworkInterceptor(prefsManager: PrefsManager): Interceptor { return Interceptor { chain -> var request = chain.request() - val requestBuilder = request.newBuilder() + requestBuilder.addHeader("Accept", "application/json") + .header("Connection", "close") - val accessToken = prefsManager.getObject(USER_DATA, UserData::class.java)?.data?.tokens?.accessToken + .addHeader("timezone", TimeZone.getDefault().id) + + + val accessToken = prefsManager.getString(TOKEN,"") if (!accessToken.isNullOrEmpty()) requestBuilder.addHeader("authorization", "Bearer $accessToken") diff --git a/app/src/main/java/com/example/fieldagent/ui/addsite/AddSiteFragment.kt b/app/src/main/java/com/example/fieldagent/ui/addsite/AddSiteFragment.kt index a1c2db3..5889862 100644 --- a/app/src/main/java/com/example/fieldagent/ui/addsite/AddSiteFragment.kt +++ b/app/src/main/java/com/example/fieldagent/ui/addsite/AddSiteFragment.kt @@ -1,25 +1,81 @@ package com.example.fieldagent.ui.addsite +import android.Manifest +import android.app.Dialog +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.net.Uri +import android.os.Build import android.os.Bundle +import android.os.Environment import android.util.Log +import android.util.Patterns import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.Window import android.widget.ArrayAdapter +import android.widget.Toast +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.PickVisualMediaRequest +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.content.FileProvider +import androidx.fragment.app.viewModels +import androidx.lifecycle.Observer import androidx.navigation.fragment.findNavController +import com.bumptech.glide.Glide +import com.consultantapp.data.network.responseUtil.Status import com.example.fieldagent.R +import com.example.fieldagent.data.models.responses.UserData +import com.example.fieldagent.data.network.ApisRespHandler import com.example.fieldagent.databinding.FragmentAddSiteBinding import com.example.fieldagent.databinding.FragmentHomeBinding +import com.example.fieldagent.databinding.SelectPhotoBinding +import com.example.fieldagent.ui.homescreen.HomeViewModel import com.example.fieldagent.ui.homescreen.adapter.HomeAdapter +import com.example.fieldagent.utils.PER_PAGE_LOAD +import com.example.fieldagent.utils.PrefsManager +import com.example.fieldagent.utils.dialogs.ProgressDialog +import com.example.fieldagent.utils.getRequestBody +import com.example.fieldagent.utils.gone +import com.example.fieldagent.utils.hideShowView +import com.example.fieldagent.utils.isConnectedToInternet +import com.example.fieldagent.utils.showSnackBar +import com.example.fieldagent.utils.visible +import dagger.hilt.android.AndroidEntryPoint +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.asRequestBody +import java.io.File +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale +import javax.inject.Inject +@AndroidEntryPoint class AddSiteFragment : Fragment() { private var _binding: FragmentAddSiteBinding? = null private val binding get() = _binding!! + private val viewModel: AddSiteViewModel by viewModels() + + @Inject + lateinit var prefsManager: PrefsManager + + private lateinit var progressDialog: ProgressDialog + + private var image:String=""; + private var selectWomenPrayerArea:String="" + private var selectRestroom:String="" + + private lateinit var cameraLauncher: ActivityResultLauncher + private lateinit var galleryLauncher: ActivityResultLauncher + private lateinit var permissionLauncher: ActivityResultLauncher> + private var imageUri: Uri? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -32,7 +88,18 @@ class AddSiteFragment : Fragment() { super.onViewCreated(view, savedInstanceState) + initialize() + listener() + bindObservers() + + + } + + private fun initialize() { + + selectWomenPrayerArea=getString(R.string.yes) + selectRestroom=getString(R.string.ok_condition) val options = resources.getStringArray(R.array.availability).toList() val adapter = ArrayAdapter(requireActivity(), R.layout.dropdown_item, options) @@ -43,6 +110,12 @@ class AddSiteFragment : Fragment() { binding.autoCompleteBuilding.showDropDown() } + binding.autoCompleteBuilding.setOnItemClickListener { parent, view, position, id -> + val selectedItem = parent.getItemAtPosition(position) as String + Log.d("SELECTED_ITEM", "User selected: $selectedItem") + selectWomenPrayerArea=selectedItem; + } + val options2 = resources.getStringArray(R.array.condition).toList() val adapter2 = ArrayAdapter(requireActivity(), R.layout.dropdown_item, options2) @@ -54,18 +127,189 @@ class AddSiteFragment : Fragment() { binding.autoCompleteTextView.showDropDown() } + binding.autoCompleteBuilding.setOnItemClickListener { parent, view, position, id -> + val selectedItem = parent.getItemAtPosition(position) as String + Log.d("SELECTED_ITEM", "User selected: $selectedItem") + selectRestroom=selectedItem; + } + + } + + private fun listener(){ + + + binding.ivLeft.setOnClickListener { findNavController().popBackStack() } + + + binding.btnAdd.setOnClickListener { + + + when{ + binding.etName.text.toString().isEmpty() -> { + binding.etName.showSnackBar(getString(R.string.please_enter_your_name)) + } + + binding.etLocation.text.toString().isEmpty() -> { + binding.etLocation.showSnackBar(getString(R.string.please_enter_your_location)) + } + + binding.etSupervisorContact.text.toString().isEmpty() -> { + binding.etSupervisorContact.showSnackBar(getString(R.string.please_enter_supervisor_contact_number)) + } + + binding.etSupervisorAuthority.text.toString().isEmpty() -> { + binding.etSupervisorAuthority.showSnackBar(getString(R.string.please_enter_supervisor_authority_mosque)) + } + + binding.etBuildingCondition.text.toString().isEmpty() -> { + binding.etBuildingCondition.showSnackBar(getString(R.string.please_enter_building_condition)) + } + + binding.etMosqueArea.text.toString().isEmpty() -> { + binding.etMosqueArea.showSnackBar(getString(R.string.please_enter_mosque_area)) + } + binding.etApproximateNumber.text.toString().isEmpty() -> { + binding.etApproximateNumber.showSnackBar(getString(R.string.please_enter_approximate_number_worshippers)) + } + image.isEmpty() -> { + binding.rvImage.showSnackBar(getString(R.string.please_select_image)) + } + isConnectedToInternet(requireActivity(), true) -> { + val hashMap = HashMap() + hashMap["name"] = getRequestBody(binding.etName.text.toString()) + hashMap["location"] = getRequestBody(binding.etLocation.text.toString()) + hashMap["supervisor_name"] = getRequestBody(binding.etSupervisorAuthority.text.toString()) + hashMap["supervisor_phone_number"] = getRequestBody(binding.etSupervisorContact.text.toString()) + hashMap["site_condition"] = getRequestBody(binding.etBuildingCondition.text.toString()) + hashMap["area"] = getRequestBody(binding.etMosqueArea.text.toString()) + //hashMap["women_prayer_area"] = binding.wom.text.toString() + hashMap["total_capacity"] = getRequestBody(binding.etApproximateNumber.text.toString()) + //hashMap["total_restrooms"] = binding.etPassword.text.toString() + + + // val body: RequestBody = fileToUpload?.asRequestBody("image/*".toMediaType())!! + // hashMap["image\"; fileName=\"" + fileToUpload?.name] = body*/ + // viewModel.addSites(hashMap) + } + } + + } + + + binding.rvImage.setOnClickListener { + showImageDialog(); + } + + cameraLauncher = registerForActivityResult(ActivityResultContracts.TakePicture()) { success -> + if (success) { + imageUri?.let { + // Handle image from camera + binding.rvImage.gone() + binding.ivSetImage.setImageURI(imageUri) + binding.ivCloseImage.visible() + } + } + } + + galleryLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) { uri -> + uri?.let { + + binding.llUploadImage.gone() + binding.ivSetImage.visible() + Glide.with(this).load(imageUri).into(binding.ivSetImage) + binding.ivCloseImage.visible() + + } + } + + binding.ivCloseImage.setOnClickListener { + + binding.llUploadImage.visible() + binding.ivSetImage.visible() + Glide.with(this).load(imageUri).into(binding.ivSetImage) + binding.ivCloseImage.visible() + } + + // Permission launcher + permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> + if (permissions[Manifest.permission.CAMERA] == true) { + openCamera() + } else { + Toast.makeText(requireContext(), "Camera permission denied", Toast.LENGTH_SHORT).show() + } + } } + private fun bindObservers() { + viewModel.sites.observe(requireActivity(), Observer { + it ?: return@Observer + when (it.status) { + Status.SUCCESS -> { + + findNavController().popBackStack(); + progressDialog.setLoading(false) + } + Status.ERROR -> { + progressDialog.setLoading(false) + ApisRespHandler.handleError(it.error, requireActivity()) + } + Status.LOADING -> { + progressDialog.setLoading(true) + } + } + }) + } + + fun showImageDialog() { + val dialog: Dialog = Dialog(requireActivity()) + val view = SelectPhotoBinding.inflate(layoutInflater) + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE) + dialog.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + dialog.setContentView(view.root) + + view.tvGallery.setOnClickListener { + galleryLauncher.launch("image/*") + dialog.dismiss() + } + + + view.tvCamera.setOnClickListener { + permissionLauncher.launch(arrayOf(Manifest.permission.CAMERA)) + + dialog.dismiss() + } + dialog.show() + } + + + private fun openCamera() { + imageUri = FileProvider.getUriForFile( + requireContext(), + "${requireContext().packageName}.provider", + createImageFile() + ) + cameraLauncher.launch(imageUri!!) + + + } + + private fun createImageFile(): File { + val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date()) + val fileName = "JPEG_${timeStamp}_" + val storageDir = requireContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES) + return File.createTempFile(fileName, ".jpg", storageDir) + } override fun onDestroyView() { super.onDestroyView() _binding = null } + } \ No newline at end of file diff --git a/app/src/main/java/com/example/fieldagent/ui/addsite/AddSiteViewModel.kt b/app/src/main/java/com/example/fieldagent/ui/addsite/AddSiteViewModel.kt new file mode 100644 index 0000000..c68f016 --- /dev/null +++ b/app/src/main/java/com/example/fieldagent/ui/addsite/AddSiteViewModel.kt @@ -0,0 +1,50 @@ +package com.example.fieldagent.ui.addsite + +import androidx.lifecycle.ViewModel +import com.example.fieldagent.data.apis.WebService +import com.example.fieldagent.data.models.responses.UserData +import com.example.fieldagent.data.network.responseUtil.ApiResponse +import com.example.fieldagent.data.network.responseUtil.ApiUtils +import com.example.fieldagent.data.network.responseUtil.Resource +import com.example.fieldagent.di.SingleLiveEvent +import dagger.hilt.android.lifecycle.HiltViewModel +import okhttp3.RequestBody +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import javax.inject.Inject + + +@HiltViewModel +class AddSiteViewModel @Inject constructor(private val webService: WebService) : ViewModel() { + + val sites by lazy { SingleLiveEvent>() } + + fun addSites(hashMap: HashMap) { + sites.value = Resource.loading() + + webService.createInspections(hashMap) + .enqueue(object : Callback { + + override fun onResponse(call: Call, + response: Response + ) { + if (response.isSuccessful) { + sites.value = Resource.success(response.body()) + + } else { + sites.value = Resource.error( + ApiUtils.getError(response.code(), + response.errorBody()?.string())) + } + } + + override fun onFailure(call: Call, throwable: Throwable) { + sites.value = Resource.error(ApiUtils.failure(throwable)) + } + + }) + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/fieldagent/ui/homescreen/HomeFragment.kt b/app/src/main/java/com/example/fieldagent/ui/homescreen/HomeFragment.kt index d95eb3a..53bcfde 100644 --- a/app/src/main/java/com/example/fieldagent/ui/homescreen/HomeFragment.kt +++ b/app/src/main/java/com/example/fieldagent/ui/homescreen/HomeFragment.kt @@ -7,6 +7,7 @@ import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.text.Editable import android.text.TextWatcher +import android.util.Log import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View @@ -21,6 +22,7 @@ import com.example.fieldagent.R import com.example.fieldagent.databinding.FragmentHomeBinding import com.example.fieldagent.ui.homescreen.adapter.HomeAdapter import androidx.core.graphics.drawable.toDrawable +import androidx.core.view.isVisible import androidx.fragment.app.viewModels import com.consultantapp.data.network.responseUtil.Status import com.example.fieldagent.data.network.ApisRespHandler @@ -36,11 +38,16 @@ import javax.inject.Inject import androidx.lifecycle.Observer import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.RecyclerView +import com.example.fieldagent.data.models.responses.InspectionData +import com.example.fieldagent.data.models.responses.InspectionList import com.example.fieldagent.data.models.responses.UserData import com.example.fieldagent.databinding.PopLayoutBinding import com.example.fieldagent.utils.AFTER +import com.example.fieldagent.utils.LIMIT_TEXT +import com.example.fieldagent.utils.PAGE_TEXT import com.example.fieldagent.utils.PER_PAGE import com.example.fieldagent.utils.PER_PAGE_LOAD +import com.example.fieldagent.utils.SEARCH import com.example.fieldagent.utils.gone import com.example.fieldagent.utils.hideShowView import com.example.fieldagent.utils.isConnectedToInternet @@ -61,17 +68,21 @@ class HomeFragment : Fragment() { lateinit var prefsManager: PrefsManager private val viewModel: HomeViewModel by viewModels() - private lateinit var progressDialog: ProgressDialog - private var items = ArrayList() + + private var items = ArrayList() private var isLastPage = false private var isFirstPage = true private var isLoadingMoreItems = false + private var pageNumber = 1 private var searchJob: Job? = null + private var click: String ="all" + private var searchData: String ="" + private var selectStatus: String ="" override fun onCreateView( @@ -100,8 +111,8 @@ class HomeFragment : Fragment() { prefsManager.save(IS_LOGIN,true) val hashMap = HashMap() - hashMap["limit"] = "10" - hashMap["Page"] = "1" + hashMap[LIMIT_TEXT] = PER_PAGE_LOAD + hashMap[PAGE_TEXT] = PER_PAGE viewModel.getInspectionList(hashMap); } @@ -120,11 +131,13 @@ class HomeFragment : Fragment() { } binding.llLogoutBtn.setOnClickListener { + prefsManager.removeAll() val intent = Intent(requireActivity(), LoginActivity::class.java) startActivity(intent) requireActivity().finish() } + binding.ivFilter.setOnClickListener { @@ -142,12 +155,18 @@ class HomeFragment : Fragment() { popupView.txtCompleted.setOnClickListener { refreshPagination() - hitApi(false) + click="status" + selectStatus="true" + callStatusSearchApi("true","") + popupWindow.dismiss() } popupView.txtInProgress.setOnClickListener { refreshPagination() - hitApi(false) + click="status" + selectStatus="false" + callStatusSearchApi("false","") + popupWindow.dismiss() } @@ -160,6 +179,7 @@ class HomeFragment : Fragment() { binding.swipeRefresh.setOnRefreshListener { + Log.e("hckkkk===>","swipes"); hitApi(true) } @@ -168,7 +188,6 @@ class HomeFragment : Fragment() { binding.rvList.addOnScrollListener(object : RecyclerView.OnScrollListener() { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { super.onScrolled(recyclerView, dx, dy) - val layoutManager = binding.rvList.layoutManager as LinearLayoutManager val totalItemCount = layoutManager.itemCount - 1 val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition() @@ -188,8 +207,17 @@ class HomeFragment : Fragment() { delay(300) // wait for user to stop typing (300ms) val query = s.toString() if (query.isNotBlank()) { + click="search" + searchData=query refreshPagination() - hitApi(false) + callStatusSearchApi("false",query) + }else{ + refreshPagination() + click="all" + val hashMap = HashMap() + hashMap[LIMIT_TEXT] = PER_PAGE_LOAD + hashMap[PAGE_TEXT] = PER_PAGE + viewModel.getInspectionList(hashMap); } } } @@ -200,24 +228,65 @@ class HomeFragment : Fragment() { } + private fun refreshPagination(){ + pageNumber=1; isLastPage = false isFirstPage = true isLoadingMoreItems = false } + private fun callStatusSearchApi( value:String,search:String){ + val hashMap = HashMap() + if(search.isEmpty()) + { + hashMap["isCompleted"] = value + }else{ + hashMap[SEARCH] = searchData + } + + hashMap[LIMIT_TEXT] = PER_PAGE_LOAD + hashMap[PAGE_TEXT] = PER_PAGE + + + viewModel.getInspectionList(hashMap); + } private fun hitApi(firstHit: Boolean) { if (isConnectedToInternet(requireContext(), true)) { if (firstHit) { + pageNumber=1 isFirstPage = true isLastPage = false } val hashMap = HashMap() if (!isFirstPage && items.isNotEmpty()) - // hashMap[AFTER] = items[items.size - 1].id ?: "" + { + pageNumber++ + hashMap[LIMIT_TEXT] = PER_PAGE_LOAD + hashMap[PAGE_TEXT] = pageNumber.toString() + if(click=="status") + { + hashMap["isCompleted"] = selectStatus + }else if(click=="search") + { + hashMap[SEARCH] = searchData + } + + + }else{ + if(click=="status") + { + hashMap["isCompleted"] = selectStatus + }else if(click=="search") + { + hashMap[SEARCH] = searchData + } + + hashMap[LIMIT_TEXT] = PER_PAGE_LOAD + hashMap[PAGE_TEXT] = PER_PAGE + } - hashMap[PER_PAGE] = PER_PAGE_LOAD.toString() viewModel.getInspectionList(hashMap) } else @@ -233,8 +302,8 @@ class HomeFragment : Fragment() { isLoadingMoreItems = false - // val tempList = it.data?.notifications ?: emptyList() - val tempList=ArrayList() + + val tempList = it.data?.data?.inspections ?: emptyList() if (isFirstPage) { isFirstPage = false items.clear() @@ -248,11 +317,13 @@ class HomeFragment : Fragment() { adapter.notifyItemRangeInserted(oldSize, items.size) } - isLastPage = tempList.size < PER_PAGE_LOAD - adapter.setAllItemsLoaded(isLastPage) + isLastPage = tempList.size < PER_PAGE_LOAD.toInt() + /* if(click!="search"){ + adapter.setAllItemsLoaded(isLastPage) + }*/ - binding.clNoData.rootView.hideShowView(items.isEmpty()) + binding.clNoData.hideShowView(items.isEmpty()) } Status.ERROR -> { isLoadingMoreItems = false @@ -263,7 +334,7 @@ class HomeFragment : Fragment() { ApisRespHandler.handleError(it.error, requireActivity()) } Status.LOADING -> { - if (!isLoadingMoreItems && !binding.swipeRefresh.isRefreshing) + if (!isLoadingMoreItems && !binding.swipeRefresh.isRefreshing && !binding.clNoData.isVisible && items.isEmpty()) binding.clLoader.root.visible() } } @@ -275,6 +346,11 @@ class HomeFragment : Fragment() { val item = items[pos] } + fun clickDeleteItem(pos: Int) { + items.removeAt(pos) + adapter.notifyDataSetChanged() + + } override fun onDestroyView() { diff --git a/app/src/main/java/com/example/fieldagent/ui/homescreen/HomeViewModel.kt b/app/src/main/java/com/example/fieldagent/ui/homescreen/HomeViewModel.kt index 26a5876..a35fd1e 100644 --- a/app/src/main/java/com/example/fieldagent/ui/homescreen/HomeViewModel.kt +++ b/app/src/main/java/com/example/fieldagent/ui/homescreen/HomeViewModel.kt @@ -2,6 +2,8 @@ package com.example.fieldagent.ui.homescreen import androidx.lifecycle.ViewModel import com.example.fieldagent.data.apis.WebService +import com.example.fieldagent.data.models.responses.InspectionData +import com.example.fieldagent.data.models.responses.InspectionList import com.example.fieldagent.data.models.responses.UserData import com.example.fieldagent.data.network.responseUtil.ApiResponse import com.example.fieldagent.data.network.responseUtil.ApiUtils @@ -17,19 +19,19 @@ import javax.inject.Inject @HiltViewModel class HomeViewModel @Inject constructor(private val webService: WebService) : ViewModel() { - val inspections by lazy { SingleLiveEvent>() } + val inspections by lazy { SingleLiveEvent>() } fun getInspectionList(hashMap: HashMap) { inspections.value = Resource.loading() webService.inspectionsList(hashMap) - .enqueue(object : Callback> { + .enqueue(object : Callback { - override fun onResponse(call: Call>, - response: Response> + override fun onResponse(call: Call, + response: Response ) { if (response.isSuccessful) { - inspections.value = Resource.success(response.body()?.data) + inspections.value = Resource.success(response.body()) } else { inspections.value = Resource.error( @@ -38,7 +40,7 @@ class HomeViewModel @Inject constructor(private val webService: WebService) : Vi } } - override fun onFailure(call: Call>, throwable: Throwable) { + override fun onFailure(call: Call, throwable: Throwable) { inspections.value = Resource.error(ApiUtils.failure(throwable)) } diff --git a/app/src/main/java/com/example/fieldagent/ui/homescreen/adapter/HomeAdapter.kt b/app/src/main/java/com/example/fieldagent/ui/homescreen/adapter/HomeAdapter.kt index d204087..bd39766 100644 --- a/app/src/main/java/com/example/fieldagent/ui/homescreen/adapter/HomeAdapter.kt +++ b/app/src/main/java/com/example/fieldagent/ui/homescreen/adapter/HomeAdapter.kt @@ -10,15 +10,18 @@ import androidx.navigation.findNavController import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.RecyclerView import com.example.fieldagent.R +import com.example.fieldagent.data.models.responses.InspectionData +import com.example.fieldagent.data.models.responses.InspectionList import com.example.fieldagent.data.models.responses.UserData import com.example.fieldagent.databinding.FragmentHomeBinding import com.example.fieldagent.databinding.HomeAdapterBinding import com.example.fieldagent.databinding.ItemPagingLoaderBinding import com.example.fieldagent.ui.homescreen.HomeFragment +import com.example.fieldagent.utils.DateUtils.getTimeAgo import com.example.fieldagent.utils.LoadingStatus.ITEM import com.example.fieldagent.utils.LoadingStatus.LOADING -class HomeAdapter(private val fragment: HomeFragment,private val items: ArrayList) : +class HomeAdapter(private val fragment: HomeFragment,private val items: ArrayList) : RecyclerView.Adapter() { private var allItemsLoaded = true @@ -48,15 +51,21 @@ class HomeAdapter(private val fragment: HomeFragment,private val items: ArrayLi binding.clMain.setOnClickListener { fragment.clickItem(bindingAdapterPosition) } + binding.ivDelete.setOnClickListener { + fragment.clickDeleteItem(bindingAdapterPosition) + } } - fun bind(item: UserData) = with(binding) { - /*tvName.text = item.message - - loadImage("tag",binding.ivPic, item.form_user?.profile_image, - R.drawable.image_placeholder) - - tvCallDuration.text = getTimeAgo(item.created_at)*/ + fun bind(item: InspectionList) = with(binding) { + binding.txtName.text=item.name.toString() + binding.txtLocation.text=item.location.toString() + binding.txtTime.text=getTimeAgo(item.createdAt.toString()) + binding.txtPayment.text="$ 0" + binding.txtStatus.text = if (item.isCompleted == true) { + binding.root.context.getString(R.string.completed) + } else { + binding.root.context.getString(R.string.in_progress) + } } } @@ -67,35 +76,3 @@ class HomeAdapter(private val fragment: HomeFragment,private val items: ArrayLi allItemsLoaded = allLoaded } } -/*(var homes: List) : RecyclerView.Adapter() { - - class HomeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - val nameText: TextView = itemView.findViewById(R.id.txtName) - val locationText: TextView = itemView.findViewById(R.id.txtLocation) - val timeText: TextView = itemView.findViewById(R.id.txtTime) - val moneyText: TextView = itemView.findViewById(R.id.txtPayment) - val statusText: TextView = itemView.findViewById(R.id.txtStatus) - val viewClick: RelativeLayout = itemView.findViewById(R.id.rlView) - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeViewHolder { - val view = LayoutInflater.from(parent.context).inflate(R.layout.home_adapter, parent, false) - return HomeViewHolder(view) - } - - override fun onBindViewHolder(holder: HomeViewHolder, position: Int) { - val user = homes[position] - holder.nameText.text = user.name - holder.locationText.text = user.address - holder.timeText.text = user.time - holder.moneyText.text = user.payment - holder.statusText.text = user.status - holder.viewClick.setOnClickListener {view-> - - view.findNavController().navigate(R.id.damageListFragment) - } - - } - - override fun getItemCount(): Int = homes.size -}*/ \ No newline at end of file diff --git a/app/src/main/java/com/example/fieldagent/ui/login/LoginActivity.kt b/app/src/main/java/com/example/fieldagent/ui/login/LoginActivity.kt index a3f8aa7..826e781 100644 --- a/app/src/main/java/com/example/fieldagent/ui/login/LoginActivity.kt +++ b/app/src/main/java/com/example/fieldagent/ui/login/LoginActivity.kt @@ -8,13 +8,15 @@ import android.util.Patterns import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.viewModels -import androidx.lifecycle.Observer import com.consultantapp.data.network.responseUtil.Status import com.example.fieldagent.R +import com.example.fieldagent.data.models.responses.UserData import com.example.fieldagent.data.network.ApisRespHandler import com.example.fieldagent.databinding.ActivityLoginBinding import com.example.fieldagent.ui.homescreen.HomeActivity +import androidx.lifecycle.Observer import com.example.fieldagent.utils.PrefsManager +import com.example.fieldagent.utils.TOKEN import com.example.fieldagent.utils.USER_DATA import com.example.fieldagent.utils.dialogs.ProgressDialog import com.example.fieldagent.utils.isConnectedToInternet @@ -79,9 +81,10 @@ class LoginActivity : AppCompatActivity() { when (it.status) { Status.SUCCESS -> { progressDialog.setLoading(false) + // prefsManager.save(USER_DATA, it.data?.data) + prefsManager.saveString(TOKEN,it.data?.data?.tokens?.accessToken.toString()) - prefsManager.save(USER_DATA, it.data) val intent = Intent(this, HomeActivity::class.java) startActivity(intent) finish() diff --git a/app/src/main/java/com/example/fieldagent/ui/login/LoginViewModel.kt b/app/src/main/java/com/example/fieldagent/ui/login/LoginViewModel.kt index 6c2fe44..43ad13f 100644 --- a/app/src/main/java/com/example/fieldagent/ui/login/LoginViewModel.kt +++ b/app/src/main/java/com/example/fieldagent/ui/login/LoginViewModel.kt @@ -1,6 +1,7 @@ package com.example.fieldagent.ui.login import android.content.Intent +import android.util.Log import androidx.core.content.ContextCompat.startActivity import androidx.lifecycle.ViewModel import com.example.fieldagent.data.apis.WebService @@ -25,13 +26,13 @@ class LoginViewModel @Inject constructor(private val webService: WebService) : V login.value = Resource.loading() webService.login(hashMap) - .enqueue(object : Callback> { + .enqueue(object : Callback { - override fun onResponse(call: Call>, - response: Response> + override fun onResponse(call: Call, + response: Response ) { if (response.isSuccessful) { - login.value = Resource.success(response.body()?.data) + login.value = Resource.success(response.body()) } else { login.value = Resource.error( @@ -40,7 +41,7 @@ class LoginViewModel @Inject constructor(private val webService: WebService) : V } } - override fun onFailure(call: Call>, throwable: Throwable) { + override fun onFailure(call: Call, throwable: Throwable) { login.value = Resource.error(ApiUtils.failure(throwable)) } diff --git a/app/src/main/java/com/example/fieldagent/utils/AppConstant.kt b/app/src/main/java/com/example/fieldagent/utils/AppConstant.kt index 6d1ce3d..bc6f51c 100644 --- a/app/src/main/java/com/example/fieldagent/utils/AppConstant.kt +++ b/app/src/main/java/com/example/fieldagent/utils/AppConstant.kt @@ -3,12 +3,17 @@ package com.example.fieldagent.utils const val USER_DATA = "userData" +const val TOKEN = "token" const val IS_LOGIN = "isLogin" const val AFTER = "after" const val BEFORE = "before" -const val PER_PAGE = "per_page" -const val PER_PAGE_LOAD = 10 +const val PER_PAGE = "1" +const val LIMIT_TEXT = "limit" +const val SEARCH = "search" +const val PAGE_TEXT = "page" +const val PER_PAGE_LOAD = "10" + object LoadingStatus { diff --git a/app/src/main/java/com/example/fieldagent/utils/DateUtils.kt b/app/src/main/java/com/example/fieldagent/utils/DateUtils.kt new file mode 100644 index 0000000..050ac9d --- /dev/null +++ b/app/src/main/java/com/example/fieldagent/utils/DateUtils.kt @@ -0,0 +1,66 @@ +package com.example.fieldagent.utils + +import android.text.format.DateUtils + +import java.text.SimpleDateFormat +import java.util.* + + +object DateUtils { + + val utcFormat = SimpleDateFormat(DateFormat.UTC_FORMAT_NORMAL, Locale.ENGLISH) + + + + fun getTimeAgo(createdAt: String?): String { + if (createdAt == null) return "" + + return try { + val utcFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()) + utcFormat.timeZone = TimeZone.getTimeZone("UTC") + + val pastTime = utcFormat.parse(createdAt)?.time ?: return "" + val now = System.currentTimeMillis() + + val seconds = (now - pastTime) / 1000 + val minutes = seconds / 60 + val hours = minutes / 60 + val days = hours / 24 + + return when { + seconds < 60 -> "$seconds seconds ago" + minutes < 60 -> "$minutes minutes ago" + hours < 24 -> "$hours hours ago" + days < 7 -> "$days days ago" + else -> { + val outputFormat = SimpleDateFormat("dd MMM yyyy", Locale.getDefault()) + outputFormat.format(Date(pastTime)) + } + } + } catch (e: Exception) { + e.printStackTrace() + "" + } + } + +} + + + +object DateFormat { + const val DATE_FORMAT = "yyyy-MM-dd" + const val DATE_TIME_FORMAT = "MMM dd, yyyy · hh:mm a" + const val DAY_DATE_FORMAT = "EEE · MMM dd, yyyy" + const val TIME_FORMAT = "hh:mm a" + const val TIME_FORMAT_24 = "HH:mm" + const val MON_DATE_YEAR = "MMM dd, yyyy" + const val MON_DATE = "MMM dd" + const val DATE_FORMAT_SLASH_YEAR = "dd/MM/yyyy" + const val UTC_FORMAT_NORMAL = "yyyy-MM-dd HH:mm:ss" + const val UTC_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" + const val DATE = "dd" + const val MONTH = "MM" + const val YEAR = "yyyy" + const val HH_24 = "HH" + const val MM = "mm" +} diff --git a/app/src/main/java/com/example/fieldagent/utils/GeneralFunction.kt b/app/src/main/java/com/example/fieldagent/utils/GeneralFunction.kt index a36975e..13e6112 100644 --- a/app/src/main/java/com/example/fieldagent/utils/GeneralFunction.kt +++ b/app/src/main/java/com/example/fieldagent/utils/GeneralFunction.kt @@ -7,8 +7,8 @@ import android.widget.Toast import androidx.core.content.ContextCompat import com.example.fieldagent.R import com.google.android.material.snackbar.Snackbar - - +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.RequestBody fun View.gone() { @@ -28,7 +28,9 @@ fun View.hideShowView(listIsEmpty: Boolean) { else View.GONE } - +fun getRequestBody(string: String?): RequestBody { + return RequestBody.create("text/plain".toMediaTypeOrNull(), string ?: "") +} fun View.showSnackBar(msg: String) { @@ -45,6 +47,7 @@ fun View.showSnackBar(msg: String) { } catch (e: Exception) { e.printStackTrace() } + } fun Context.longToast(text: CharSequence) { Toast.makeText(this, text, Toast.LENGTH_LONG).show() diff --git a/app/src/main/java/com/example/fieldagent/utils/PrefsManager.kt b/app/src/main/java/com/example/fieldagent/utils/PrefsManager.kt index 471e697..ff9dde7 100644 --- a/app/src/main/java/com/example/fieldagent/utils/PrefsManager.kt +++ b/app/src/main/java/com/example/fieldagent/utils/PrefsManager.kt @@ -15,7 +15,7 @@ class PrefsManager @Inject constructor(private val preferences: SharedPreference private lateinit var instance: PrefsManager fun get(): PrefsManager = instance } - fun save(@PrefKey key: String, value: String) { + fun saveString(@PrefKey key: String, value: String) { preferences.edit().putString(key, value).apply() } diff --git a/app/src/main/res/layout/fragment_add_site.xml b/app/src/main/res/layout/fragment_add_site.xml index ddf2e5f..7b73f30 100644 --- a/app/src/main/res/layout/fragment_add_site.xml +++ b/app/src/main/res/layout/fragment_add_site.xml @@ -411,20 +411,28 @@ android:layout_marginTop="@dimen/dp_4" android:background="@drawable/line_spce_line" android:layout_marginBottom="@dimen/dp_20" - - - > + + + + + + +