diff --git a/.idea/misc.xml b/.idea/misc.xml
index e41c484c..918a92d8 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -10,7 +10,7 @@
diff --git a/app/build.gradle b/app/build.gradle
index c1be5151..ddd93edd 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -185,5 +185,12 @@ dependencies {
// Daraja
implementation 'com.androidstudy.daraja:daraja:2.0.2'
+ // In App Updates
+ implementation("com.google.android.play:app-update-ktx:2.1.0")
+
+ // Google Firebase Analytics
+ implementation(platform("com.google.firebase:firebase-bom:33.4.0"))
+ implementation("com.google.firebase:firebase-analytics")
+
}
\ No newline at end of file
diff --git a/app/release/app-release.aab b/app/release/app-release.aab
new file mode 100644
index 00000000..6df1a359
Binary files /dev/null and b/app/release/app-release.aab differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1ac4e996..aff36a5e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,12 @@
+
+
+
+
@@ -11,6 +17,7 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/steve_md/smartmkulima/ShambaApp.kt b/app/src/main/java/com/steve_md/smartmkulima/ShambaApp.kt
index aeb3760d..9fdf6efa 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/ShambaApp.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/ShambaApp.kt
@@ -1,16 +1,17 @@
package com.steve_md.smartmkulima
-import android.app.Activity
import android.app.Application
import android.content.Context
import android.content.SharedPreferences
-import android.os.Build
+import android.os.Bundle
import android.os.StrictMode
import androidx.appcompat.app.AppCompatDelegate
+import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.database.FirebaseDatabase
-import com.steve_md.smartmkulima.utils.SnackbarHelper
import dagger.hilt.android.HiltAndroidApp
import timber.log.Timber
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
/**
@@ -19,16 +20,55 @@ import timber.log.Timber
*/
@HiltAndroidApp
class ShambaApp : Application() {
+
+ private lateinit var firebaseAnalytics: FirebaseAnalytics
override fun onCreate() {
super.onCreate()
timber()
- setNetworkSecurity()
+ // setNetworkSecurity()
FirebaseDatabase.getInstance().setPersistenceEnabled(true)
val sharedPreferences: SharedPreferences =
getSharedPreferences("ui_mode", Context.MODE_PRIVATE)
val itemUIMode: Boolean = sharedPreferences.getBoolean("ISCHECKED", false)
Timber.d("UI Theme: $itemUIMode")
uiMode(itemUIMode)
+
+ initializeSDKS()
+ }
+
+ private fun initializeSDKS() {
+ val executorService: ExecutorService = Executors.newFixedThreadPool(2)
+ executorService.execute {
+ initializeAnalyticsSDKS(context = this.applicationContext)
+ }
+
+ executorService.execute {
+ initializeCrashReportingSDKS()
+ }
+ }
+
+ private fun initializeCrashReportingSDKS() {
+
+ }
+
+ private fun initializeAnalyticsSDKS(context: Context) {
+ // Initialize Firebase Analytics
+ firebaseAnalytics = FirebaseAnalytics.getInstance(context)
+
+ // Example of logging an event after initialization
+ val bundle = Bundle().apply {
+ putString(FirebaseAnalytics.Param.METHOD, "app_start")
+ }
+
+ /*
+ firebaseAnalytics.logEvent(FirebaseAnalytics.Event.SELECT_CONTENT) {
+ param(FirebaseAnalytics.Param.ITEM_ID, bundle);
+ param(FirebaseAnalytics.Param.ITEM_NAME, name);
+ param(FirebaseAnalytics.Param.CONTENT_TYPE, "image");
+ }
+ */
+
+ firebaseAnalytics.logEvent(FirebaseAnalytics.Event.APP_OPEN, bundle)
}
@@ -44,9 +84,20 @@ class ShambaApp : Application() {
}
}
+ /**
+ * StrictMode is a developer tool which detects things you might be doing
+ * by accident and brings them to your attention so you can fix them
+ *
+ */
private fun setNetworkSecurity() {
val builder = StrictMode.VmPolicy.Builder()
- StrictMode.setVmPolicy(builder.build())
+ StrictMode.setVmPolicy(builder
+ .detectAll()
+ .detectLeakedSqlLiteObjects()
+ .detectLeakedClosableObjects()
+ .penaltyLog()
+ .penaltyDeath()
+ .build())
}
private fun timber() {
diff --git a/app/src/main/java/com/steve_md/smartmkulima/adapter/FarmProduceAdapter.kt b/app/src/main/java/com/steve_md/smartmkulima/adapter/FarmProduceAdapter.kt
index b200ef43..aec7e801 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/adapter/FarmProduceAdapter.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/adapter/FarmProduceAdapter.kt
@@ -8,10 +8,13 @@ import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.steve_md.smartmkulima.databinding.ProductsRowBinding
+import com.steve_md.smartmkulima.model.AgroDealer
import com.steve_md.smartmkulima.model.FarmProduce
-class FarmProduceAdapter : ListAdapter(MyDiffUtil) {
+class FarmProduceAdapter(
+ private val onClickListener: OnClickListener
+) : ListAdapter(MyDiffUtil) {
object MyDiffUtil : DiffUtil.ItemCallback() {
override fun areItemsTheSame(oldItem: FarmProduce, newItem: FarmProduce): Boolean {
return oldItem == newItem
@@ -47,5 +50,13 @@ class FarmProduceAdapter : ListAdapter Unit) {
+ fun onClick(farmProduce: FarmProduce) = clickListener(farmProduce)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/steve_md/smartmkulima/data/repositories/FarmCycleRepository.kt b/app/src/main/java/com/steve_md/smartmkulima/data/repositories/FarmCycleRepository.kt
index 9a9186c7..25dae904 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/data/repositories/FarmCycleRepository.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/data/repositories/FarmCycleRepository.kt
@@ -141,23 +141,34 @@ class FarmCycleRepository @Inject constructor(
}
suspend fun fieldAgentAddANewAgroDealer(fieldAgentAddAgroDealerData: FieldAgentAddAgroDealerData) = apiRequestByResource {
+
+ // Inserting AgroDealer Into db
fieldAgentAddAgrodealerDao.fieldAgentAddANewAgrodealer(fieldAgentAddAgroDealerData)
- }
- fun getAllFieldAgentAddedAgroDealers(): LiveData> {
- return fieldAgentAddAgrodealerDao.getAllFieldAgentAddedAgrodealers()
- }
+ // Update field agent points
+ val agentPoints = fieldAgentEarningsDao.getPointsByAgentId(fieldAgentAddAgroDealerData.agentId)
+ if (agentPoints != null) {
+ agentPoints.points += 10
+ agentPoints.earnings += 200.0
+ fieldAgentEarningsDao.saveOrUpdatePoints(agentPoints)
+ } else {
+ // First time this agent registers/ adds a new farmer
+ val newAgentPoints = FieldAgentEarnings(
+ fieldAgentID = fieldAgentAddAgroDealerData.agentId,
+ points = 10,
+ earnings = 200.0
+ )
- // Field agent earnings METHODS
- suspend fun saveEarnings(fieldAgentEarnings: FieldAgentEarnings) = apiRequestByResource {
- fieldAgentEarningsDao.saveFieldAgentEarnings(fieldAgentEarnings)
+ fieldAgentEarningsDao.saveOrUpdatePoints(newAgentPoints)
+ }
}
- suspend fun updateFieldAgentEarnings(newPoints: Int, earnings: Double) {
- fieldAgentEarningsDao.updateFieldAgentEarnings(newPoints, earnings)
+
+ suspend fun getAgentPoints(agentId: String): FieldAgentEarnings? {
+ return fieldAgentEarningsDao.getPointsByAgentId(agentId)
}
- fun getAllFieldAgentEarnings(): LiveData {
- return fieldAgentEarningsDao.fetchAllFieldAgentEarnings()
+ fun getAllFieldAgentAddedAgroDealers(): LiveData> {
+ return fieldAgentAddAgrodealerDao.getAllFieldAgentAddedAgrodealers()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/steve_md/smartmkulima/data/room/AppDatabase.kt b/app/src/main/java/com/steve_md/smartmkulima/data/room/AppDatabase.kt
index 7b0e3fa4..7f81fd30 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/data/room/AppDatabase.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/data/room/AppDatabase.kt
@@ -33,7 +33,7 @@ import com.steve_md.smartmkulima.model.responses.fieldagent.Data
OrderCheckoutByFarmer::class,
FieldAgentAddAgroDealerData::class,
Data::class, FieldAgentEarnings::class, com.steve_md.smartmkulima.model.responses.buyer.Data::class],
- version = 12,exportSchema = false)
+ version = 13,exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun transactionDao(): TransactionDao
diff --git a/app/src/main/java/com/steve_md/smartmkulima/data/room/FieldAgentEarningsDao.kt b/app/src/main/java/com/steve_md/smartmkulima/data/room/FieldAgentEarningsDao.kt
index a735230d..34b0cd42 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/data/room/FieldAgentEarningsDao.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/data/room/FieldAgentEarningsDao.kt
@@ -5,7 +5,6 @@ import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
-import com.steve_md.smartmkulima.model.OrderCheckoutByFarmer
import com.steve_md.smartmkulima.model.fieldagentmodels.FieldAgentEarnings
@@ -13,11 +12,9 @@ import com.steve_md.smartmkulima.model.fieldagentmodels.FieldAgentEarnings
interface FieldAgentEarningsDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
- suspend fun saveFieldAgentEarnings(fieldAgentEarnings: FieldAgentEarnings)
+ suspend fun saveOrUpdatePoints(fieldAgentEarnings: FieldAgentEarnings)
- @Query("UPDATE field_agents_earnings SET points =:newPoints, earnings = :newEarnings")
- suspend fun updateFieldAgentEarnings(newPoints: Int, newEarnings: Double)
-
- @Query("SELECT * FROM field_agents_earnings")
- fun fetchAllFieldAgentEarnings(): LiveData
+ @Query("SELECT * FROM field_agents_earnings WHERE fieldAgentID = :agentId LIMIT 1")
+ suspend fun getPointsByAgentId(agentId: String): FieldAgentEarnings? // Only expecting a single result.
+ // save loads of data and improve query performance.
}
\ No newline at end of file
diff --git a/app/src/main/java/com/steve_md/smartmkulima/model/fieldagentmodels/FieldAgentAddAgroDealerData.kt b/app/src/main/java/com/steve_md/smartmkulima/model/fieldagentmodels/FieldAgentAddAgroDealerData.kt
index 18cd9085..50ec15a6 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/model/fieldagentmodels/FieldAgentAddAgroDealerData.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/model/fieldagentmodels/FieldAgentAddAgroDealerData.kt
@@ -14,5 +14,7 @@ data class FieldAgentAddAgroDealerData(
val email: String,
val phone: String,
val location: String,
- val physicalLocationAddress: String
+ val physicalLocationAddress: String,
+ val agentId: String, // field agent who registered this farmer
+ val offers: String // offer categories ie. select where applicable
)
diff --git a/app/src/main/java/com/steve_md/smartmkulima/model/fieldagentmodels/FieldAgentEarnings.kt b/app/src/main/java/com/steve_md/smartmkulima/model/fieldagentmodels/FieldAgentEarnings.kt
index 339a4b8d..4f06f651 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/model/fieldagentmodels/FieldAgentEarnings.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/model/fieldagentmodels/FieldAgentEarnings.kt
@@ -4,10 +4,16 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
+
+/**
+ * A model data class to track the field agent's points
+ * for registering / adding new farmers.
+ */
@Entity(tableName = "field_agents_earnings")
data class FieldAgentEarnings(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
- val points: Int = 0,
- val earnings: Double = 0.0
+ val fieldAgentID: String,
+ var points: Int = 0,
+ var earnings: Double = 0.0
)
\ No newline at end of file
diff --git a/app/src/main/java/com/steve_md/smartmkulima/ui/activities/MainActivity.kt b/app/src/main/java/com/steve_md/smartmkulima/ui/activities/MainActivity.kt
index 4105d03a..4a3446cd 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/ui/activities/MainActivity.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/ui/activities/MainActivity.kt
@@ -12,6 +12,7 @@ import android.os.Bundle
import android.view.View
import android.view.Window
import android.view.WindowManager
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
@@ -19,10 +20,16 @@ import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.setupWithNavController
+import com.google.android.play.core.appupdate.AppUpdateManager
+import com.google.android.play.core.appupdate.AppUpdateManagerFactory
+import com.google.android.play.core.appupdate.AppUpdateOptions
+import com.google.android.play.core.install.model.AppUpdateType
+import com.google.android.play.core.install.model.UpdateAvailability
import com.steve_md.smartmkulima.R
import com.steve_md.smartmkulima.databinding.ActivityMainBinding
import com.steve_md.smartmkulima.utils.SnackbarHelper
import dagger.hilt.android.AndroidEntryPoint
+import timber.log.Timber
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@@ -32,6 +39,8 @@ class MainActivity : AppCompatActivity() {
private var screenCaptureCallback: ScreenCaptureCallback? = null
+ private val appUpdateManager: AppUpdateManager by lazy { AppUpdateManagerFactory.create(this) }
+
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -39,6 +48,7 @@ class MainActivity : AppCompatActivity() {
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
+ checkUpdate()
supportActionBar?.hide()
@@ -73,9 +83,34 @@ class MainActivity : AppCompatActivity() {
}
}
+ private val updateLauncher = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) {
+ if (it?.data == null) return@registerForActivityResult
+ if (it.resultCode == UPDATE_REQUEST_CODE) {
+ Timber.d("Download Started")
+ if (it.resultCode != Activity.RESULT_OK) {
+ Timber.d("Download Failed")
+ }
+ }
+ }
+ /**
+ * we are getting the info if the update is available or not
+ */
+ private fun checkUpdate() {
+ val appUpdateInfoTask = appUpdateManager.appUpdateInfo
+ appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
+ if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
+ appUpdateManager.startUpdateFlowForResult( // to start the app update process.
+ appUpdateInfo,
+ updateLauncher,
+ AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build())
+ }
+ }
+ }
-
+ companion object {
+ const val UPDATE_REQUEST_CODE = 1
+ }
}
diff --git a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/ManualWalkingFarmMappingFragment.kt b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/ManualWalkingFarmMappingFragment.kt
index e141aa81..f0d11022 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/ManualWalkingFarmMappingFragment.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/ManualWalkingFarmMappingFragment.kt
@@ -1,8 +1,10 @@
package com.steve_md.smartmkulima.ui.fragments.main
import android.Manifest
+import android.content.Context
import android.content.pm.PackageManager
-import android.location.Criteria
+import android.location.LocationListener
+import android.location.LocationManager
import android.os.Bundle
import android.os.Looper
import android.view.LayoutInflater
@@ -23,25 +25,26 @@ import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
+import com.google.android.gms.maps.model.MarkerOptions
import com.google.android.gms.maps.model.Polygon
import com.google.android.gms.maps.model.PolygonOptions
import com.google.android.gms.maps.model.PolylineOptions
import com.google.maps.android.SphericalUtil
+import com.google.maps.android.SphericalUtil.computeOffsetOrigin
import com.steve_md.smartmkulima.R
import com.steve_md.smartmkulima.databinding.FragmentManualWalkingFarmMappingBinding
-import com.steve_md.smartmkulima.ui.fragments.others.LocationProvider
import dagger.hilt.android.AndroidEntryPoint
+import timber.log.Timber
/**
* Aspect of Manual Mapping by walking in the farm
*/
@AndroidEntryPoint
-class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
- private lateinit var binding: FragmentManualWalkingFarmMappingBinding
+class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback {
+ private lateinit var binding: FragmentManualWalkingFarmMappingBinding
private lateinit var googleMap: GoogleMap
- private lateinit var locationProvider: LocationProvider
private lateinit var fusedLocationClient: FusedLocationProviderClient
// List of Pins to be Placed to Create a Polygon
@@ -49,9 +52,12 @@ class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
private var isMappingActive: Boolean = false
private var farmPolygon: Polygon? = null
+ private lateinit var locationManager: LocationManager
+ private lateinit var locationListener: LocationListener
+
companion object {
- private const val LOCATION_PERMISSION_CODE: Int = 1
+ private const val LOCATION_PERMISSION_CODE: Int = 1000
}
override fun onCreateView(
@@ -71,6 +77,8 @@ class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext())
+ //set up location manager
+
binding.apply {
buttonStartMapping.setOnClickListener {
isMappingActive = true
@@ -108,6 +116,15 @@ class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
}
}
+
+ /*
+ private fun getPolygonCorners(startLatLng: LatLng, endLng: LatLng) {
+ val corners = arrayOfNulls(4)
+ corners[0] = computeOffsetOrigin(endLng, 12.0, 16.0) // test dummy values
+ }
+ */
+
+
private fun saveMapppedArea() {
val calculatedFarmSize = SphericalUtil.computeArea(pathPoints) // area in Metres squared
@@ -127,7 +144,7 @@ class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
this.googleMap.mapType = GoogleMap.MAP_TYPE_SATELLITE
- setCriteria()
+ // setCriteria()
// Get current location of the user.
// as it zooms
@@ -155,16 +172,23 @@ class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
)
}
+ /**
+ * Zoom and give the user's
+ * current location on the Map.
+ */
private fun getMyCurrentLocationANDStartManualMapping() {
- locationProvider = LocationProvider(this.requireContext())
-
// Zoom to current location
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
location?.let {
val currentLatLng = LatLng(location.latitude, location.longitude)
- googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 18f)) // Zoom to current location
+ googleMap.moveCamera(
+ CameraUpdateFactory.newLatLngZoom(
+ currentLatLng,
+ 18f
+ )
+ ) // Zoom to current location
}
}
@@ -184,46 +208,72 @@ class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
- return
- }
-
- /**
- * Real time tracking
- */
- val locationRequest = LocationRequest.create().apply {
- interval = 5000
- fastestInterval = 2000
- priority = LocationRequest.PRIORITY_HIGH_ACCURACY
- }
+ requestLocationPermission()
+ } else {
- // GPS to record user movement , track and provide location updates.
- // Start plotting immediately.
- fusedLocationClient.requestLocationUpdates(locationRequest, object : LocationCallback() {
- override fun onLocationResult(locationResult: LocationResult) {
- super.onLocationResult(locationResult)
- for (location in locationResult.locations) {
- val latLng = LatLng(location.latitude, location.longitude)
- pathPoints.add(latLng)
-
- polylineOptions.add(latLng)
-// googleMap.clear()
- googleMap.addPolyline(polylineOptions)
- googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 18f))
- }
+ /**
+ * Real time tracking
+ */
+ val locationRequest = LocationRequest.create().apply {
+ interval = 5000
+ fastestInterval = 2000
+ priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
- }, Looper.getMainLooper())
- } else {
- showMappingNotYetStartedDialog()
+ /**
+ * Geographic Information Systems.
+ */
+
+ // GPS to record user movement , track and provide location updates.
+ // Start plotting immediately.
+ fusedLocationClient.requestLocationUpdates(
+ locationRequest,
+ object : LocationCallback() {
+ override fun onLocationResult(locationResult: LocationResult) {
+ super.onLocationResult(locationResult)
+ for (location in locationResult.locations) {
+ val latLng = LatLng(location.latitude, location.longitude)
+ pathPoints.add(latLng)
+
+ googleMap.addMarker(MarkerOptions().position(latLng))
+
+ polylineOptions.add(latLng)
+ googleMap.addPolyline(polylineOptions)
+
+ googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 18f))
+
+ updatePolygonArea()
+ }
+ }
+ },
+ Looper.getMainLooper()
+ )
+ }
+ } else {
+ showMappingNotYetStartedDialog()
+ }
+ }
+
+
+ private fun updatePolygonArea() {
+ if (pathPoints.size > 2) {
+ val areaInSquareMeters = SphericalUtil.computeArea(pathPoints)
+ val areaInHectares = areaInSquareMeters / 10000
+
+ // Display the area in real time
+ binding.buttonSaveMappedArea.text = "Area: %.2f ha".format(areaInHectares)
}
}
+
/**
* Set map location criteria to follow while setting up
* location updates
*/
+
+ /*
private fun setCriteria() {
// Location criteria
val locationCriteria : Criteria = Criteria()
@@ -237,6 +287,8 @@ class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
locationCriteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH)
}
+ */
+
private fun showMappingNotYetStartedDialog() {
AlertDialog.Builder(requireContext())
.setTitle("Mapping Has Not Started")
@@ -255,6 +307,45 @@ class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
}
+ private fun setupLocationManager() {
+
+ locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE)
+ as LocationManager
+
+ locationListener = LocationListener { location ->
+ // Handle new location
+ val latitude = location.latitude
+ val longitude = location.longitude
+
+ // Update your UI or send location data to a server
+ Timber.d("Current Location: $latitude || $longitude")
+ }
+
+ // Check for the appropriate location provider and request updates
+ if (ActivityCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.ACCESS_FINE_LOCATION
+ ) == PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.ACCESS_COARSE_LOCATION
+ ) == PackageManager.PERMISSION_GRANTED
+ ) {
+
+ locationManager.requestLocationUpdates(
+ LocationManager.GPS_PROVIDER,
+ 5000L, // Time in milliseconds between location updates
+ 10f, // Distance in meters between location updates
+ locationListener
+ )
+
+ // permissions granted proceed with location updates.
+ setupLocationManager()
+
+ } else {
+ requestLocationPermission()
+ setupLocationManager()
+ }
+ }
private fun resetMapping() {
farmPolygon?.remove()
@@ -263,7 +354,7 @@ class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
}
private fun createPolygon() {
- if (pathPoints.size >= 2) {
+ if (pathPoints.size > 0) {
farmPolygon = googleMap.addPolygon(
PolygonOptions()
.addAll(pathPoints)
@@ -278,15 +369,12 @@ class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
// Display the area
binding.buttonSaveMappedArea.text = "Save Mapped Area: %.2f ha".format(areaInHectares)
+ Timber.d("Mapped $areaInHectares ha")
- } else {
+ }
+ else {
binding.buttonSaveMappedArea.text = "Mapped Area: 0.0 ha"
- // Show a message if the user hasn't marked enough points to create a polygon
- AlertDialog.Builder(requireContext())
- .setTitle("Insufficient Path Points")
- .setMessage("Please mark at least three points to create a farm boundary.")
- .setPositiveButton("OK", null)
- .show()
+ Timber.d("Mapped 0.0ha")
}
}
@@ -299,6 +387,8 @@ class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
if (requestCode == LOCATION_PERMISSION_CODE) {
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
getMyCurrentLocationANDStartManualMapping()
+ // permissions granted proceed with location updates.
+ setupLocationManager()
} else {
AlertDialog.Builder(requireContext())
.setTitle("Permission Denied")
@@ -309,6 +399,14 @@ class ManualWalkingFarmMappingFragment : Fragment() ,OnMapReadyCallback{
}
}
+ override fun onPause() {
+ super.onPause()
+ if (::locationManager.isInitialized) {
+ locationManager.removeUpdates(locationListener)
+ }
+ }
+
+
/**
* Lifecycle callbacks.
*/
diff --git a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/MappingFarmLocationWithPinsFragment.kt b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/MappingFarmLocationWithPinsFragment.kt
index 09edfefa..8c11d49a 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/MappingFarmLocationWithPinsFragment.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/MappingFarmLocationWithPinsFragment.kt
@@ -125,8 +125,6 @@ class MappingFarmLocationWithPinsFragment : Fragment() ,OnMapReadyCallback {
// Continue to AddNewFarmFieldFragment
findNavController().navigate(R.id.addNewFarmFieldFragment, bundle)
- findNavController().popBackStack()
-
}
private fun showMappingInProgressDialog() {
@@ -184,7 +182,7 @@ class MappingFarmLocationWithPinsFragment : Fragment() ,OnMapReadyCallback {
)
}
- userLocationLatLng?.let { CameraUpdateFactory.newLatLngZoom(it,15f) }
+ userLocationLatLng?.let { CameraUpdateFactory.newLatLngZoom(it,18f) }
?.let { map.moveCamera(it) }
// Then click on the map and start mapping
@@ -208,7 +206,7 @@ class MappingFarmLocationWithPinsFragment : Fragment() ,OnMapReadyCallback {
private fun updateFarmPolygon() {
farmPolygon?.remove()
- if (boundaryPoints.size >= 3) {
+ if (boundaryPoints.size > 0) {
val polygonOptions = PolygonOptions()
.addAll(boundaryPoints)
.strokeWidth(2f)
diff --git a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/agrodealer/AgroDealerHomeDashboardFragment.kt b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/agrodealer/AgroDealerHomeDashboardFragment.kt
index fc88c13d..72b74780 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/agrodealer/AgroDealerHomeDashboardFragment.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/agrodealer/AgroDealerHomeDashboardFragment.kt
@@ -30,6 +30,7 @@ class AgroDealerHomeDashboardFragment : Fragment() {
private val viewModel: MainViewModel by viewModels()
private lateinit var agrodealerOrdersAdapter : AgrodealerOrdersAdapter
private var ordersList = mutableListOf()
+
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
@@ -101,7 +102,7 @@ class AgroDealerHomeDashboardFragment : Fragment() {
binding.recyclerView5.layoutManager = LinearLayoutManager(requireContext())
// Initialize the adapter
- agrodealerOrdersAdapter = AgrodealerOrdersAdapter(AgrodealerOrdersAdapter.OnClickListener{ order ->
+ agrodealerOrdersAdapter = AgrodealerOrdersAdapter( AgrodealerOrdersAdapter.OnClickListener { order ->
Timber.tag("...CreatedFarmCycles....").e(order.toString())
Timber.i("=====Checking==ORDER WITH ID=====>: ${order.orderId} ")
diff --git a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/MarketProduce.kt b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/buyer/MarketProduce.kt
similarity index 87%
rename from app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/MarketProduce.kt
rename to app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/buyer/MarketProduce.kt
index 89787ce7..aaa1c2ce 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/MarketProduce.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/buyer/MarketProduce.kt
@@ -1,4 +1,4 @@
-package com.steve_md.smartmkulima.ui.fragments.main
+package com.steve_md.smartmkulima.ui.fragments.main.buyer
import android.os.Bundle
import android.text.Editable
@@ -14,6 +14,7 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
+import com.steve_md.smartmkulima.R
import com.steve_md.smartmkulima.adapter.FarmProduceAdapter
import com.steve_md.smartmkulima.databinding.FragmentMarketProduceBinding
import com.steve_md.smartmkulima.model.FarmProduce
@@ -31,7 +32,7 @@ class MarketProduce : Fragment() {
private lateinit var binding: FragmentMarketProduceBinding
private val mainViewModel by viewModels()
- private val farmProduceAdapter by lazy { FarmProduceAdapter() }
+ private lateinit var farmProduceAdapter: FarmProduceAdapter
private val farmProduceList = mutableListOf()
@@ -44,20 +45,33 @@ class MarketProduce : Fragment() {
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+
(activity as AppCompatActivity).supportActionBar?.hide()
subScribeToFarmProduceObserver()
setUpBinding()
- }
- private fun setUpBinding() {
+ farmProduceAdapter =
+ FarmProduceAdapter(FarmProduceAdapter.OnClickListener { farmProduce ->
+ Timber.i("Farm Produce ::Product:: ${farmProduce.productTitle}")
+
+ val bundle = Bundle().apply {
+ putString("productImage", farmProduce.productImageUrl)
+ putString("productTitle", farmProduce.productTitle)
+ putString("productDescription", farmProduce.productPrice)
+ }
+ findNavController().navigate(R.id.marketProduceInDetailsFragment, bundle)
+ })
+ }
+ private fun setUpBinding() {
+
// Filters Search results as you type in the Edit Text
binding.inputSearchFarmProduce.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()) {
@@ -68,7 +82,6 @@ class MarketProduce : Fragment() {
searchingFarmProduce(s.toString())
}
}
-
override fun afterTextChanged(s: Editable?) {
}
diff --git a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/buyer/MarketProduceInDetailsFragment.kt b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/buyer/MarketProduceInDetailsFragment.kt
new file mode 100644
index 00000000..b9969e7e
--- /dev/null
+++ b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/buyer/MarketProduceInDetailsFragment.kt
@@ -0,0 +1,95 @@
+package com.steve_md.smartmkulima.ui.fragments.main.buyer
+
+import android.annotation.SuppressLint
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.provider.Settings
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.bumptech.glide.Glide
+import com.steve_md.smartmkulima.databinding.FragmentMarketProduceInDetailsBinding
+import com.steve_md.smartmkulima.utils.OverlayService
+import com.steve_md.smartmkulima.utils.displaySnackBar
+import com.steve_md.smartmkulima.utils.hideSupportActionBar
+import dagger.hilt.android.AndroidEntryPoint
+
+@AndroidEntryPoint
+class MarketProduceInDetailsFragment : Fragment() {
+ private lateinit var binding: FragmentMarketProduceInDetailsBinding
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentMarketProduceInDetailsBinding.inflate(
+ inflater, container, false
+ )
+ return binding.root
+ }
+
+ @SuppressLint("SetTextI18n")
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ hideSupportActionBar()
+
+ Glide.with(binding.imageView32)
+ .load(arguments?.getString("productImage"))
+ .centerCrop()
+ .into(binding.imageView32)
+ binding.textView175.text = arguments?.getString("productTitle")
+ binding.textView176.text = ""+arguments?.getString("productDescription")
+
+ binding.addToCart.setOnClickListener {
+ // check permission for overlay over other apps.
+ checkOverlayPermission()
+ }
+ }
+
+ private fun checkOverlayPermission() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (!Settings.canDrawOverlays(requireContext())) {
+ // Permission is not granted, request it
+ val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:${requireContext().packageName}"))
+
+ startActivityForResult(intent, REQUEST_CODE_OVERLAY_PERMISSION)
+ } else {
+ // Permission is granted, show the overlay
+ showOverLay()
+ }
+ } else {
+ // For devices below API 23, permission is granted by default
+ showOverLay()
+ }
+ }
+
+ private fun showOverLay() {
+ val intent = Intent(requireContext(), OverlayService::class.java)
+ requireContext().startService(intent)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (requestCode == REQUEST_CODE_OVERLAY_PERMISSION) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (Settings.canDrawOverlays(requireContext())) {
+ // Permission is granted
+ showOverLay()
+
+ displaySnackBar("Permitted to overlay over other apps")
+ } else {
+ displaySnackBar("No permission to overlay over other apps")
+ }
+ }
+ }
+ }
+
+
+
+ companion object {
+ const val REQUEST_CODE_OVERLAY_PERMISSION = 1
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/fieldagents/AddANewAgroDealerBottomSheetFragment.kt b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/fieldagents/AddANewAgroDealerBottomSheetFragment.kt
index 95e419ef..a3aa4d11 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/fieldagents/AddANewAgroDealerBottomSheetFragment.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/fieldagents/AddANewAgroDealerBottomSheetFragment.kt
@@ -34,10 +34,6 @@ class AddANewAgroDealerBottomSheetFragment : BottomSheetDialogFragment() {
private lateinit var binding: FragmentAddANewAgroDealerBottomsheetBinding
private lateinit var fusedLocationClient: FusedLocationProviderClient
private val viewModel: MainViewModel by viewModels()
- private var fieldAgentEarning: FieldAgentEarnings? = null
- private val agentId: Long = 1 // By Default say agent ID is 1
- private val pointsPerFarmer = 10
- private val pointsToKSHRate = 200.0
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
@@ -52,6 +48,8 @@ class AddANewAgroDealerBottomSheetFragment : BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+ Timber.tag("-on View Created - ShowAddAgrodealerBottomSheet 2").d("Received arg is: ${arguments?.getString("fieldAgentEmail")}")
+
fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity())
binding.inputAgroDealerLocation.setOnFocusChangeListener { _, hasFocus ->
@@ -64,45 +62,23 @@ class AddANewAgroDealerBottomSheetFragment : BottomSheetDialogFragment() {
}
}
-
-
binding.addAgroDealerByFieldAgentBtn.setOnClickListener {
- if (inputsAreValidated()) {
+ if (inputsAreValidated()) {
val fieldAgentAddAgroDealerData = FieldAgentAddAgroDealerData(
- name = binding.inputAgroDealerName.text.toString(),
- email = binding.inputAgroDealerEmail.text.toString(),
- phone = binding.inputAgroDealerPhone.text.toString(),
- location = binding.inputAgroDealerLocation.text.toString(),
- physicalLocationAddress = binding.inputAgroDealerPhysicalAddress.text.toString()
- )
+ name = binding.inputAgroDealerName.text.toString(),
+ email = binding.inputAgroDealerEmail.text.toString(),
+ phone = binding.inputAgroDealerPhone.text.toString(),
+ location = binding.inputAgroDealerLocation.text.toString(),
+ physicalLocationAddress = binding.inputAgroDealerPhysicalAddress.text.toString(),
+ offers = binding.spinnerSelectOfferCategories.selectedItem.toString(),
+ agentId = "${arguments?.getString("fieldAgentEmail")}"
+ )
+
try {
viewModel.fieldAgentAddANewAgroDealer(fieldAgentAddAgroDealerData)
- viewModel.allFieldAgentEarnings.observe(viewLifecycleOwner) {
- if (it.earnings == 200.0 && it.points == 10) {
-
- val newPoints = it.points + pointsPerFarmer
-
- val newEarnings = calculateEarnings(newPoints)
-
- viewModel.updateFieldAgentEarnings(
- newPoints, newEarnings
- )
- } else {
- viewModel.saveFieldAgentEarnings(
- FieldAgentEarnings(
- 1, 10, 200.0
- )
- )
- }
- }
-
-
-
-
-
requireActivity().runOnUiThread {
displaySnackBar("A new Agro-dealer was added.")
}
@@ -117,28 +93,6 @@ class AddANewAgroDealerBottomSheetFragment : BottomSheetDialogFragment() {
}
- updateFieldAgentEarnings()
- }
-
- private fun updateFieldAgentEarnings() {
- lifecycleScope.launch {
- fieldAgentEarning?.let {
- val newPoints = it.points + pointsPerFarmer
- val newEarnings = calculateEarnings(newPoints)
-
- // Update earnings and points in room db
- viewModel.updateFieldAgentEarnings(
- newPoints, newEarnings
- )
-
- toast("Farmer added! You've earned 10 points. Yaaay!")
- }
- }
- }
-
-
- private fun calculateEarnings(points: Int): Double {
- return points * (pointsToKSHRate / pointsPerFarmer)
}
private fun getCurrentLocation(onLocationReceived: (Location) -> Unit) {
@@ -186,8 +140,10 @@ class AddANewAgroDealerBottomSheetFragment : BottomSheetDialogFragment() {
}
}
-
companion object {
const val LOCATION_PERMISSION_REQUEST_CODE = 1000
+ const val TAG = "AddNewAgroDealerBottomSheeet"
}
+
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/fieldagents/FieldAgentDashboardFragment.kt b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/fieldagents/FieldAgentDashboardFragment.kt
index 3e2bbbd3..6a710e48 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/fieldagents/FieldAgentDashboardFragment.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/main/fieldagents/FieldAgentDashboardFragment.kt
@@ -3,6 +3,8 @@ package com.steve_md.smartmkulima.ui.fragments.main.fieldagents
import android.graphics.drawable.GradientDrawable.Orientation
import android.icu.lang.UCharacter.VerticalOrientation
import android.os.Bundle
+import android.text.Editable
+import android.text.TextWatcher
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
@@ -35,6 +37,7 @@ import com.steve_md.smartmkulima.viewmodel.MainViewModel
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
+import timber.log.Timber
import java.util.Calendar
@AndroidEntryPoint
@@ -97,6 +100,10 @@ class FieldAgentDashboardFragment : Fragment() {
setUpRecyclerView()
fetchAllFieldAgentCreatedAgroDealers()
+
+ viewModel.getAgentPoints("${arguments?.getString("fieldAgentEmail")}")
+
+ subscribeToFieldAgentEarningVMObservables()
}
@@ -123,13 +130,14 @@ class FieldAgentDashboardFragment : Fragment() {
private fun setUpUi() {
- subscribeToFieldAgentEarningVMObservables()
-
binding.apply {
+ val agentEmail = arguments?.getString("fieldAgentEmail")
button4.setOnClickListener {
- showAddANewAgroDealerBottomSheetFragment()
+ if (agentEmail != null) {
+ showAddANewAgroDealerBottomSheetFragment(agentEmail)
+ }
}
button3.setOnClickListener {
@@ -137,11 +145,35 @@ class FieldAgentDashboardFragment : Fragment() {
progressBar7.isVisible = true
delay(500L)
progressBar7.isVisible = false
+ // Load agent points initially
+ viewModel.getAgentPoints("${arguments?.getString("fieldAgentEmail")}")
}
}
}
+
+ binding.inputSearchAgrodealer.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()) {
+ binding.noRecordsAgrodealers.isVisible = false
+ fieldAgentAddedAgroDealersAdapter.submitList(fieldAgentAgroDealers)
+ binding.recyclerViewAddedAgrodealers.isVisible = true // when no search rlts
+ } else {
+ searchingAgroDealer(s.toString())
+ }
+ }
+
+ override fun afterTextChanged(s: Editable?) {
+
+ }
+ })
+
binding.inputSearchAgrodealer.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
@@ -172,20 +204,48 @@ class FieldAgentDashboardFragment : Fragment() {
}
private fun subscribeToFieldAgentEarningVMObservables() {
- viewModel.allFieldAgentEarnings.observe(viewLifecycleOwner) {
+ viewModel.agentPoints.observe(viewLifecycleOwner) {
it?.let {
binding.textViewEarnings.text = "Current Earnings: ${it.points} points worth KSH. ${it.earnings}"
}
}
}
- private fun showAddANewAgroDealerBottomSheetFragment() {
- val modal = AddANewAgroDealerBottomSheetFragment()
- modal.show(parentFragmentManager, TAG)
+ private fun showAddANewAgroDealerBottomSheetFragment(fieldAgentEmail: String) {
+ // pass here field agent ID here as an arg who registered / added this new farmer
+
+// val bottomSheet = AddANewAgroDealerBottomSheetFragment.newInstance(agentEmail)
+// bottomSheet.show(parentFragmentManager, bottomSheet.tag)
+
+ val modal = AddANewAgroDealerBottomSheetFragment().apply {
+ arguments = Bundle().apply {
+ putString("fieldAgentEmail", fieldAgentEmail)
+ }
+ }
+ // modal.show(parentFragmentManager, TAG)
+ parentFragmentManager.let {
+ modal.show(it, AddANewAgroDealerBottomSheetFragment.TAG)
+ }
+
+ Timber.tag("ShowAddAgrodealerBottomSheet").d("Passed arg is: ${arguments?.getString("fieldAgentEmail")}")
+
+// val fragment = AddANewAgroDealerBottomSheetFragment()
+// val bundle = Bundle().apply {
+// putString("agentEmail","${arguments?.getString("fieldAgentEmail")}")
+// }
+// fragment.arguments = bundle
+// fragment.show(parentFragmentManager, fragment.tag)
+
}
+
+
private fun searchingAgroDealer(searchText: String) {
- val filteredList = fieldAgentAgroDealers.filter { it.name.equals(searchText, ignoreCase = true) }
+ val filteredList = fieldAgentAgroDealers.filter {
+ it.name.contains(searchText, ignoreCase = true)
+ }
fieldAgentAddedAgroDealersAdapter.submitList(filteredList.toMutableList())
+
+ binding.noRecordsAgrodealers.isVisible = filteredList.isEmpty()
}
private fun exitDialog() {
@@ -214,9 +274,25 @@ class FieldAgentDashboardFragment : Fragment() {
}
override fun onResume() {
super.onResume()
+
+ viewModel.getAgentPoints("${arguments?.getString("fieldAgentEmail")}")
+
displaySnackBar("Yaaay! Onboard more Agro-Dealers to increase your earnings")
}
companion object {
const val TAG = "AddANewAgroDealerBottomSheetFragment"
+
+
+ private const val ARG_AGENT_EMAIL = "agentEmail"
+
+ // Create new instance of BottomSheet with argument
+ fun newInstance(agentEmail: String): AddANewAgroDealerBottomSheetFragment {
+ val fragment = AddANewAgroDealerBottomSheetFragment()
+ val args = Bundle().apply {
+ putString(ARG_AGENT_EMAIL, agentEmail)
+ }
+ fragment.arguments = args
+ return fragment
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/others/LocationProvider.kt b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/others/LocationProvider.kt
index 728acfdd..dcdd22d7 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/others/LocationProvider.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/ui/fragments/others/LocationProvider.kt
@@ -30,7 +30,7 @@ class LocationProvider(private val context:Context) {
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
- // promptUserRequestingPermissions()
+ promptUserRequestingPermissions()
return
}
diff --git a/app/src/main/java/com/steve_md/smartmkulima/utils/ExtensionFunctions.kt b/app/src/main/java/com/steve_md/smartmkulima/utils/ExtensionFunctions.kt
index f6c1252d..8572650f 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/utils/ExtensionFunctions.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/utils/ExtensionFunctions.kt
@@ -2,16 +2,19 @@ package com.steve_md.smartmkulima.utils
import android.app.Activity
import android.content.Context
+import android.content.Intent
import android.graphics.Color
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
+import android.provider.Settings
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
+import androidx.core.app.ActivityCompat.startActivityForResult
import androidx.core.view.updateMargins
import androidx.fragment.app.Fragment
import com.google.android.material.snackbar.Snackbar
@@ -21,6 +24,8 @@ import okhttp3.ResponseBody
import org.json.JSONException
import org.json.JSONObject
import retrofit2.HttpException
+import android.net.Uri
+
fun Fragment.toast(text:String) {
@@ -187,3 +192,5 @@ fun formatNameFromEmail(email: String): String {
+
+
diff --git a/app/src/main/java/com/steve_md/smartmkulima/utils/OverLayService.kt b/app/src/main/java/com/steve_md/smartmkulima/utils/OverLayService.kt
new file mode 100644
index 00000000..88c5b634
--- /dev/null
+++ b/app/src/main/java/com/steve_md/smartmkulima/utils/OverLayService.kt
@@ -0,0 +1,63 @@
+package com.steve_md.smartmkulima.utils
+
+
+import android.app.Service
+import android.content.Intent
+import android.graphics.PixelFormat
+import android.os.Build
+import android.os.IBinder
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.view.WindowManager
+import androidx.annotation.RequiresApi
+import com.steve_md.smartmkulima.R
+
+class OverlayService : Service() {
+
+ private lateinit var windowManager: WindowManager
+ private lateinit var overlayView: View
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ override fun onCreate() {
+ super.onCreate()
+
+ // Inflate your overlay layout
+ windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
+ overlayView = LayoutInflater.from(this).inflate(R.layout.overlay_layout, null)
+
+ val params = WindowManager.LayoutParams(
+ WindowManager.LayoutParams.WRAP_CONTENT,
+ WindowManager.LayoutParams.WRAP_CONTENT,
+ WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, // Use TYPE_PHONE for older versions
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ PixelFormat.TRANSLUCENT
+ )
+
+ // Specify the overlay position on the screen
+ params.gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
+ params.x = 0
+ params.y = 100
+
+ // Add the view to the window
+ windowManager.addView(overlayView, params)
+
+ // Set up click listeners for the overlay
+ overlayView.setOnClickListener {
+ // Handle clicks on the overlay
+ stopSelf() // This will remove the overlay
+ }
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ // Remove the overlay view
+ if (::overlayView.isInitialized) {
+ windowManager.removeView(overlayView)
+ }
+ }
+}
diff --git a/app/src/main/java/com/steve_md/smartmkulima/utils/services/LocationPermissionHelper.kt b/app/src/main/java/com/steve_md/smartmkulima/utils/services/LocationPermissionHelper.kt
new file mode 100644
index 00000000..2874d3bc
--- /dev/null
+++ b/app/src/main/java/com/steve_md/smartmkulima/utils/services/LocationPermissionHelper.kt
@@ -0,0 +1,41 @@
+package com.steve_md.smartmkulima.utils.services
+
+import android.Manifest
+import android.app.Activity
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.provider.Settings
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+
+
+/**
+ * Handling Location runtime permissions in Android | Kotlin.
+ */
+object LocationPermissionHelper {
+ private val BASIC_PERMISSION = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
+ private const val BASIC_PERMISSION_REQUESTCODE = 0
+
+ fun hasAccessFinePermission(activity: Activity): Boolean {
+ return ContextCompat.checkSelfPermission(
+ activity,
+ Manifest.permission.ACCESS_FINE_LOCATION
+ ) == PackageManager.PERMISSION_GRANTED
+ }
+
+ fun requestFineLocationPermission(activity: Activity?) {
+ ActivityCompat.requestPermissions(activity!!, BASIC_PERMISSION, BASIC_PERMISSION_REQUESTCODE)
+ }
+
+ fun shouldShowRequestPermissionRationale(activity: Activity): Boolean{
+ return ActivityCompat.shouldShowRequestPermissionRationale(activity, BASIC_PERMISSION.get(0))
+ }
+ fun launchPermissionSettings(activity: Activity) {
+ val intent = Intent()
+ intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
+ intent.data = Uri.fromParts("package", activity.packageName, null)
+ activity.startActivity(intent)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/steve_md/smartmkulima/viewmodel/MainViewModel.kt b/app/src/main/java/com/steve_md/smartmkulima/viewmodel/MainViewModel.kt
index 65168d31..706015ce 100644
--- a/app/src/main/java/com/steve_md/smartmkulima/viewmodel/MainViewModel.kt
+++ b/app/src/main/java/com/steve_md/smartmkulima/viewmodel/MainViewModel.kt
@@ -482,19 +482,18 @@ class MainViewModel @Inject constructor(
// FIELD AGENT EARNINGS
- fun updateFieldAgentEarnings(newPoints: Int, newEarnings: Double) = viewModelScope.launch {
- repository.updateFieldAgentEarnings(newPoints, newEarnings)
- }
+ private val _agentPoints = MutableLiveData()
+ val agentPoints: LiveData get() = _agentPoints
- fun saveFieldAgentEarnings(fieldAgentEarnings: FieldAgentEarnings) = viewModelScope.launch {
- withContext(Dispatchers.IO) {
- repository.saveEarnings(fieldAgentEarnings)
+ fun getAgentPoints(agentId: String) {
+ viewModelScope.launch {
+ val points = repository.getAgentPoints(agentId)
+ points?.let {
+ _agentPoints.postValue(it)
+ }
}
}
- val allFieldAgentEarnings: LiveData =
- repository.getAllFieldAgentEarnings()
-
// Field Agents account register and log in by finding if exists in backend
private var _fieldAgentRegisterState = MutableStateFlow?>(null)
diff --git a/app/src/main/res/layout/fragment_add_a_new_agro_dealer_bottomsheet.xml b/app/src/main/res/layout/fragment_add_a_new_agro_dealer_bottomsheet.xml
index ff9b110f..6c428f39 100644
--- a/app/src/main/res/layout/fragment_add_a_new_agro_dealer_bottomsheet.xml
+++ b/app/src/main/res/layout/fragment_add_a_new_agro_dealer_bottomsheet.xml
@@ -178,12 +178,25 @@
android:inputType="text|number" />
+
+
+ app:layout_constraintTop_toBottomOf="@+id/spinnerSelectOfferCategories" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_market_produce.xml b/app/src/main/res/layout/fragment_market_produce.xml
index 66d3cf00..4d9f18a1 100644
--- a/app/src/main/res/layout/fragment_market_produce.xml
+++ b/app/src/main/res/layout/fragment_market_produce.xml
@@ -8,7 +8,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bg_gray"
- tools:context=".ui.fragments.main.MarketProduce">
+ tools:context=".ui.fragments.main.buyer.MarketProduce">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/overlay_layout.xml b/app/src/main/res/layout/overlay_layout.xml
new file mode 100644
index 00000000..705dadb7
--- /dev/null
+++ b/app/src/main/res/layout/overlay_layout.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/products_row.xml b/app/src/main/res/layout/products_row.xml
index 6b74e313..898b7392 100644
--- a/app/src/main/res/layout/products_row.xml
+++ b/app/src/main/res/layout/products_row.xml
@@ -1,8 +1,6 @@
-
-
-
+ tools:layout="@layout/fragment_market_produce" >
+
+
+
\ 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 03686358..8db53f84 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -47,6 +47,7 @@
Shop Now
loading_status_update
location
+ farmProduceDetails
- Crop Cycle
@@ -194,6 +195,16 @@
- Uasin Gishu
+
+ - Fertilizers
+ - Agrochemicals
+ - Farm machinery
+ - Land leasing
+ - Agricultural loans
+ - Farm inputs
+ - Veterinary services
+
+
- Seedling Acquisition
- Potting