From 546738888395565ac2d5fe2cfb941ecdd0c1df45 Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Mon, 11 Apr 2022 00:55:26 -0500 Subject: - [shared] Added DateUtils 'expect' class for platform-specific date format. - [android] Redesigned reports view, now supports custom reports! - [ios] Not rewritten yet, it won't build! --- .../android/details/reports/UnitReportsFragment.kt | 116 +++++++++++++++++++-- 1 file changed, 108 insertions(+), 8 deletions(-) (limited to 'androidApp/src/main/java') 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 091cb7b..03a4220 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 @@ -18,6 +18,8 @@ package mx.trackermap.TrackerMap.android.details.reports import android.app.Activity +import android.app.DatePickerDialog +import android.app.TimePickerDialog import android.content.Intent import android.os.Build import android.os.Bundle @@ -27,14 +29,16 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.PopupMenu -import android.widget.TableRow -import android.widget.TextView +import android.widget.* import androidx.activity.result.contract.ActivityResultContracts import androidx.core.view.setMargins import androidx.fragment.app.Fragment import androidx.fragment.app.commit +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.card.MaterialCardView +import io.ktor.utils.io.* import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.datetime.LocalDateTime import mx.trackermap.TrackerMap.android.R import mx.trackermap.TrackerMap.android.databinding.UnitDetailsReportsBinding import mx.trackermap.TrackerMap.android.details.UnitDetailsAdapter @@ -47,6 +51,7 @@ import mx.trackermap.TrackerMap.utils.Formatter import mx.trackermap.TrackerMap.utils.ReportDates import org.koin.androidx.viewmodel.ext.android.viewModel import java.io.* +import java.util.* import kotlin.math.max import kotlin.time.ExperimentalTime @@ -59,12 +64,22 @@ class UnitReportsFragment : Fragment() { private val unitReportsViewModel: UnitReportsViewModel by viewModel() private lateinit var mapFragment: MapWrapperFragment + private lateinit var bottomSheetBehavior: BottomSheetBehavior private var reportFile: ReportController.Report.XlsxReport? = null private var exportAction: UnitReportsViewModel.ExportAction? = null + private lateinit var fromPickedDatetime: LocalDateTime + private lateinit var fromDatePicker: DatePickerDialog + private lateinit var fromTimePicker: TimePickerDialog + + private lateinit var toPickedDatetime: LocalDateTime + private lateinit var toDatePicker: DatePickerDialog + private lateinit var toTimePicker: TimePickerDialog + private companion object { - const val XLSX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + const val XLSX_MIME_TYPE = + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" } override fun onCreateView( @@ -80,7 +95,12 @@ class UnitReportsFragment : Fragment() { super.onViewCreated(view, savedInstanceState) unitReportsViewModel.setDeviceId( - arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG) ?: 0) + arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG) ?: 0 + ) + + bottomSheetBehavior = BottomSheetBehavior.from(binding.bottomSheet) + bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED + setupEvents() initializeMap() } @@ -129,6 +149,12 @@ class UnitReportsFragment : Fragment() { binding.periodButton.setOnClickListener { showPeriodPopUp(it) } + binding.fromEditText.setOnClickListener { + fromDatePicker.show() + } + binding.toEditText.setOnClickListener { + toDatePicker.show() + } binding.exportButton.setOnClickListener { exportAction = UnitReportsViewModel.ExportAction.ACTION_SAVE unitReportsViewModel.fetchReportXlsx() @@ -137,6 +163,26 @@ class UnitReportsFragment : Fragment() { exportAction = UnitReportsViewModel.ExportAction.ACTION_SHARE unitReportsViewModel.fetchReportXlsx() } + binding.toggleSheet.setOnClickListener { + if (bottomSheetBehavior.state == BottomSheetBehavior.STATE_EXPANDED) { + bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED + } else { + bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED + } + } + bottomSheetBehavior.addBottomSheetCallback(object: BottomSheetBehavior.BottomSheetCallback() { + override fun onStateChanged(bottomSheet: View, newState: Int) { + if (newState == BottomSheetBehavior.STATE_EXPANDED) { + binding.toggleSheet.setImageResource(R.drawable.icon_down) + binding.toggleSheet.contentDescription = getString(R.string.shared_slide_down) + } else { + binding.toggleSheet.setImageResource(R.drawable.icon_up) + binding.toggleSheet.contentDescription = getString(R.string.shared_slide_up) + } + } + + override fun onSlide(bottomSheet: View, slideOffset: Float) {} + }) unitReportsViewModel.setReportPeriod(ReportDates.ReportPeriod.Today()) unitReportsViewModel.setReportType(ReportController.ReportType.POSITIONS) } @@ -149,7 +195,11 @@ class UnitReportsFragment : Fragment() { when (report) { is ReportController.Report.PositionsReport -> { mapFragment.display(unitReportsViewModel.geofences.value!!) - mapFragment.display(report.positions.toTypedArray(), isReport = true, center = true) + mapFragment.display( + report.positions.toTypedArray(), + isReport = true, + center = true + ) showMap(true) } is ReportController.Report.EventsReport -> { @@ -191,6 +241,55 @@ class UnitReportsFragment : Fragment() { is ReportDates.ReportPeriod.Custom -> R.string.period_custom } ) + + binding.rangeLayout.visibility = + if (period is ReportDates.ReportPeriod.Custom) View.VISIBLE else View.GONE + + (period as? ReportDates.ReportPeriod.Custom)?.let { + val (from, to) = it.getStringDates() + binding.fromEditText.setText(Formatter.formatDate(from)) + binding.toEditText.setText(Formatter.formatDate(to)) + } + + /** + * Initialize date and time pickers + */ + + val (from, to) = period.getObjectDates() + + fromDatePicker = DatePickerDialog(requireContext(), { p0, p1, p2, p3 -> + fromPickedDatetime = LocalDateTime(p1, p2, p3, from.hour, from.minute) + fromTimePicker.show() + }, from.year, from.monthNumber, from.dayOfMonth) + + fromTimePicker = TimePickerDialog(requireContext(), { p0, p1, p2 -> + fromPickedDatetime = LocalDateTime( + fromPickedDatetime.year, + fromPickedDatetime.monthNumber, + fromPickedDatetime.dayOfMonth, + p1, p2 + ) + (period as? ReportDates.ReportPeriod.Custom)?.let { + unitReportsViewModel.setReportPeriod(it.withFrom(fromPickedDatetime)) + } + }, from.hour, from.minute, false) + + toDatePicker = DatePickerDialog(requireContext(), { p0, p1, p2, p3 -> + toPickedDatetime = LocalDateTime(p1, p2, p3, from.hour, from.minute) + toTimePicker.show() + }, to.year, to.monthNumber, to.dayOfMonth) + + toTimePicker = TimePickerDialog(requireContext(), { p0, p1, p2 -> + toPickedDatetime = LocalDateTime( + toPickedDatetime.year, + toPickedDatetime.monthNumber, + toPickedDatetime.dayOfMonth, + p1, p2 + ) + (period as? ReportDates.ReportPeriod.Custom)?.let { + unitReportsViewModel.setReportPeriod(it.withFrom(fromPickedDatetime)) + } + }, to.hour, to.minute, false) } unitReportsViewModel.geofences.observe(viewLifecycleOwner) { geofences -> @@ -280,9 +379,10 @@ class UnitReportsFragment : Fragment() { EventInformation.Type.MAINTENANCE -> R.string.event_maintenance EventInformation.Type.TEXT_MESSAGE -> R.string.event_text_message EventInformation.Type.DRIVER_CHANGED -> R.string.event_driver_changed - EventInformation.Type.UNKNOWN -> R.string.event_unknown + EventInformation.Type.UNKNOWN -> R.string.event_unknown else -> R.string.event_unknown - }) + } + ) } event.geofence?.let { geofenceText.text = it.name -- cgit v1.2.3