11package com.poti.android.presentation.party.create
22
3+ import androidx.core.text.isDigitsOnly
34import androidx.lifecycle.viewModelScope
45import com.poti.android.core.base.BaseViewModel
56import com.poti.android.core.common.state.ApiState
@@ -17,6 +18,9 @@ import com.poti.android.presentation.party.create.model.CreateUiIntent
1718import com.poti.android.presentation.party.create.model.CreateUiState
1819import com.poti.android.presentation.party.create.model.FieldError
1920import com.poti.android.presentation.party.create.model.MemberSettingStatus
21+ import com.poti.android.presentation.party.create.util.isTodayOrAfter
22+ import com.poti.android.presentation.party.create.util.toDashedDate
23+ import com.poti.android.presentation.party.create.util.toDateOrNull
2024import dagger.hilt.android.lifecycle.HiltViewModel
2125import kotlinx.collections.immutable.ImmutableList
2226import kotlinx.collections.immutable.toPersistentList
@@ -48,10 +52,15 @@ class PartyCreateViewModel @Inject constructor(
4852
4953 override fun processIntent (intent : CreateUiIntent ) {
5054 when (intent) {
55+ CreateUiIntent .InitializeScreen -> initializeDeliveryOptions()
56+
57+ CreateUiIntent .CleanScreen -> updateState { CreateUiState () }
58+
5159 CreateUiIntent .OnBackClick -> {
5260 if (uiState.value.isDirty) {
5361 sendEffect(CreateUiEffect .ShowDialog )
5462 } else {
63+ updateState { CreateUiState () }
5564 sendEffect(CreateUiEffect .NavigateToBack )
5665 }
5766 }
@@ -61,11 +70,14 @@ class PartyCreateViewModel @Inject constructor(
6170 sendEffect(CreateUiEffect .NavigateToBack )
6271 }
6372
73+ is CreateUiIntent .OnBackToCreate -> sendEffect(CreateUiEffect .NavigateToBack )
74+
6475 is CreateUiIntent .OnImagesChanged -> {
6576 updateState {
6677 copy(
6778 isDirty = true ,
6879 selectedImages = intent.uris.toPersistentList(),
80+ imageError = if (intent.uris.isNotEmpty()) null else this .imageError,
6981 )
7082 }
7183 }
@@ -158,10 +170,6 @@ class PartyCreateViewModel @Inject constructor(
158170 }
159171
160172 init {
161- viewModelScope.launch {
162- initializeDeliveryOptions()
163- }
164-
165173 viewModelScope.launch {
166174 artistSearchKeywordForDebounce
167175 .debounce(500 )
@@ -183,23 +191,25 @@ class PartyCreateViewModel @Inject constructor(
183191 }
184192 }
185193
186- private suspend fun initializeDeliveryOptions () {
187- getDeliveryOptionsUseCase()
188- .onSuccess { result ->
189- updateState {
190- copy(
191- deliveryOptionsState = ApiState .Success (result.toPersistentList()),
192- editableDeliveryOptions = result.toPersistentList(),
193- selectedDeliveryIds = this .selectedDeliveryIds + result.first().deliveryId,
194- )
195- }
196- }.onFailure { e ->
197- updateState {
198- copy(
199- deliveryOptionsState = ApiState .Failure (e.message ? : " get delivery fail" ),
200- )
194+ private fun initializeDeliveryOptions () {
195+ viewModelScope.launch {
196+ getDeliveryOptionsUseCase()
197+ .onSuccess { result ->
198+ updateState {
199+ copy(
200+ deliveryOptionsState = ApiState .Success (result.toPersistentList()),
201+ editableDeliveryOptions = result.toPersistentList(),
202+ selectedDeliveryIds = this .selectedDeliveryIds + result.first().deliveryId,
203+ )
204+ }
205+ }.onFailure { e ->
206+ updateState {
207+ copy(
208+ deliveryOptionsState = ApiState .Failure (e.message ? : " get delivery fail" ),
209+ )
210+ }
201211 }
202- }
212+ }
203213 }
204214
205215 private fun handleAccountNumberChange (newValue : String ) {
@@ -221,6 +231,7 @@ class PartyCreateViewModel @Inject constructor(
221231 val selectedMemberIds = getAllMemberIdSet(members)
222232
223233 updateState {
234+ val errorBefore = this .memberSettingStatus == MemberSettingStatus .ERROR_NO_PRICE || this .memberSettingStatus == MemberSettingStatus .ERROR_NO_MEMBER
224235 copy(
225236 isDirty = true ,
226237 selectedArtist = newArtist,
@@ -230,6 +241,7 @@ class PartyCreateViewModel @Inject constructor(
230241 editableMemberOptions = members.toPersistentList(),
231242 selectedMemberIds = selectedMemberIds,
232243 memberSettingStatus = MemberSettingStatus .IN_PROGRESS ,
244+ neverShowHint = errorBefore,
233245 )
234246 }
235247 }
@@ -321,6 +333,8 @@ class PartyCreateViewModel @Inject constructor(
321333 }
322334
323335 private fun handleDeadlineChange (newValue : String ) {
336+ if (! newValue.isDigitsOnly() || newValue.length > 8 ) return
337+
324338 updateState {
325339 copy(
326340 isDirty = true ,
@@ -415,10 +429,10 @@ class PartyCreateViewModel @Inject constructor(
415429 }
416430
417431 private fun handleAllMemberSelect () {
418- val newIndices = if (uiState.value.sheetDisplayMemberIndices.isEmpty()) {
419- uiState.value.editableMemberOptions.indices.toSet()
420- } else {
432+ val newIndices = if (uiState.value.sheetDisplayMemberIndices.size == uiState.value.editableMemberOptions.size) {
421433 setOf ()
434+ } else {
435+ uiState.value.editableMemberOptions.indices.toSet()
422436 }
423437
424438 updateState {
@@ -463,7 +477,15 @@ class PartyCreateViewModel @Inject constructor(
463477 val imageError = if (uiState.value.selectedImages.isEmpty()) FieldError .IMAGE_EMPTY_ERROR else null
464478 val artistError = if (uiState.value.selectedArtist == null ) FieldError .ARTIST_EMPTY_ERROR else null
465479 val productError = if (uiState.value.productName.isBlank()) FieldError .PRODUCT_EMPTY_ERROR else null
466- val deadlineError = if (uiState.value.deadline.isBlank()) FieldError .DEADLINE_EMPTY_ERROR else null
480+ val deadlineError = when (val date = uiState.value.deadline.toDateOrNull()) {
481+ null -> if (uiState.value.deadline.isBlank()) {
482+ FieldError .DEADLINE_EMPTY_ERROR
483+ } else {
484+ FieldError .DEADLINE_INVALID_ERROR
485+ }
486+
487+ else -> if (! date.isTodayOrAfter()) FieldError .DEADLINE_PAST_ERROR else null
488+ }
467489 val descriptionError = if (uiState.value.description.isBlank()) FieldError .DESCRIPTION_ERROR else null
468490 val accountNumberError = if (uiState.value.accountNumber.isBlank()) FieldError .ACCOUNT_NUMBER_ERROR else null
469491 val bankError = if (uiState.value.bank.isBlank()) FieldError .BANK_ERROR else null
@@ -493,6 +515,7 @@ class PartyCreateViewModel @Inject constructor(
493515 accountNumberError = accountNumberError,
494516 bankError = bankError,
495517 memberSettingStatus = currentSettingStatus,
518+ neverShowHint = if (hasMemberOptionError) true else this .neverShowHint,
496519 )
497520 }
498521 }
@@ -507,7 +530,7 @@ class PartyCreateViewModel @Inject constructor(
507530 artistId = uiState.value.selectedArtist?.artistId ? : 0L ,
508531 product = uiState.value.productName,
509532 description = uiState.value.description,
510- deadline = uiState.value.deadline,
533+ deadline = uiState.value.deadline.toDashedDate() ,
511534 bank = uiState.value.bank,
512535 accountNumber = uiState.value.accountNumber,
513536 imageUrls = urls,
@@ -540,6 +563,7 @@ class PartyCreateViewModel @Inject constructor(
540563 copy(createPartyState = ApiState .Success (partyId))
541564 }
542565 sendEffect(CreateUiEffect .NavigateToDetail (partyId))
566+ updateState { CreateUiState () }
543567 }
544568 .onFailure {
545569 updateState {
0 commit comments