How do I get my DatePicker Dialog to return a date and display it? Issue updating viewmodel

Viewed 78

A quick preface, I'm probably overlooking something rather simple but I'm willing to admit I'm not 100% sure of what I'm doing! The project I'm working on is a just for fun project to tinker around with Kotlin and Jetpack Compose by making an Android application.

So to my problem, I'm trying to use a DatePicker dialog using the vanpra compose-material-dialogs. I can get the dialog datepicker to appear but I can't get my selected date to return to my textfield I made after selecting the date from the dialog. It seems I'm running in to some issues updating the viewmodel correctly. Any help at all is greatly appreciated! Thank you!


Below is my DatePicker composable:

@Composable
fun TradeDatePicker(
    value: LocalDate,
    onValueChanged: (LocalDate) -> Unit,
    modifier:Modifier = Modifier,
    ) {
        val dialogState = rememberMaterialDialogState()

        MaterialDialog(
            dialogState = dialogState,
            buttons = {
                positiveButton("OK")
                negativeButton("CANCEL")


            },
            backgroundColor = MaterialTheme.colors.background
        ) {
            this.datepicker(onDateChange = onValueChanged)
        }
        Box(
            modifier = modifier
                .border(
                    width = 1.dp,
                    color = MaterialTheme.colors.onPrimary,
                    shape = RoundedCornerShape(50),
                    )
                .clip(ButtonShape) //clip keeps animation within box borders
                .clickable {
                    dialogState.show()
                }
        ){
            Row (
                modifier = Modifier
                    .padding(16.dp),
                    ){
                Text(
                    text = "Trade Date",
                    modifier = Modifier
                        .weight(1F),
                )
                Icon(
                    Icons.Default.DateRange,
                    contentDescription = "Select Date",
                )
            }
        }
    }

Here is my screen where you select the datepicker field to display the datepicker dialog, it seems I'm trying to pass a LocalDate to the viewmodel but it requires a long(that's how I thought the date got returned from the dialog, as a long):

@Composable
fun AddEditTradeScreen(

    navController: NavController,
    viewModel: AddEditTradeViewModel = hiltViewModel()
){
    val tradesymbolState = viewModel.tradeSymbol.value
    val tradequantState = viewModel.tradeQuantity.value
    val tradeDateState = viewModel.tradeDate
    val scaffoldState = rememberScaffoldState()
    val value: LocalDate

    LaunchedEffect(key1 = true){
        viewModel.eventFlow.collectLatest { event ->
            when(event){
                is AddEditTradeViewModel.UiEvent.ShowSnackbar ->{
                    scaffoldState.snackbarHostState.showSnackbar(
                        message = event.message
                    )

                }
                is AddEditTradeViewModel.UiEvent.SaveTrade -> {
                    navController.navigateUp()

                }
            }
        }
    }
    
    Scaffold(
        floatingActionButton = {
            FloatingActionButton(
                onClick = {
                    viewModel.onEvent(AddEditTradeEvent.SaveTrade)
                },
                backgroundColor = MaterialTheme.colors.primary
            ) {
                Icon(imageVector = Icons.Default.Save, contentDescription = "Save Trade")
            }
        },
        scaffoldState = scaffoldState
    ) {
        Column(

            modifier = Modifier
                .fillMaxSize()
                .padding(16.dp)
        ) {



            Text(
                modifier = Modifier.fillMaxWidth(),
                text = "Enter Your Tradeeee",
                style = MaterialTheme.typography.h4,
                textAlign = TextAlign.Center
            )

            Spacer(modifier = Modifier.height(20.dp))


            TransparentHintTextField(
                text = tradesymbolState.text,
                hint = tradesymbolState.hint,
                onValueChange = {
                                viewModel.onEvent(AddEditTradeEvent.EnteredSymbol(it))
                },
                onFocusChange = {
                    viewModel.onEvent(AddEditTradeEvent.ChangeSymbolFocus(it))
                },
                isHintVisible = tradesymbolState.isHintVisible,
                singleLine = true,
                textStyle = MaterialTheme.typography.h5
            )
            Spacer(modifier = Modifier.height(16.dp))

            TransparentHintTextField(
                text = tradequantState.text,
                hint = tradequantState.hint,
                onValueChange = {
                    viewModel.onEvent(AddEditTradeEvent.EnteredQuantity(it))
                },
                onFocusChange = {
                    viewModel.onEvent(AddEditTradeEvent.ChangeQuantityFocus(it))
                },
                isHintVisible = tradequantState.isHintVisible,
                textStyle = MaterialTheme.typography.body1,
                //modifier = Modifier.fillMaxHeight()
            )

            Spacer(modifier = Modifier.height(16.dp))

            TradeDatePicker(
                value = LocalDate.now(),
                onValueChanged = {
                                 viewModel.onEvent(AddEditTradeEvent.EnteredTradeDate(it))
                                 },
                modifier = Modifier
                    .fillMaxWidth()
            )

        }
    }

}

