Skip to content

Commit

Permalink
Merge pull request #66 from PetJournal/feature/post-pet-information
Browse files Browse the repository at this point in the history
Post pet information
  • Loading branch information
N0stalgiaUltra authored Jul 17, 2024
2 parents 6939216 + c7cbc49 commit 694dcf9
Show file tree
Hide file tree
Showing 17 changed files with 200 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import com.soujunior.domain.use_case.auth.SignUpUseCase
import com.soujunior.domain.use_case.guardian.GetGuardianNameUseCase
import com.soujunior.domain.use_case.guardian.GetPetRegistrationWentLive
import com.soujunior.domain.use_case.guardian.SetPetRegistrationWentLive
import com.soujunior.domain.use_case.pet.CreatePetInformationApiUseCase
import com.soujunior.domain.use_case.pet.GetListPetRacesUseCase
import com.soujunior.domain.use_case.pet.GetListPetSizesUseCase
import com.soujunior.domain.use_case.pet.GetPetInformationUseCase
Expand Down Expand Up @@ -105,6 +106,7 @@ val mainModule = module {
factory { SavedStateHandle() }
factory { GetListPetSizesUseCase(get()) }
factory { GetListPetRacesUseCase(get()) }
factory { CreatePetInformationApiUseCase(get()) }

single<AuthService> { get<Retrofit>().create(AuthService::class.java) }
single<GuardianService> { get<Retrofit>().create(GuardianService::class.java) }
Expand Down Expand Up @@ -154,6 +156,6 @@ val mainModule = module {
)
}

