aboutsummaryrefslogtreecommitdiff
path: root/androidApp/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'androidApp/src/main')
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt4
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt32
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt142
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesAdapter.kt2
-rw-r--r--androidApp/src/main/res/layout/unit_details_reports.xml57
-rw-r--r--androidApp/src/main/res/values/strings.xml5
6 files changed, 228 insertions, 14 deletions
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
index f46a5c9..16cad74 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
@@ -3,11 +3,13 @@ package mx.trackermap.TrackerMap.android
import android.app.Application
import mx.trackermap.TrackerMap.android.details.commands.UnitCommandsViewModel
import mx.trackermap.TrackerMap.android.details.information.UnitInformationViewModel
+import mx.trackermap.TrackerMap.android.details.reports.UnitReportsViewModel
import mx.trackermap.TrackerMap.android.session.LoginViewModel
import mx.trackermap.TrackerMap.android.units.UnitsViewModel
import mx.trackermap.TrackerMap.client.apis.CommandsApi
import mx.trackermap.TrackerMap.client.apis.DevicesApi
import mx.trackermap.TrackerMap.client.apis.PositionsApi
+import mx.trackermap.TrackerMap.client.apis.ReportsApi
import mx.trackermap.TrackerMap.client.apis.SessionApi
import mx.trackermap.TrackerMap.controllers.UnitsController
import org.koin.android.ext.koin.androidContext
@@ -28,6 +30,7 @@ class TrackerApp : Application() {
single { DevicesApi(get()) }
single { PositionsApi(get()) }
single { CommandsApi(get()) }
+ single { ReportsApi(get()) }
single { UnitsController(get(), get()) }
@@ -35,6 +38,7 @@ class TrackerApp : Application() {
viewModel { UnitInformationViewModel(get()) }
viewModel { UnitCommandsViewModel(get()) }
single { UnitsViewModel(get()) }
+ viewModel { UnitReportsViewModel(get(), get()) }
}
startKoin {
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt
index a2faec8..dfc0493 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt
@@ -1,17 +1,22 @@
package mx.trackermap.TrackerMap.android.details.reports
import android.os.Bundle
+import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import mx.trackermap.TrackerMap.android.databinding.UnitDetailsReportsBinding
import mx.trackermap.TrackerMap.android.details.UnitDetailsAdapter
+import org.koin.androidx.viewmodel.ext.android.viewModel
+
+class UnitReportsFragment : Fragment() {
-class UnitReportsFragment: Fragment() {
private var _binding: UnitDetailsReportsBinding? = null
private val binding get() = _binding!!
+ private val unitReportsViewModel: UnitReportsViewModel by viewModel()
+
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -23,12 +28,33 @@ class UnitReportsFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- val id = arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG)
- binding.unitReportsText.text = "COMMANDS for ID - $id"
+
+ unitReportsViewModel.deviceId.value =
+ arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG) ?: 0
+ setupEvents()
+ setupObservers()
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
+
+ private fun setupEvents() {
+ binding.reportType.setOnPositionChangedListener { position ->
+ unitReportsViewModel.reportType.value = when (position) {
+ 0 -> UnitReportsViewModel.ReportType.POSITIONS
+ 1 -> UnitReportsViewModel.ReportType.EVENTS
+ else -> UnitReportsViewModel.ReportType.STOPS
+ }
+ }
+ unitReportsViewModel.reportPeriod.value = UnitReportsViewModel.ReportPeriod.DAY
+ unitReportsViewModel.reportType.value = UnitReportsViewModel.ReportType.POSITIONS
+ }
+
+ private fun setupObservers() {
+ unitReportsViewModel.report.observe(this) { report ->
+ Log.d("UnitReportsFragment", "Report available: $report")
+ }
+ }
} \ No newline at end of file
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt
new file mode 100644
index 0000000..808bdda
--- /dev/null
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt
@@ -0,0 +1,142 @@
+package mx.trackermap.TrackerMap.android.details.reports
+
+import android.util.Log
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.SavedStateHandle
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.asFlow
+import androidx.lifecycle.viewModelScope
+import java.text.SimpleDateFormat
+import java.util.Calendar
+import java.util.Date
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
+import mx.trackermap.TrackerMap.client.apis.ReportsApi
+import mx.trackermap.TrackerMap.client.models.Event
+import mx.trackermap.TrackerMap.client.models.Position
+import mx.trackermap.TrackerMap.client.models.Stop
+import org.koin.core.component.KoinComponent
+
+class UnitReportsViewModel(
+ private val reportsApi: ReportsApi,
+ savedStateHandle: SavedStateHandle
+) : ViewModel(), KoinComponent {
+
+ sealed class Report {
+ class PositionsReport(positions: Array<Position>) : Report()
+ class EventsReport(events: Array<Event>) : Report()
+ class StopsReport(stops: Array<Stop>) : Report()
+ }
+
+ enum class ReportType {
+ POSITIONS, EVENTS, STOPS
+ }
+
+ enum class ReportPeriod {
+ DAY, WEEK, MONTH
+ }
+
+ var deviceId = savedStateHandle.getLiveData("deviceId", 0)
+ val reportType: MutableLiveData<ReportType> = savedStateHandle.getLiveData("reportType", null)
+ val reportPeriod: MutableLiveData<ReportPeriod> =
+ savedStateHandle.getLiveData("reportPeriod", null)
+ val report: MutableLiveData<Report> = MutableLiveData()
+
+ val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
+
+ init {
+ viewModelScope.launch {
+ setupTypeObserver()
+ }
+ viewModelScope.launch {
+ setupPeriodObserver()
+ }
+ }
+
+ private suspend fun setupTypeObserver() {
+ reportType.asFlow().collect {
+ fetchReport()
+ }
+ }
+
+ private suspend fun setupPeriodObserver() {
+ reportPeriod.asFlow().collect {
+ fetchReport()
+ }
+ }
+
+ private fun fetchReport() {
+ if (reportType.value == null || reportPeriod.value == null) {
+ return
+ }
+
+ val (currentDate, previousDate) = getDates()
+ Log.d("UnitReportsVM", "Current report type: ${reportType.value.toString()}")
+ Log.d("UnitReportsVM", "Current report period: ${reportPeriod.value.toString()}")
+ Log.d("UnitReportsVM", "Current date:${dateFormat.format(currentDate)}")
+ Log.d("UnitReportsVM", "Previous date:${dateFormat.format(previousDate)}")
+
+ viewModelScope.launch {
+ when (reportType.value!!) {
+ ReportType.POSITIONS -> fetchPositions(previousDate, currentDate)
+ ReportType.EVENTS -> fetchEvents(previousDate, currentDate)
+ ReportType.STOPS -> fetchStops(previousDate, currentDate)
+ }
+ }
+ }
+
+ private fun getDates(): Pair<Date, Date> {
+ val calendar = Calendar.getInstance()
+ val currentDate = calendar.time
+
+ calendar.add(
+ Calendar.DATE, when (reportPeriod.value!!) {
+ ReportPeriod.DAY -> -1
+ ReportPeriod.WEEK -> -7
+ ReportPeriod.MONTH -> -30
+ }
+ )
+ val previousDate = calendar.time
+
+ return Pair(currentDate, previousDate)
+ }
+
+ private suspend fun fetchPositions(from: Date, to: Date) {
+ Log.d("UnitReportsVM", "Fetching positions")
+
+ val result = reportsApi.reportsRouteGet(
+ dateFormat.format(from),
+ dateFormat.format(to),
+ deviceId.value!!
+ )
+
+ Log.d("UnitReportsVM", "Positions report: $result")
+ report.postValue(Report.PositionsReport(result))
+ }
+
+ private suspend fun fetchEvents(from: Date, to: Date) {
+ Log.d("UnitReportsVM", "Fetching events")
+
+ val result = reportsApi.reportsEventsGet(
+ dateFormat.format(from),
+ dateFormat.format(to),
+ deviceId.value!!
+ )
+
+ Log.d("UnitReportsVM", "Events report: $result")
+ report.postValue(Report.EventsReport(result))
+ }
+
+ private suspend fun fetchStops(from: Date, to: Date) {
+ Log.d("UnitReportsVM", "Fetching stops")
+
+ val result = reportsApi.reportsStopsGet(
+ dateFormat.format(from),
+ dateFormat.format(to),
+ deviceId.value!!
+ )
+
+ Log.d("UnitReportsVM", "Stops report: $result")
+ report.postValue(Report.StopsReport(result))
+ }
+} \ No newline at end of file
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesAdapter.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesAdapter.kt
index 4852757..6a01e33 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesAdapter.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesAdapter.kt
@@ -73,7 +73,7 @@ class DevicesAdapter(
driverName.text = unit.device.contact
unitSpeed.text = context.getString(R.string.unit_speed_format, unit.position?.speed?.toInt() ?: 0)
lastAddress.text = unit.position?.address
- lastDate.text = "yyyy/mm/dd, hh:mm"
+ lastDate.text = unit.position?.deviceTime
actionCallback?.let { callback ->
detailsButton.setOnClickListener { callback(unit, Action.DETAILS) }
reportsButton.setOnClickListener { callback(unit, Action.REPORTS) }
diff --git a/androidApp/src/main/res/layout/unit_details_reports.xml b/androidApp/src/main/res/layout/unit_details_reports.xml
index f1b52e3..f064a3f 100644
--- a/androidApp/src/main/res/layout/unit_details_reports.xml
+++ b/androidApp/src/main/res/layout/unit_details_reports.xml
@@ -1,19 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools">
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
- <TextView
- android:id="@+id/unitReportsText"
- android:layout_width="wrap_content"
+ <com.addisonelliott.segmentedbutton.SegmentedButtonGroup
+ android:id="@+id/reportType"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
+ android:layout_margin="@dimen/margin"
+ app:borderWidth="1dp"
+ app:dividerPadding="10dp"
+ app:dividerWidth="1dp"
app:layout_constraintBottom_toBottomOf="parent"
- tools:text="REPORTS"/>
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:position="0"
+ app:radius="30dp"
+ app:ripple="true"
+ app:selectedBackground="@color/colorPrimary">
+
+ <com.addisonelliott.segmentedbutton.SegmentedButton
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:padding="10dp"
+ app:drawableGravity="top"
+ app:selectedTextColor="@color/darkBackground"
+ app:text="@string/positions"
+ app:textColor="@color/colorPrimaryDark" />
+
+ <com.addisonelliott.segmentedbutton.SegmentedButton
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:padding="10dp"
+ app:drawableGravity="top"
+ app:selectedTextColor="@color/darkBackground"
+ app:text="@string/events"
+ app:textColor="@color/colorPrimaryDark" />
+
+ <com.addisonelliott.segmentedbutton.SegmentedButton
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:padding="10dp"
+ app:drawableGravity="top"
+ app:selectedTextColor="@color/darkBackground"
+ app:text="@string/stops"
+ app:textColor="@color/colorPrimaryDark" />
+
+ </com.addisonelliott.segmentedbutton.SegmentedButtonGroup>
</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file
diff --git a/androidApp/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml
index 7478ddb..ca9ff5e 100644
--- a/androidApp/src/main/res/values/strings.xml
+++ b/androidApp/src/main/res/values/strings.xml
@@ -23,7 +23,12 @@
<string name="unit_reports">Reports</string>
<string name="unit_commands">Commands</string>
<string name="units_search">Type to search</string>
+
<string name="key">Key</string>
<string name="value">Value</string>
<string name="send_command">Send Command</string>
+
+ <string name="positions">Positions</string>
+ <string name="events">Events</string>
+ <string name="stops">Stops</string>
</resources> \ No newline at end of file