This is my viewmodel that I'm trying to update:

@HiltViewModel
class AddEditTradeViewModel @Inject constructor(
    private val tradeUseCases: TradeUseCases,
    savedStateHandle: SavedStateHandle
) : ViewModel(){
    private val _tradeSymbol = mutableStateOf(
        TradeTextFieldState(
        hint = "Enter Trade Symobol"
    ))
    val tradeSymbol: State<TradeTextFieldState> = _tradeSymbol
    private val _tradeQuantity = mutableStateOf(
        TradeTextFieldState(
        hint = "Enter Number of Shares"
    ))
    val tradeQuantity: State<TradeTextFieldState> = _tradeQuantity
    private var _tradeDate : String? by remember {
        mutableStateOf(null)
    }
    val tradeDate = { date: Long? ->
        _tradeDate = date?.toString()?:""
    }
    private val _eventFlow = MutableSharedFlow<UiEvent>()
    val eventFlow = _eventFlow.asSharedFlow()
    private var currentTradeId: Int? = null

    init{
        savedStateHandle.get<Int>("tradeId")?.let { tradeId ->
            if (tradeId != -1){
                viewModelScope.launch {
                    tradeUseCases.getTrade(tradeId)?.also { trade ->
                        currentTradeId = trade.id
                        _tradeSymbol.value = tradeSymbol.value.copy(
                            text = trade.tradeSymb,
                            isHintVisible = false
                        )
                        _tradeQuantity.value = tradeQuantity.value.copy(
                            text = trade.tradequant,
                            isHintVisible = false
                        )
                    }
                }
            }
        }
    }

    fun onEvent(event: AddEditTradeEvent){
        when(event){
            is AddEditTradeEvent.EnteredSymbol -> {
                _tradeSymbol.value = tradeSymbol.value.copy(
                    text = event.value
                )
            }
            is AddEditTradeEvent.ChangeSymbolFocus -> {
                _tradeSymbol.value = tradeSymbol.value.copy(
                    isHintVisible = !event.focusState.isFocused &&
                            tradeSymbol.value.text.isBlank()
                )
            }
            is AddEditTradeEvent.EnteredQuantity -> {
                _tradeQuantity.value = tradeQuantity.value.copy(
                    text = event.value
                )
            }
            is AddEditTradeEvent.ChangeQuantityFocus -> {
                _tradeQuantity.value = tradeQuantity.value.copy(
                    isHintVisible = !event.focusState.isFocused &&
                            _tradeQuantity.value.text.isBlank()
                )
            }
            is AddEditTradeEvent.EnteredTradeDate -> {
                _tradeDate.value = tradeDate.value.copy(
                    text = event.value
                )
            }
            is AddEditTradeEvent.SaveTrade -> {
                viewModelScope.launch{
                    try {
                        tradeUseCases.addTrade(
                            Trade(
                                tradeSymb = tradeSymbol.value.text,
                                tradequant= tradeQuantity.value.text,
                                timestamp = System.currentTimeMillis(),
                                //tradestatus = "Long",
                                //color = MaterialTheme.colors.primary.green
                                id = currentTradeId
                            )
                        )
                        _eventFlow.emit(UiEvent.SaveTrade)
                    } catch (e: InvalidTradeException){
                        _eventFlow.emit(
                            UiEvent.ShowSnackbar(
                                message = e.message ?: "Couldn't save trade"
                            )
                        )
                    }
                }
            }
        }
    }
}

Lastly this is the event sealed class, not sure I'm using this correctly but in here for the "EnteredTradeDate" I declare it as a long and I'm not sure this is correct since I'm having trouble passing it from the screen to the viewmodel.

sealed class AddEditTradeEvent {
    data class EnteredSymbol(val value: String): AddEditTradeEvent()
    data class ChangeSymbolFocus(val focusState: FocusState): AddEditTradeEvent()
    data class EnteredQuantity(val value: String): AddEditTradeEvent()
    data class ChangeQuantityFocus(val focusState: FocusState): AddEditTradeEvent()
    data class EnteredTradeDate(val value: Long) : AddEditTradeEvent()
    data class ChangeDateFocus(val focusState: FocusState): AddEditTradeEvent()

    object SaveTrade: AddEditTradeEvent()


}
0 Answers
Related