viewModel<BirthDateViewModel> { BirthDateViewModelImpl(get(), get(), get()) }
viewModel<BirthDateViewModel> { BirthDateViewModelImpl(get(), get(), get(), get()) }
viewModel<ViewModelRaceSize> { ViewModelRaceSizeImpl(get(), get(), get(), get(), get()) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ abstract class BirthDateViewModel : ViewModel(){
)
abstract fun getPetInformation(id: Long)
abstract fun updatePetInformation()
abstract fun createPetInformation()

abstract fun successPetUpdate(unit: Unit)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,26 @@ import androidx.compose.runtime.setValue
import androidx.lifecycle.viewModelScope
import com.soujunior.domain.model.PetInformationModel
import com.soujunior.domain.repository.ValidationRepository
import com.soujunior.domain.use_case.pet.CreatePetInformationApiUseCase
import com.soujunior.domain.use_case.pet.GetPetInformationUseCase
import com.soujunior.domain.use_case.pet.UpdatePetInformationUseCase
import com.soujunior.petjournal.ui.states.TaskState
import com.soujunior.petjournal.ui.util.Constants.ERROR_MESSAGE
import com.soujunior.petjournal.ui.util.Constants.SUCCESS_MESSAGE
import com.soujunior.petjournal.ui.util.ValidationEvent
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import java.time.LocalDate
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter

class BirthDateViewModelImpl(
val validation: ValidationRepository,
private val getPetInformationUseCase: GetPetInformationUseCase,
private val updatePetInformationUseCase: UpdatePetInformationUseCase
private val updatePetInformationUseCase: UpdatePetInformationUseCase,
private val createPetInformationApiUseCase: CreatePetInformationApiUseCase
) : BirthDateViewModel() {

override var state by mutableStateOf(BirthDateFormState())
Expand All @@ -42,14 +49,14 @@ class BirthDateViewModelImpl(
viewModelScope.launch {
validationEventChannel.send(ValidationEvent.Success)
}
_message.value = "Sucesso"
_message.value = SUCCESS_MESSAGE
}

override fun failed(exception: Throwable?) {
viewModelScope.launch {
validationEventChannel.send(ValidationEvent.Failed)
}
_message.value = "Error"
_message.value = ERROR_MESSAGE
}

override fun onEvent(event: BirthDateFormEvent) {
Expand All @@ -60,6 +67,7 @@ class BirthDateViewModelImpl(
change(petCastration = state.castration)
change(petBirth = state.birth)
}

is BirthDateFormEvent.PetCastration -> change(petCastration = event.petCastration)
}
}
Expand All @@ -76,12 +84,14 @@ class BirthDateViewModelImpl(
state = if (result.success) state.copy(birthError = null)
else state.copy(birthError = result.errorMessage)
}
petCastration == null || petCastration == true || petCastration == false-> {

petCastration == null || petCastration == true || petCastration == false -> {
state = state.copy(castration = petCastration)
val result = validation.validatePetCastration(state.castration)
state = if (result.success) state.copy(castrationError = null)
else state.copy(castrationError = result.errorMessage)
}

idPetInformation != null -> {
state = state.copy(idPetInformation = idPetInformation)
}
Expand All @@ -99,7 +109,6 @@ class BirthDateViewModelImpl(
}

override fun updatePetInformation() {
_taskState.value = TaskState.Loading
viewModelScope.launch {
val petInformation = PetInformationModel(
id = state.idPetInformation ?: 0L,
Expand All @@ -108,13 +117,31 @@ class BirthDateViewModelImpl(
gender = state.gender,
size = state.size,
petRace = state.race,
petAge = state.birth,
guardianId = 1,
castration = state.castration
petAge = formatToIso8601(state.birth),
guardianId = 1
)

val result = updatePetInformationUseCase.execute(petInformation)
result.handleResult(::successPetUpdate, ::failed)
}
}

override fun createPetInformation() {
_taskState.value = TaskState.Loading
viewModelScope.launch {
val petInformation = PetInformationModel(
id = state.idPetInformation ?: 0L,
species = state.specie,
name = state.name,
gender = state.gender,
size = state.size,
petRace = state.race,
petAge = formatToIso8601(state.birth),
guardianId = 1,
castrated = state.castration
)
val result = createPetInformationApiUseCase.execute(petInformation)
result.handleResult(::successPetUpdate, ::failed)
_taskState.value = TaskState.Idle
}
}
Expand All @@ -123,7 +150,18 @@ class BirthDateViewModelImpl(
viewModelScope.launch {
validationEventChannel.send(ValidationEvent.Success)
}
_message.value = "Sucesso"
_message.value = SUCCESS_MESSAGE
}


private fun formatToIso8601(date: String): String {
if (date.isNotEmpty()){
val dateFormatter = DateTimeFormatter.ofPattern("ddMMyyyy")
val dateF = LocalDate.parse(date, dateFormatter)
val localDateTime = dateF.atStartOfDay()
return localDateTime.atOffset(ZoneOffset.UTC).format(DateTimeFormatter.ISO_DATE_TIME)
}
return ""
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.soujunior.petjournal.ui.screens_app.screens_pets.petBirthDateScreen.components

import android.annotation.SuppressLint
import android.content.ContentValues.TAG
import android.util.Log
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
Expand All @@ -19,6 +17,7 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand All @@ -32,18 +31,21 @@ import com.soujunior.petjournal.R
import com.soujunior.petjournal.ui.components.Breadcrumb
import com.soujunior.petjournal.ui.components.Button3
import com.soujunior.petjournal.ui.components.DateInputText
import com.soujunior.petjournal.ui.components.IndeterminateCircularIndicator
import com.soujunior.petjournal.ui.components.NavigationBar
import com.soujunior.petjournal.ui.components.ScaffoldCustom
import com.soujunior.petjournal.ui.components.mask.formatDate
import com.soujunior.petjournal.ui.screens_app.screens_pets.petBirthDateScreen.BirthDateFormEvent
import com.soujunior.petjournal.ui.screens_app.screens_pets.petBirthDateScreen.BirthDateViewModel
import com.soujunior.petjournal.ui.screens_app.screens_pets.petRaceAndSizeScreen.RaceSizeFormEvent
import com.soujunior.petjournal.ui.states.TaskState
import org.koin.androidx.compose.getViewModel

@SuppressLint("StateFlowValueCalledInComposition")
@Composable
fun Screen(idPetInformation: String?, navController: NavController) {
val viewModel: BirthDateViewModel = getViewModel()
val taskState by viewModel.taskState.collectAsState()
var isClearCastration by remember { mutableStateOf(false) }
if (idPetInformation != null) {
viewModel.getPetInformation(idPetInformation.toLong())
Expand All @@ -57,7 +59,9 @@ fun Screen(idPetInformation: String?, navController: NavController) {
showBottomBarNavigation = true,
bottomNavigationBar = { NavigationBar(navController) },
contentToUse = { it ->
Box(modifier = Modifier.padding(it)) {
if (taskState is TaskState.Loading)
IndeterminateCircularIndicator(modifier = Modifier.align(Alignment.CenterHorizontally))
else Box(modifier = Modifier.padding(it)) {
LazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top,
Expand Down Expand Up @@ -153,8 +157,8 @@ fun Screen(idPetInformation: String?, navController: NavController) {
viewModel.state.birth.isNotEmpty() &&
viewModel.state.castration != null
) {
Log.i(TAG, viewModel.state.birth + viewModel.state.castration.toString())
viewModel.updatePetInformation()
viewModel.createPetInformation()
//navController.navigate("pets/birth/$it")
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ class ViewModelRaceSizeImpl(
private val _taskState: MutableStateFlow<TaskState> = MutableStateFlow(TaskState.Idle)
override val taskState: StateFlow<TaskState> get() = _taskState
override val shouldScrollToTop = MutableStateFlow(false)

init {
_taskState.value = TaskState.Loading
}
override fun success(petInformationModel: PetInformationModel) {
state = state.copy(
specie = petInformationModel.species ?: "", idPetInformation = petInformationModel.id,
Expand Down Expand Up @@ -168,11 +170,9 @@ class ViewModelRaceSizeImpl(
}

override fun getPetInformation(id: Long) {
_taskState.value = TaskState.Loading
viewModelScope.launch {
val result = getPetInformationUseCase.execute(id)
result.handleResult(::success, ::failed)
_taskState.value = TaskState.Idle
}
}

Expand Down Expand Up @@ -207,7 +207,6 @@ class ViewModelRaceSizeImpl(
}

override suspend fun requestGetListSizes() {
_taskState.value = TaskState.Loading
if (state.specie == CAT || state.specie == DOG) {
val result = getListPetSizesUseCase.execute(state.specie)
result.handleResult(::successGetPetSizes, ::failed)
Expand All @@ -218,7 +217,7 @@ class ViewModelRaceSizeImpl(
}

override suspend fun requestGetListRaces() {
_taskState.value = TaskState.Loading

if (state.specie == CAT || state.specie == DOG) {
val result = getListPetRacesUseCase.execute(state.specie)
result.handleResult(::successGetPetRaces, ::failed)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,20 @@ import com.soujunior.petjournal.ui.components.Breadcrumb
import com.soujunior.petjournal.ui.components.Button3
import com.soujunior.petjournal.ui.components.DashedInputText
import com.soujunior.petjournal.ui.components.DropDown
import com.soujunior.petjournal.ui.components.IndeterminateCircularIndicator
import com.soujunior.petjournal.ui.components.NavigationBar
import com.soujunior.petjournal.ui.components.ScaffoldCustom
import com.soujunior.petjournal.ui.screens_app.screens_pets.petRaceAndSizeScreen.RaceSizeFormEvent
import com.soujunior.petjournal.ui.screens_app.screens_pets.petRaceAndSizeScreen.ViewModelRaceSize
import com.soujunior.petjournal.ui.states.TaskState
import com.soujunior.petjournal.ui.util.getScreenHeightInch
import org.koin.androidx.compose.getViewModel

@SuppressLint("StateFlowValueCalledInComposition")
@Composable
fun Screen(idPetInformation: String?, navController: NavController) {
val viewModel: ViewModelRaceSize = getViewModel()
val taskState by viewModel.taskState.collectAsState()
val isTextFiledOthersVisible by viewModel.isTextFiledOthersVisible.collectAsState()
if (idPetInformation != null) {
viewModel.getPetInformation(idPetInformation.toLong())
Expand All @@ -71,7 +74,9 @@ fun Screen(idPetInformation: String?, navController: NavController) {
showBottomBarNavigation = true,
bottomNavigationBar = { NavigationBar(navController) },
contentToUse = {
Box(modifier = Modifier.padding(it)) {
if (taskState is TaskState.Loading)
IndeterminateCircularIndicator(modifier = Modifier.align(Alignment.CenterHorizontally))
else Box(modifier = Modifier.padding(it)) {
Image(
painter = painterResource(R.drawable.rastro),
contentDescription = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ val perInformation = PetInformationModel(
petRace = "Akita",
petAge = "12122012",
guardianId = 1,
castration = true
castrated = true
)

val listDogRaces = listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import assertk.assertThat
import assertk.assertions.isFalse
import assertk.assertions.isTrue
import com.soujunior.domain.use_case.base.DataResult
import com.soujunior.domain.use_case.pet.CreatePetInformationApiUseCase
import com.soujunior.domain.use_case.pet.GetPetInformationUseCase
import com.soujunior.domain.use_case.pet.UpdatePetInformationUseCase
import com.soujunior.domain.use_case.util.ValidationRepositoryImpl
Expand Down Expand Up @@ -32,11 +33,12 @@ class PetBirthDateViewModelTest {
private val validation = mockk<ValidationRepositoryImpl>(relaxed = true)
private val getPetInformationUseCase = mockk<GetPetInformationUseCase>(relaxed = true)
private val updatePetInformationUseCase = mockk<UpdatePetInformationUseCase>(relaxed = true)
private val createPetInformationApiUseCase = mockk<CreatePetInformationApiUseCase>(relaxed = true)
@OptIn(ExperimentalCoroutinesApi::class)
@Before
fun setup() {
Dispatchers.setMain(Dispatchers.Unconfined)
viewModelTest = BirthDateViewModelImpl(validation, getPetInformationUseCase, updatePetInformationUseCase)
viewModelTest = BirthDateViewModelImpl(validation, getPetInformationUseCase, updatePetInformationUseCase, createPetInformationApiUseCase)
}

@After
Expand Down Expand Up @@ -296,5 +298,13 @@ class PetBirthDateViewModelTest {
viewModelTest.updatePetInformation()
assertEquals("Error", viewModelTest.message.value)
}
@Test
fun `createPetInformation should call the use case to create pet information in the api`() {

}
coEvery { createPetInformationApiUseCase.execute(any()) } returns DataResult.Success(
Unit
)
viewModelTest.createPetInformation()
assertEquals("Sucesso", viewModelTest.message.value)
}
}
Binary file modified petJournal/buildSrc/build/libs/buildSrc.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package com.soujunior.data.remote
import com.soujunior.domain.model.request.PetRaceItemModel
import com.soujunior.domain.model.request.PetSizeItemModel
import com.soujunior.domain.model.response.GuardianNameResponse
import com.soujunior.domain.model.response.PetInformationResponse
import com.soujunior.domain.network.NetworkResult
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST
import retrofit2.http.Path

interface GuardianService {
Expand All @@ -23,4 +26,10 @@ interface GuardianService {
@Header("Authorization") token: String,
@Path("petSpecie") petSpecie: String
): NetworkResult<List<PetRaceItemModel>>

@POST("api/pet")
suspend fun savePetInformation(
@Header("Authorization") token: String,
@Body petInformationResponse: PetInformationResponse
): NetworkResult<Unit>
}
Loading

0 comments on commit 694dcf9

Please sign in to comment.