diff --git a/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt b/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt index 82e3c3bff7b..5537229dd18 100644 --- a/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt +++ b/app/src/androidTest/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/EventInitialTest.kt @@ -224,7 +224,7 @@ class EventInitialTest { EventInputDateUiModel( eventDate = date, detailsEnabled = details.enabled, - onDateClick = { viewModel.onDateClick() }, + onDateClick = viewModel.showPeriodDialog() , onDateSet = { dateValues -> viewModel.onDateSet(dateValues.year, dateValues.month, dateValues.day) }, @@ -257,7 +257,7 @@ class EventInitialTest { EventInputDateUiModel( eventDate = date, detailsEnabled = details.enabled, - onDateClick = { viewModel.onDateClick() }, + onDateClick = viewModel.showPeriodDialog(), onDateSet = { dateValues -> viewModel.onDateSet(dateValues.year, dateValues.month, dateValues.day) }, diff --git a/app/src/main/java/org/dhis2/usescases/events/ScheduledEventActivity.kt b/app/src/main/java/org/dhis2/usescases/events/ScheduledEventActivity.kt index de8bc640284..4f12d3b6088 100644 --- a/app/src/main/java/org/dhis2/usescases/events/ScheduledEventActivity.kt +++ b/app/src/main/java/org/dhis2/usescases/events/ScheduledEventActivity.kt @@ -4,15 +4,12 @@ import android.content.Context import android.content.Intent import android.os.Bundle import android.view.View -import android.widget.DatePicker import androidx.compose.foundation.layout.Column import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.databinding.DataBindingUtil import org.dhis2.App import org.dhis2.R import org.dhis2.commons.data.EventCreationType -import org.dhis2.commons.dialogs.calendarpicker.CalendarPicker -import org.dhis2.commons.dialogs.calendarpicker.OnDatePickerListener import org.dhis2.databinding.ActivityEventScheduledBinding import org.dhis2.usescases.eventsWithoutRegistration.eventCapture.EventCaptureActivity import org.dhis2.usescases.eventsWithoutRegistration.eventDetails.models.EventDate @@ -28,8 +25,6 @@ import org.hisp.dhis.android.core.event.EventStatus import org.hisp.dhis.android.core.period.PeriodType import org.hisp.dhis.android.core.program.Program import org.hisp.dhis.android.core.program.ProgramStage -import java.util.Calendar -import java.util.Date import javax.inject.Inject const val EXTRA_EVENT_UID = "EVENT_UID" @@ -109,14 +104,17 @@ class ScheduledEventActivity : ActivityGlobalAbstract(), ScheduledEventContract. dateValue = "", ) + val eventDateAction = if (programStage.periodType() == null) null else showEventDatePeriodDialog(programStage.periodType()) + ProvideInputDate( EventInputDateUiModel( eventDate = eventDate, allowsManualInput = false, detailsEnabled = true, - onDateClick = { setEvenDateListener(programStage.periodType()) }, + onDateClick = eventDateAction, onDateSet = {}, onClear = {}, + selectableDates = presenter.getSelectableDates(program, false), ), ) @@ -125,13 +123,18 @@ class ScheduledEventActivity : ActivityGlobalAbstract(), ScheduledEventContract. label = programStage.dueDateLabel() ?: getString(R.string.due_date), dateValue = DateUtils.uiDateFormat().format(event.dueDate() ?: ""), ) + val dueDateAction = if (programStage.periodType() == null) null else showDueDatePeriodDialog(programStage.periodType()) + ProvideInputDate( EventInputDateUiModel( eventDate = dueDate, detailsEnabled = true, - onDateClick = { setDueDateListener(programStage.periodType()) }, - onDateSet = {}, + onDateClick = dueDateAction, + onDateSet = { date -> + presenter.setEventDate(presenter.formatDateValues(date)) + }, onClear = {}, + selectableDates = presenter.getSelectableDates(program, true), ), ) } @@ -145,10 +148,8 @@ class ScheduledEventActivity : ActivityGlobalAbstract(), ScheduledEventContract. binding.name = program.displayName() } - private fun setEvenDateListener(periodType: PeriodType?) { - if (periodType == null) { - showCustomCalendar(false) - } else { + private fun showEventDatePeriodDialog(periodType: PeriodType?) { + if (periodType != null) { var minDate = DateUtils.getInstance().expDate(null, program.expiryDays()!!, periodType) val lastPeriodDate = @@ -174,10 +175,8 @@ class ScheduledEventActivity : ActivityGlobalAbstract(), ScheduledEventContract. } } - private fun setDueDateListener(periodType: PeriodType?) { - if (periodType == null) { - showCustomCalendar(true) - } else { + private fun showDueDatePeriodDialog(periodType: PeriodType?) { + if (periodType != null) { var minDate = DateUtils.getInstance().expDate(null, program.expiryDays()!!, periodType) val lastPeriodDate = @@ -203,51 +202,6 @@ class ScheduledEventActivity : ActivityGlobalAbstract(), ScheduledEventContract. } } - private fun showCustomCalendar(isDueDate: Boolean) { - val dialog = CalendarPicker(this) - - if (isDueDate) { - dialog.setInitialDate(event.dueDate()) - dialog.setScheduleInterval(stage.standardInterval() ?: 0) - } - - if (program.expiryPeriodType() != null) { - val minDate = DateUtils.getInstance().expDate( - null, - program.expiryDays() ?: 0, - program.expiryPeriodType(), - ) - dialog.setMinDate(minDate) - } - - if (!isDueDate) { - dialog.setMaxDate(Date(System.currentTimeMillis() - 1000)) - } - dialog.setListener(object : OnDatePickerListener { - override fun onNegativeClick() { - dialog.dismiss() - } - - override fun onPositiveClick(datePicker: DatePicker) { - val date = Calendar.getInstance().apply { - set(Calendar.YEAR, datePicker.year) - set(Calendar.MONTH, datePicker.month) - set(Calendar.DAY_OF_MONTH, datePicker.dayOfMonth) - set(Calendar.HOUR, 0) - set(Calendar.MINUTE, 0) - set(Calendar.SECOND, 0) - set(Calendar.MILLISECOND, 0) - }.time - if (isDueDate) { - presenter.setDueDate(date) - } else { - presenter.setEventDate(date) - } - } - }) - dialog.show() - } - override fun openInitialActivity() { val bundle = EventInitialActivity.getBundle( program.uid(), diff --git a/app/src/main/java/org/dhis2/usescases/events/ScheduledEventContract.kt b/app/src/main/java/org/dhis2/usescases/events/ScheduledEventContract.kt index 0bf7b898a49..052a792c2a2 100644 --- a/app/src/main/java/org/dhis2/usescases/events/ScheduledEventContract.kt +++ b/app/src/main/java/org/dhis2/usescases/events/ScheduledEventContract.kt @@ -1,11 +1,13 @@ package org.dhis2.usescases.events +import org.dhis2.usescases.eventsWithoutRegistration.eventDetails.providers.InputDateValues import org.dhis2.usescases.general.AbstractActivityContracts import org.hisp.dhis.android.core.category.CategoryOption import org.hisp.dhis.android.core.enrollment.Enrollment import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.program.Program import org.hisp.dhis.android.core.program.ProgramStage +import org.hisp.dhis.mobile.ui.designsystem.component.SelectableDates import java.util.Date class ScheduledEventContract { @@ -22,11 +24,14 @@ class ScheduledEventContract { fun init() fun finish() fun setEventDate(date: Date) + fun formatDateValues(date: InputDateValues): Date fun setDueDate(date: Date) + fun getDateFormatConfiguration(): String? fun skipEvent() fun setCatOptionCombo(catComboUid: String, arrayList: ArrayList) fun onBackClick() fun getEventTei(): String fun getEnrollment(): Enrollment? + fun getSelectableDates(program: Program, isDueDate: Boolean): SelectableDates? } } diff --git a/app/src/main/java/org/dhis2/usescases/events/ScheduledEventPresenterImpl.kt b/app/src/main/java/org/dhis2/usescases/events/ScheduledEventPresenterImpl.kt index 407a2991c59..3b1098efee8 100644 --- a/app/src/main/java/org/dhis2/usescases/events/ScheduledEventPresenterImpl.kt +++ b/app/src/main/java/org/dhis2/usescases/events/ScheduledEventPresenterImpl.kt @@ -4,13 +4,20 @@ import io.reactivex.Single import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable import org.dhis2.data.dhislogic.DhisEventUtils +import org.dhis2.usescases.eventsWithoutRegistration.eventDetails.providers.InputDateValues +import org.dhis2.utils.DateUtils import org.hisp.dhis.android.core.D2 import org.hisp.dhis.android.core.arch.helpers.UidsHelper import org.hisp.dhis.android.core.category.CategoryOption import org.hisp.dhis.android.core.enrollment.Enrollment import org.hisp.dhis.android.core.event.EventStatus +import org.hisp.dhis.android.core.program.Program +import org.hisp.dhis.mobile.ui.designsystem.component.SelectableDates import timber.log.Timber +import java.text.SimpleDateFormat +import java.util.Calendar import java.util.Date +import java.util.Locale class ScheduledEventPresenterImpl( val view: ScheduledEventContract.View, @@ -82,6 +89,32 @@ class ScheduledEventPresenterImpl( } } + override fun formatDateValues(date: InputDateValues): Date { + val calendar = Calendar.getInstance() + calendar[date.year, date.month - 1, date.day, 0, 0] = 0 + calendar[Calendar.MILLISECOND] = 0 + return calendar.time + } + + override fun getDateFormatConfiguration(): String? { + return d2.systemInfoModule().systemInfo().blockingGet()?.dateFormat() + } + + override fun getSelectableDates(program: Program, isDueDate: Boolean): SelectableDates? { + val minDate = if (program.expiryPeriodType() != null) { + DateUtils.getInstance().expDate( + null, + program.expiryDays() ?: 0, + program.expiryPeriodType(), + ) + } else { + null + } + val minDateString = if (minDate == null) null else SimpleDateFormat("ddMMyyyy", Locale.US).format(minDate) + val maxDateString = if (isDueDate)"12112124" else SimpleDateFormat("ddMMyyyy", Locale.US).format(Date(System.currentTimeMillis() - 1000)) + return SelectableDates(minDateString ?: "12111924", maxDateString) + } + override fun setDueDate(date: Date) { d2.eventModule().events().uid(eventUid).setDueDate(date) d2.eventModule().events().uid(eventUid).setStatus(EventStatus.SCHEDULE) diff --git a/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/data/EventDetailsRepository.kt b/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/data/EventDetailsRepository.kt index 0029f6ac3d5..c92dded19e5 100644 --- a/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/data/EventDetailsRepository.kt +++ b/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/data/EventDetailsRepository.kt @@ -42,6 +42,10 @@ class EventDetailsRepository( .blockingGet() } + fun getDateFormatConfiguration(): String? { + return d2.systemInfoModule().systemInfo().blockingGet()?.dateFormat() + } + fun getObjectStyle(): ObjectStyle? { val programStage = getProgramStage() val program = getProgram() diff --git a/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/models/EventInputDateUiModel.kt b/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/models/EventInputDateUiModel.kt index c7f92b621c9..5ec149426f2 100644 --- a/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/models/EventInputDateUiModel.kt +++ b/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/models/EventInputDateUiModel.kt @@ -1,14 +1,17 @@ package org.dhis2.usescases.eventsWithoutRegistration.eventDetails.models import org.dhis2.usescases.eventsWithoutRegistration.eventDetails.providers.InputDateValues +import org.hisp.dhis.mobile.ui.designsystem.component.SelectableDates data class EventInputDateUiModel( val eventDate: EventDate, val detailsEnabled: Boolean, - val onDateClick: () -> Unit, + val onDateClick: Unit?, val allowsManualInput: Boolean = true, val onDateSet: (InputDateValues) -> Unit, val onClear: () -> Unit, val required: Boolean = false, val showField: Boolean = true, + val is24HourFormat: Boolean = true, + val selectableDates: SelectableDates? = null, ) diff --git a/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/providers/InputFieldsProvider.kt b/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/providers/InputFieldsProvider.kt index 4dd1678f0e9..f6a22679c8b 100644 --- a/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/providers/InputFieldsProvider.kt +++ b/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/providers/InputFieldsProvider.kt @@ -30,10 +30,11 @@ import org.hisp.dhis.android.core.common.FeatureType import org.hisp.dhis.android.core.common.Geometry import org.hisp.dhis.android.core.common.ValueType import org.hisp.dhis.mobile.ui.designsystem.component.Coordinates -import org.hisp.dhis.mobile.ui.designsystem.component.DateTimeActionIconType +import org.hisp.dhis.mobile.ui.designsystem.component.DateTimeActionType import org.hisp.dhis.mobile.ui.designsystem.component.DropdownItem import org.hisp.dhis.mobile.ui.designsystem.component.InputCoordinate import org.hisp.dhis.mobile.ui.designsystem.component.InputDateTime +import org.hisp.dhis.mobile.ui.designsystem.component.InputDateTimeModel import org.hisp.dhis.mobile.ui.designsystem.component.InputDropDown import org.hisp.dhis.mobile.ui.designsystem.component.InputOrgUnit import org.hisp.dhis.mobile.ui.designsystem.component.InputPolygon @@ -41,6 +42,7 @@ import org.hisp.dhis.mobile.ui.designsystem.component.InputRadioButton import org.hisp.dhis.mobile.ui.designsystem.component.InputShellState import org.hisp.dhis.mobile.ui.designsystem.component.Orientation import org.hisp.dhis.mobile.ui.designsystem.component.RadioButtonData +import org.hisp.dhis.mobile.ui.designsystem.component.SelectableDates import org.hisp.dhis.mobile.ui.designsystem.component.internal.DateTransformation import java.time.LocalDate import java.time.format.DateTimeFormatter @@ -54,7 +56,6 @@ fun ProvideInputDate( if (uiModel.showField) { Spacer(modifier = Modifier.height(16.dp)) val textSelection = TextRange(if (uiModel.eventDate.dateValue != null) uiModel.eventDate.dateValue.length else 0) - var value by remember(uiModel.eventDate.dateValue) { if (uiModel.eventDate.dateValue != null) { mutableStateOf(TextFieldValue(formatStoredDateToUI(uiModel.eventDate.dateValue) ?: "", textSelection)) @@ -68,25 +69,36 @@ fun ProvideInputDate( } InputDateTime( - title = uiModel.eventDate.label ?: "", - allowsManualInput = uiModel.allowsManualInput, - inputTextFieldValue = value, - actionIconType = DateTimeActionIconType.DATE, - onActionClicked = uiModel.onDateClick, - state = state, - visualTransformation = DateTransformation(), - onValueChanged = { - value = it - state = getInputShellStateBasedOnValue(it.text) - manageActionBasedOnValue(uiModel, it.text) - }, - isRequired = uiModel.required, + InputDateTimeModel( + title = uiModel.eventDate.label ?: "", + allowsManualInput = uiModel.allowsManualInput, + inputTextFieldValue = value, + actionType = DateTimeActionType.DATE, + state = state, + visualTransformation = DateTransformation(), + onValueChanged = { + value = it ?: TextFieldValue() + state = getInputShellStateBasedOnValue(it?.text) + it?.let { it1 -> manageActionBasedOnValue(uiModel, it1.text) } + }, + isRequired = uiModel.required, + onFocusChanged = { focused -> + if (!focused && !isValid(value.text)) { + state = InputShellState.ERROR + } + }, + format = "ddMMyyyy", + is24hourFormat = uiModel.is24HourFormat, + selectableDates = uiModel.selectableDates ?: SelectableDates("01011924", "12312124"), + onDateSelected = { dateString -> + dateString?.let { + formatUIDateToStored(it)?.let { formatedDate -> + uiModel.onDateSet.invoke(formatedDate) + } + } + }, + ), modifier = modifier.testTag(INPUT_EVENT_INITIAL_DATE), - onFocusChanged = { focused -> - if (!focused && !isValid(value.text)) { - state = InputShellState.ERROR - } - }, ) } } diff --git a/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/ui/EventDetailsFragment.kt b/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/ui/EventDetailsFragment.kt index 5fa549c06eb..dcbbfe13f37 100644 --- a/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/ui/EventDetailsFragment.kt +++ b/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/ui/EventDetailsFragment.kt @@ -236,18 +236,20 @@ class EventDetailsFragment : FragmentGlobalAbstract() { coordinates: EventCoordinates, eventTemp: EventTemp, ) { + val eventDateAction = if (viewModel.getPeriodType() == null) null else viewModel.showPeriodDialog() Column { ProvideInputDate( EventInputDateUiModel( eventDate = date, detailsEnabled = details.enabled, - onDateClick = { viewModel.onDateClick() }, + onDateClick = eventDateAction, onDateSet = { dateValues -> viewModel.onDateSet(dateValues.year, dateValues.month - 1, dateValues.day) }, onClear = { viewModel.onClearEventReportDate() }, required = true, showField = date.active, + ), ) ProvideOrgUnit( diff --git a/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/ui/EventDetailsViewModel.kt b/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/ui/EventDetailsViewModel.kt index 614e1232a85..22ceb88aed6 100644 --- a/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/ui/EventDetailsViewModel.kt +++ b/app/src/main/java/org/dhis2/usescases/eventsWithoutRegistration/eventDetails/ui/EventDetailsViewModel.kt @@ -243,10 +243,10 @@ class EventDetailsViewModel( EventDetailIdlingResourceSingleton.decrement() } - fun onDateClick() { + fun showPeriodDialog() { periodType?.let { showPeriods?.invoke() - } ?: showCalendar?.invoke() + } } fun onDateSet(year: Int, month: Int, day: Int) { @@ -323,6 +323,10 @@ class EventDetailsViewModel( } } + fun getPeriodType(): PeriodType? { + return periodType + } + fun onReopenClick() { configureEventDetails.reopenEvent().mockSafeFold( onSuccess = { diff --git a/form/src/androidTest/kotlin/org/dhis2/form/ui/provider/inputfield/DateProviderTest.kt b/form/src/androidTest/kotlin/org/dhis2/form/ui/provider/inputfield/DateProviderTest.kt index 2576ed2979a..adb6feeb33f 100644 --- a/form/src/androidTest/kotlin/org/dhis2/form/ui/provider/inputfield/DateProviderTest.kt +++ b/form/src/androidTest/kotlin/org/dhis2/form/ui/provider/inputfield/DateProviderTest.kt @@ -41,7 +41,6 @@ class DateProviderTest { modifier = Modifier.testTag(INPUT_DATE_TEST_TAG), fieldUiModel = dateValueTypeFieldUiModel, intentHandler = {}, - uiEventHandler = {} , onNextClicked = {}, ) @@ -53,20 +52,17 @@ class DateProviderTest { @Test fun shouldParseADateTimeValueCorrectlyAndDisplayInput() { - val dateValueTypeFieldUiModel = generateFieldUiModel(FIELD_UI_MODEL_UID,DATE_TIME_VALUE,DATE_TIME_VALUE, ValueType.DATETIME) composeTestRule.setContent { ProvideInputDate( modifier = Modifier.testTag(INPUT_DATE_TEST_TAG), fieldUiModel = dateValueTypeFieldUiModel, intentHandler = {}, - uiEventHandler = {} , onNextClicked = {}, ) } composeTestRule.onNodeWithTag(INPUT_DATE_TEST_TAG).assertIsDisplayed() composeTestRule.onNodeWithTag(INPUT_DATE_TEST_TAG).assertContentDescriptionEquals(FORMATTED_DATE_TIME_VALUE) - } @Test @@ -79,7 +75,6 @@ class DateProviderTest { modifier = Modifier.testTag(INPUT_DATE_TEST_TAG), fieldUiModel = dateValueTypeFieldUiModel, intentHandler = {}, - uiEventHandler = {} , onNextClicked = {}, ) } diff --git a/form/src/main/java/org/dhis2/form/data/DataEntryBaseRepository.kt b/form/src/main/java/org/dhis2/form/data/DataEntryBaseRepository.kt index 6f7b795d214..67d59f24562 100644 --- a/form/src/main/java/org/dhis2/form/data/DataEntryBaseRepository.kt +++ b/form/src/main/java/org/dhis2/form/data/DataEntryBaseRepository.kt @@ -77,6 +77,10 @@ abstract class DataEntryBaseRepository( return optionsFromGroups } + override fun dateFormatConfiguration(): String? { + return conf.dateFormatConfiguration() + } + fun transformSection( sectionUid: String, sectionName: String?, diff --git a/form/src/main/java/org/dhis2/form/data/DataEntryRepository.kt b/form/src/main/java/org/dhis2/form/data/DataEntryRepository.kt index 41a3ee02131..9bb348afdb9 100644 --- a/form/src/main/java/org/dhis2/form/data/DataEntryRepository.kt +++ b/form/src/main/java/org/dhis2/form/data/DataEntryRepository.kt @@ -26,5 +26,7 @@ interface DataEntryRepository { fun isEvent(): Boolean + fun dateFormatConfiguration(): String? + fun disableCollapsableSections(): Boolean? } diff --git a/form/src/main/java/org/dhis2/form/data/FormRepository.kt b/form/src/main/java/org/dhis2/form/data/FormRepository.kt index cddf628b63c..37e590eaf63 100644 --- a/form/src/main/java/org/dhis2/form/data/FormRepository.kt +++ b/form/src/main/java/org/dhis2/form/data/FormRepository.kt @@ -20,6 +20,7 @@ interface FormRepository { fun currentFocusedItem(): FieldUiModel? fun setFocusedItem(action: RowAction) fun updateSectionOpened(action: RowAction) + fun getDateFormatConfiguration(): String fun removeAllValues() fun setFieldRequestingCoordinates(uid: String, requestInProcess: Boolean) fun setFieldAddingImage(uid: String, requestInProcess: Boolean) diff --git a/form/src/main/java/org/dhis2/form/data/FormRepositoryImpl.kt b/form/src/main/java/org/dhis2/form/data/FormRepositoryImpl.kt index 3f7ab176148..36bb84f4c41 100644 --- a/form/src/main/java/org/dhis2/form/data/FormRepositoryImpl.kt +++ b/form/src/main/java/org/dhis2/form/data/FormRepositoryImpl.kt @@ -485,6 +485,9 @@ class FormRepositoryImpl( openedSectionUid = action.id } } + override fun getDateFormatConfiguration(): String { + return dataEntryRepository?.dateFormatConfiguration() ?: "ddMMyyyy" + } fun Iterable.updated(index: Int, elem: E): List = mapIndexed { i, existing -> if (i == index) elem else existing } diff --git a/form/src/main/java/org/dhis2/form/data/metadata/FormBaseConfiguration.kt b/form/src/main/java/org/dhis2/form/data/metadata/FormBaseConfiguration.kt index d24fb474982..98009662460 100644 --- a/form/src/main/java/org/dhis2/form/data/metadata/FormBaseConfiguration.kt +++ b/form/src/main/java/org/dhis2/form/data/metadata/FormBaseConfiguration.kt @@ -11,4 +11,7 @@ open class FormBaseConfiguration(private val d2: D2) { fun disableCollapsableSectionsInProgram(programUid: String) = d2.disableCollapsableSectionsInProgram(programUid) + + fun dateFormatConfiguration() = + d2.systemInfoModule().systemInfo().blockingGet()?.dateFormat() } diff --git a/form/src/main/java/org/dhis2/form/ui/FormViewModel.kt b/form/src/main/java/org/dhis2/form/ui/FormViewModel.kt index 538cc3b52bc..cc5d8fdd3cb 100644 --- a/form/src/main/java/org/dhis2/form/ui/FormViewModel.kt +++ b/form/src/main/java/org/dhis2/form/ui/FormViewModel.kt @@ -57,7 +57,7 @@ class FormViewModel( val focused = MutableLiveData() val showInfo = MutableLiveData() val confError = MutableLiveData>() - + var dateFormatConfig: String = "ddMMyyyy" private val _items = MutableLiveData>() val items: LiveData> = _items @@ -724,6 +724,9 @@ class FormViewModel( val result = async { repository.fetchFormItems(openErrorLocation) } + dateFormatConfig = async { + repository.getDateFormatConfiguration() + }.await() try { _items.postValue(result.await()) } catch (e: Exception) { diff --git a/form/src/main/java/org/dhis2/form/ui/provider/inputfield/DateProvider.kt b/form/src/main/java/org/dhis2/form/ui/provider/inputfield/DateProvider.kt index 3083b5dfc33..ef99a5cbd0e 100644 --- a/form/src/main/java/org/dhis2/form/ui/provider/inputfield/DateProvider.kt +++ b/form/src/main/java/org/dhis2/form/ui/provider/inputfield/DateProvider.kt @@ -10,33 +10,34 @@ import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue -import org.dhis2.commons.date.DateUtils -import org.dhis2.commons.extensions.toDate import org.dhis2.form.extensions.inputState import org.dhis2.form.extensions.legend import org.dhis2.form.extensions.supportingText import org.dhis2.form.model.FieldUiModel -import org.dhis2.form.ui.event.RecyclerViewUiEvents import org.dhis2.form.ui.intent.FormIntent import org.hisp.dhis.android.core.common.ValueType -import org.hisp.dhis.mobile.ui.designsystem.component.DateTimeActionIconType +import org.hisp.dhis.mobile.ui.designsystem.component.DateTimeActionType import org.hisp.dhis.mobile.ui.designsystem.component.InputDateTime +import org.hisp.dhis.mobile.ui.designsystem.component.InputDateTimeModel +import org.hisp.dhis.mobile.ui.designsystem.component.SelectableDates import org.hisp.dhis.mobile.ui.designsystem.component.internal.DateTimeTransformation import org.hisp.dhis.mobile.ui.designsystem.component.internal.DateTransformation import org.hisp.dhis.mobile.ui.designsystem.component.internal.TimeTransformation +import java.text.SimpleDateFormat +import java.time.LocalDate +import java.util.Locale @Composable fun ProvideInputDate( modifier: Modifier, fieldUiModel: FieldUiModel, intentHandler: (FormIntent) -> Unit, - uiEventHandler: (RecyclerViewUiEvents) -> Unit, onNextClicked: () -> Unit, ) { val (actionType, visualTransformation) = when (fieldUiModel.valueType) { - ValueType.DATETIME -> DateTimeActionIconType.DATE_TIME to DateTimeTransformation() - ValueType.TIME -> DateTimeActionIconType.TIME to TimeTransformation() - else -> DateTimeActionIconType.DATE to DateTransformation() + ValueType.DATETIME -> DateTimeActionType.DATE_TIME to DateTimeTransformation() + ValueType.TIME -> DateTimeActionType.TIME to TimeTransformation() + else -> DateTimeActionType.DATE to DateTransformation() } val textSelection = TextRange(if (fieldUiModel.value != null) fieldUiModel.value!!.length else 0) @@ -49,66 +50,38 @@ fun ProvideInputDate( }, ) } - + val selectableDates = if (fieldUiModel.allowFutureDates == true) { + SelectableDates(initialDate = "12111924", endDate = "12112124") + } else { + SelectableDates(initialDate = "12111924", endDate = SimpleDateFormat("ddMMyyyy", Locale.US).format(LocalDate.now())) + } InputDateTime( - title = fieldUiModel.label, - inputTextFieldValue = value, - actionIconType = actionType, - onActionClicked = { - when (actionType) { - DateTimeActionIconType.DATE -> uiEventHandler.invoke( - RecyclerViewUiEvents.OpenCustomCalendar( + InputDateTimeModel( + title = fieldUiModel.label, + inputTextFieldValue = value, + actionType = actionType, + state = fieldUiModel.inputState(), + legendData = fieldUiModel.legend(), + supportingText = fieldUiModel.supportingText(), + isRequired = fieldUiModel.mandatory, + visualTransformation = visualTransformation, + onFocusChanged = {}, + onNextClicked = onNextClicked, + onValueChanged = { + value = it ?: TextFieldValue() + intentHandler.invoke( + FormIntent.OnTextChange( uid = fieldUiModel.uid, - label = fieldUiModel.label, - date = value.text.toDate(), + value = formatUIDateToStored(it?.text, fieldUiModel.valueType), + valueType = fieldUiModel.valueType, allowFutureDates = fieldUiModel.allowFutureDates ?: true, - isDateTime = false, ), ) - - DateTimeActionIconType.TIME -> uiEventHandler.invoke( - RecyclerViewUiEvents.OpenTimePicker( - uid = fieldUiModel.uid, - label = fieldUiModel.label, - date = formatUIDateToStored(value.text, fieldUiModel.valueType)?.let { - DateUtils.timeFormat().parse(it) - }, - isDateTime = false, - ), - ) - - DateTimeActionIconType.DATE_TIME -> uiEventHandler.invoke( - RecyclerViewUiEvents.OpenCustomCalendar( - uid = fieldUiModel.uid, - label = fieldUiModel.label, - date = formatUIDateToStored(value.text, fieldUiModel.valueType)?.let { - DateUtils.databaseDateFormatNoSeconds().parse(it) - }, - allowFutureDates = fieldUiModel.allowFutureDates ?: true, - isDateTime = true, - ), - ) - } - }, + }, + format = "ddMMyyyy", + selectableDates = selectableDates, + ), modifier = modifier.semantics { contentDescription = formatStoredDateToUI(value.text, fieldUiModel.valueType) }, - state = fieldUiModel.inputState(), - legendData = fieldUiModel.legend(), - supportingText = fieldUiModel.supportingText(), - isRequired = fieldUiModel.mandatory, - visualTransformation = visualTransformation, - onFocusChanged = {}, - onNextClicked = onNextClicked, - onValueChanged = { - value = it - intentHandler.invoke( - FormIntent.OnTextChange( - uid = fieldUiModel.uid, - value = formatUIDateToStored(it.text, fieldUiModel.valueType), - valueType = fieldUiModel.valueType, - allowFutureDates = fieldUiModel.allowFutureDates ?: true, - ), - ) - }, ) } diff --git a/form/src/main/java/org/dhis2/form/ui/provider/inputfield/FieldProvider.kt b/form/src/main/java/org/dhis2/form/ui/provider/inputfield/FieldProvider.kt index 625a51a7e5d..12d3fcd3b40 100644 --- a/form/src/main/java/org/dhis2/form/ui/provider/inputfield/FieldProvider.kt +++ b/form/src/main/java/org/dhis2/form/ui/provider/inputfield/FieldProvider.kt @@ -319,7 +319,6 @@ internal fun FieldProvider( modifier = modifierWithFocus, fieldUiModel = fieldUiModel, intentHandler = intentHandler, - uiEventHandler = uiEventHandler, onNextClicked = onNextClicked, ) }