diff --git a/android/app/src/main/java/com/woowacourse/friendogly/application/di/AppModule.kt b/android/app/src/main/java/com/woowacourse/friendogly/application/di/AppModule.kt index 8621df5d0..8f7ec420a 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/application/di/AppModule.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/application/di/AppModule.kt @@ -6,22 +6,27 @@ import com.woowacourse.friendogly.data.repository.ClubRepositoryImpl import com.woowacourse.friendogly.data.repository.KakaoLoginRepositoryImpl import com.woowacourse.friendogly.data.repository.LocalRepositoryImpl import com.woowacourse.friendogly.data.repository.MemberRepositoryImpl +import com.woowacourse.friendogly.data.repository.PetRepositoryImpl import com.woowacourse.friendogly.data.source.ClubDataSource import com.woowacourse.friendogly.data.source.KakaoLoginDataSource import com.woowacourse.friendogly.data.source.LocalDataSource import com.woowacourse.friendogly.data.source.MemberDataSource +import com.woowacourse.friendogly.data.source.PetDataSource import com.woowacourse.friendogly.domain.repository.ClubRepository import com.woowacourse.friendogly.domain.repository.KakaoLoginRepository import com.woowacourse.friendogly.domain.repository.LocalRepository import com.woowacourse.friendogly.domain.repository.MemberRepository +import com.woowacourse.friendogly.domain.repository.PetRepository import com.woowacourse.friendogly.domain.usecase.DeleteClubUseCase import com.woowacourse.friendogly.domain.usecase.DeleteLocalDataUseCase import com.woowacourse.friendogly.domain.usecase.GetClubMineUseCase import com.woowacourse.friendogly.domain.usecase.GetJwtTokenUseCase +import com.woowacourse.friendogly.domain.usecase.GetPetsMineUseCase import com.woowacourse.friendogly.domain.usecase.KakaoLoginUseCase import com.woowacourse.friendogly.domain.usecase.PostClubParticipationUseCase import com.woowacourse.friendogly.domain.usecase.PostClubUseCase import com.woowacourse.friendogly.domain.usecase.PostMemberUseCase +import com.woowacourse.friendogly.domain.usecase.PostPetUseCase import com.woowacourse.friendogly.domain.usecase.SaveJwtTokenUseCase import com.woowacourse.friendogly.kakao.source.KakaoLoginDataSourceImpl import com.woowacourse.friendogly.local.di.LocalModule @@ -30,6 +35,7 @@ import com.woowacourse.friendogly.remote.api.BaseUrl import com.woowacourse.friendogly.remote.di.RemoteModule import com.woowacourse.friendogly.remote.source.ClubDataSourceImpl import com.woowacourse.friendogly.remote.source.MemberDataSourceImpl +import com.woowacourse.friendogly.remote.source.PetDataSourceImpl class AppModule(context: Context) { private val baseUrl = BaseUrl(BuildConfig.base_url) @@ -48,11 +54,18 @@ class AppModule(context: Context) { localModule = localModule, ) + private val petService = + RemoteModule.createPetService( + baseUrl = baseUrl, + localModule = localModule, + ) + // data source private val clubDataSource: ClubDataSource = ClubDataSourceImpl(service = clubService) private val localDataSource: LocalDataSource = LocalDataSourceImpl(localModule = localModule) private val kakaoLoginDataSource: KakaoLoginDataSource = KakaoLoginDataSourceImpl() private val memberDataSource: MemberDataSource = MemberDataSourceImpl(service = memberService) + private val petDataSource: PetDataSource = PetDataSourceImpl(service = petService) // repository private val clubRepository: ClubRepository = ClubRepositoryImpl(source = clubDataSource) @@ -60,6 +73,7 @@ class AppModule(context: Context) { private val kakaoLoginRepository: KakaoLoginRepository = KakaoLoginRepositoryImpl(dataSource = kakaoLoginDataSource) private val memberRepository: MemberRepository = MemberRepositoryImpl(source = memberDataSource) + private val petRepository: PetRepository = PetRepositoryImpl(source = petDataSource) // use case val kakaoLoginUseCase: KakaoLoginUseCase = KakaoLoginUseCase(repository = kakaoLoginRepository) @@ -73,6 +87,8 @@ class AppModule(context: Context) { val deleteLocalDataUseCase: DeleteLocalDataUseCase = DeleteLocalDataUseCase(repository = localRepository) val postMemberUseCase: PostMemberUseCase = PostMemberUseCase(repository = memberRepository) + val getPetsMineUseCase: GetPetsMineUseCase = GetPetsMineUseCase(repository = petRepository) + val postPetUseCase: PostPetUseCase = PostPetUseCase(repository = petRepository) companion object { private var instance: AppModule? = null diff --git a/android/app/src/main/java/com/woowacourse/friendogly/data/mapper/GenderMapper.kt b/android/app/src/main/java/com/woowacourse/friendogly/data/mapper/GenderMapper.kt new file mode 100644 index 000000000..749e1aea5 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/data/mapper/GenderMapper.kt @@ -0,0 +1,22 @@ +package com.woowacourse.friendogly.data.mapper + +import com.woowacourse.friendogly.data.model.GenderDto +import com.woowacourse.friendogly.domain.model.Gender + +fun GenderDto.toDomain(): Gender { + return when (this) { + GenderDto.MALE -> Gender.MALE + GenderDto.FEMALE -> Gender.FEMALE + GenderDto.MALE_NEUTERED -> Gender.MALE_NEUTERED + GenderDto.FEMALE_NEUTERED -> Gender.FEMALE_NEUTERED + } +} + +fun Gender.toData(): GenderDto { + return when (this) { + Gender.MALE -> GenderDto.MALE + Gender.FEMALE -> GenderDto.FEMALE + Gender.MALE_NEUTERED -> GenderDto.MALE_NEUTERED + Gender.FEMALE_NEUTERED -> GenderDto.FEMALE_NEUTERED + } +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/data/mapper/PetMapper.kt b/android/app/src/main/java/com/woowacourse/friendogly/data/mapper/PetMapper.kt new file mode 100644 index 000000000..723dad858 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/data/mapper/PetMapper.kt @@ -0,0 +1,17 @@ +package com.woowacourse.friendogly.data.mapper + +import com.woowacourse.friendogly.data.model.PetDto +import com.woowacourse.friendogly.domain.model.Pet + +fun PetDto.toDomain(): Pet { + return Pet( + id = this.id, + memberId = this.memberId, + name = this.name, + description = this.description, + birthDate = this.birthDate, + sizeType = this.sizeType.toDomain(), + gender = this.gender.toDomain(), + imageUrl = this.imageUrl, + ) +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/data/mapper/PetsMapper.kt b/android/app/src/main/java/com/woowacourse/friendogly/data/mapper/PetsMapper.kt new file mode 100644 index 000000000..905ee1570 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/data/mapper/PetsMapper.kt @@ -0,0 +1,13 @@ +package com.woowacourse.friendogly.data.mapper + +import com.woowacourse.friendogly.data.model.PetsDto +import com.woowacourse.friendogly.domain.model.Pets + +fun PetsDto.toDomain(): Pets { + return Pets( + contents = + this.contents.map { petResponse -> + petResponse.toDomain() + }, + ) +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/data/mapper/SizeTypeMapper.kt b/android/app/src/main/java/com/woowacourse/friendogly/data/mapper/SizeTypeMapper.kt new file mode 100644 index 000000000..b6482cea4 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/data/mapper/SizeTypeMapper.kt @@ -0,0 +1,20 @@ +package com.woowacourse.friendogly.data.mapper + +import com.woowacourse.friendogly.data.model.SizeTypeDto +import com.woowacourse.friendogly.domain.model.SizeType + +fun SizeTypeDto.toDomain(): SizeType { + return when (this) { + SizeTypeDto.SMALL -> SizeType.SMALL + SizeTypeDto.MEDIUM -> SizeType.MEDIUM + SizeTypeDto.LARGE -> SizeType.LARGE + } +} + +fun SizeType.toData(): SizeTypeDto { + return when (this) { + SizeType.SMALL -> SizeTypeDto.SMALL + SizeType.MEDIUM -> SizeTypeDto.MEDIUM + SizeType.LARGE -> SizeTypeDto.LARGE + } +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/data/model/GenderDto.kt b/android/app/src/main/java/com/woowacourse/friendogly/data/model/GenderDto.kt new file mode 100644 index 000000000..d4c70cdf3 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/data/model/GenderDto.kt @@ -0,0 +1,8 @@ +package com.woowacourse.friendogly.data.model + +enum class GenderDto { + MALE, + FEMALE, + MALE_NEUTERED, + FEMALE_NEUTERED, +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/data/model/PetDto.kt b/android/app/src/main/java/com/woowacourse/friendogly/data/model/PetDto.kt new file mode 100644 index 000000000..5a42ec42a --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/data/model/PetDto.kt @@ -0,0 +1,17 @@ +package com.woowacourse.friendogly.data.model + +import com.woowacourse.friendogly.remote.util.LocalDateSerializer +import kotlinx.datetime.LocalDate +import kotlinx.serialization.Serializable + +data class PetDto( + val id: Long, + val memberId: Long, + val name: String, + val description: String, + @Serializable(with = LocalDateSerializer::class) + val birthDate: LocalDate, + val sizeType: SizeTypeDto, + val gender: GenderDto, + val imageUrl: String, +) diff --git a/android/app/src/main/java/com/woowacourse/friendogly/data/model/PetsDto.kt b/android/app/src/main/java/com/woowacourse/friendogly/data/model/PetsDto.kt new file mode 100644 index 000000000..d6376b322 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/data/model/PetsDto.kt @@ -0,0 +1,5 @@ +package com.woowacourse.friendogly.data.model + +data class PetsDto( + val contents: List, +) diff --git a/android/app/src/main/java/com/woowacourse/friendogly/data/model/SizeTypeDto.kt b/android/app/src/main/java/com/woowacourse/friendogly/data/model/SizeTypeDto.kt new file mode 100644 index 000000000..ba9584f48 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/data/model/SizeTypeDto.kt @@ -0,0 +1,7 @@ +package com.woowacourse.friendogly.data.model + +enum class SizeTypeDto { + SMALL, + MEDIUM, + LARGE, +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/data/repository/PetRepositoryImpl.kt b/android/app/src/main/java/com/woowacourse/friendogly/data/repository/PetRepositoryImpl.kt new file mode 100644 index 000000000..ccca48b3b --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/data/repository/PetRepositoryImpl.kt @@ -0,0 +1,32 @@ +package com.woowacourse.friendogly.data.repository + +import com.woowacourse.friendogly.data.mapper.toData +import com.woowacourse.friendogly.data.mapper.toDomain +import com.woowacourse.friendogly.data.source.PetDataSource +import com.woowacourse.friendogly.domain.model.Gender +import com.woowacourse.friendogly.domain.model.Pet +import com.woowacourse.friendogly.domain.model.SizeType +import com.woowacourse.friendogly.domain.repository.PetRepository +import kotlinx.datetime.LocalDate + +class PetRepositoryImpl(private val source: PetDataSource) : PetRepository { + override suspend fun getPetsMine(): Result> = + source.getPetsMine().mapCatching { result -> result.map { petDto -> petDto.toDomain() } } + + override suspend fun postPet( + name: String, + description: String, + birthday: LocalDate, + sizeType: SizeType, + gender: Gender, + imageUrl: String, + ): Result = + source.postPet( + name = name, + description = description, + birthday = birthday, + sizeType = sizeType.toData(), + gender = gender.toData(), + imageUrl = imageUrl, + ).mapCatching { result -> result.toDomain() } +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/data/source/PetDataSource.kt b/android/app/src/main/java/com/woowacourse/friendogly/data/source/PetDataSource.kt new file mode 100644 index 000000000..aade33aff --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/data/source/PetDataSource.kt @@ -0,0 +1,19 @@ +package com.woowacourse.friendogly.data.source + +import com.woowacourse.friendogly.data.model.GenderDto +import com.woowacourse.friendogly.data.model.PetDto +import com.woowacourse.friendogly.data.model.SizeTypeDto +import kotlinx.datetime.LocalDate + +interface PetDataSource { + suspend fun getPetsMine(): Result> + + suspend fun postPet( + name: String, + description: String, + birthday: LocalDate, + sizeType: SizeTypeDto, + gender: GenderDto, + imageUrl: String, + ): Result +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/domain/model/Gender.kt b/android/app/src/main/java/com/woowacourse/friendogly/domain/model/Gender.kt new file mode 100644 index 000000000..de02244d4 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/domain/model/Gender.kt @@ -0,0 +1,8 @@ +package com.woowacourse.friendogly.domain.model + +enum class Gender { + MALE, + FEMALE, + MALE_NEUTERED, + FEMALE_NEUTERED, +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/domain/model/Pet.kt b/android/app/src/main/java/com/woowacourse/friendogly/domain/model/Pet.kt new file mode 100644 index 000000000..ff7aeb852 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/domain/model/Pet.kt @@ -0,0 +1,14 @@ +package com.woowacourse.friendogly.domain.model + +import kotlinx.datetime.LocalDate + +data class Pet( + val id: Long, + val memberId: Long, + val name: String, + val description: String, + val birthDate: LocalDate, + val sizeType: SizeType, + val gender: Gender, + val imageUrl: String, +) diff --git a/android/app/src/main/java/com/woowacourse/friendogly/domain/model/Pets.kt b/android/app/src/main/java/com/woowacourse/friendogly/domain/model/Pets.kt new file mode 100644 index 000000000..e9beac418 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/domain/model/Pets.kt @@ -0,0 +1,5 @@ +package com.woowacourse.friendogly.domain.model + +data class Pets( + val contents: List, +) diff --git a/android/app/src/main/java/com/woowacourse/friendogly/domain/model/SizeType.kt b/android/app/src/main/java/com/woowacourse/friendogly/domain/model/SizeType.kt new file mode 100644 index 000000000..04b574652 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/domain/model/SizeType.kt @@ -0,0 +1,7 @@ +package com.woowacourse.friendogly.domain.model + +enum class SizeType { + SMALL, + MEDIUM, + LARGE, +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/domain/repository/PetRepository.kt b/android/app/src/main/java/com/woowacourse/friendogly/domain/repository/PetRepository.kt new file mode 100644 index 000000000..14e2c0bca --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/domain/repository/PetRepository.kt @@ -0,0 +1,19 @@ +package com.woowacourse.friendogly.domain.repository + +import com.woowacourse.friendogly.domain.model.Gender +import com.woowacourse.friendogly.domain.model.Pet +import com.woowacourse.friendogly.domain.model.SizeType +import kotlinx.datetime.LocalDate + +interface PetRepository { + suspend fun getPetsMine(): Result> + + suspend fun postPet( + name: String, + description: String, + birthday: LocalDate, + sizeType: SizeType, + gender: Gender, + imageUrl: String, + ): Result +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/domain/usecase/GetPetsMineUseCase.kt b/android/app/src/main/java/com/woowacourse/friendogly/domain/usecase/GetPetsMineUseCase.kt new file mode 100644 index 000000000..949f91ce5 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/domain/usecase/GetPetsMineUseCase.kt @@ -0,0 +1,10 @@ +package com.woowacourse.friendogly.domain.usecase + +import com.woowacourse.friendogly.domain.model.Pet +import com.woowacourse.friendogly.domain.repository.PetRepository + +class GetPetsMineUseCase( + private val repository: PetRepository, +) { + suspend operator fun invoke(): Result> = repository.getPetsMine() +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/domain/usecase/PostPetUseCase.kt b/android/app/src/main/java/com/woowacourse/friendogly/domain/usecase/PostPetUseCase.kt new file mode 100644 index 000000000..44e8df627 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/domain/usecase/PostPetUseCase.kt @@ -0,0 +1,28 @@ +package com.woowacourse.friendogly.domain.usecase + +import com.woowacourse.friendogly.domain.model.Gender +import com.woowacourse.friendogly.domain.model.Pet +import com.woowacourse.friendogly.domain.model.SizeType +import com.woowacourse.friendogly.domain.repository.PetRepository +import kotlinx.datetime.LocalDate + +class PostPetUseCase( + private val repository: PetRepository, +) { + suspend operator fun invoke( + name: String, + description: String, + birthday: LocalDate, + sizeType: SizeType, + gender: Gender, + imageUrl: String, + ): Result = + repository.postPet( + name = name, + description = description, + birthday = birthday, + sizeType = sizeType, + gender = gender, + imageUrl = imageUrl, + ) +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageFragment.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageFragment.kt index 6e8b25299..a3c6777fa 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageFragment.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageFragment.kt @@ -2,15 +2,18 @@ package com.woowacourse.friendogly.presentation.ui.mypage import androidx.fragment.app.viewModels import com.woowacourse.friendogly.R +import com.woowacourse.friendogly.application.di.AppModule import com.woowacourse.friendogly.databinding.FragmentMyPageBinding import com.woowacourse.friendogly.presentation.base.BaseFragment import com.woowacourse.friendogly.presentation.base.observeEvent -import com.woowacourse.friendogly.presentation.ui.mypage.adapter.DogProfileAdapter +import com.woowacourse.friendogly.presentation.ui.mypage.adapter.PetProfileAdapter class MyPageFragment : BaseFragment(R.layout.fragment_my_page) { - private val viewModel: MyPageViewModel by viewModels() + private val viewModel: MyPageViewModel by viewModels { + MyPageViewModel.factory(getPetsMineUseCase = AppModule.getInstance().getPetsMineUseCase) + } - private val adapter: DogProfileAdapter by lazy { DogProfileAdapter(viewModel) } + private val adapter: PetProfileAdapter by lazy { PetProfileAdapter(viewModel) } override fun initViewCreated() { initDataBinding() @@ -31,7 +34,11 @@ class MyPageFragment : BaseFragment(R.layout.fragment_my_ when (action) { is MyPageNavigationAction.NavigateToSetting -> TODO() is MyPageNavigationAction.NavigateToDogDetail -> - navigate(MyPageFragmentDirections.actionMyPageFragmentToDogDetailFragment(action.id)) + navigate( + MyPageFragmentDirections.actionMyPageFragmentToDogDetailFragment( + action.id, + ), + ) is MyPageNavigationAction.NavigateToDogRegister -> navigate( @@ -43,7 +50,12 @@ class MyPageFragment : BaseFragment(R.layout.fragment_my_ } viewModel.uiState.observe(viewLifecycleOwner) { uiState -> - adapter.submitList(uiState.dogs) + adapter.submitList(uiState.pets) } } + + override fun onResume() { + super.onResume() + viewModel.fetchPetMine() + } } diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageUiState.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageUiState.kt index 04d274ce3..4282ad5ed 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageUiState.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageUiState.kt @@ -1,12 +1,13 @@ package com.woowacourse.friendogly.presentation.ui.mypage +import com.woowacourse.friendogly.domain.model.Pet import java.time.LocalDate data class MyPageUiState( val nickname: String = "", val email: String = "", val profilePath: String? = null, - val dogs: List = emptyList(), + val pets: List = emptyList(), ) // TODO 더미 데이터 모델 diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageViewModel.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageViewModel.kt index e339e86d7..7d5d5a5f7 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageViewModel.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageViewModel.kt @@ -2,12 +2,19 @@ package com.woowacourse.friendogly.presentation.ui.mypage import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope +import com.woowacourse.friendogly.domain.usecase.GetPetsMineUseCase import com.woowacourse.friendogly.presentation.base.BaseViewModel +import com.woowacourse.friendogly.presentation.base.BaseViewModelFactory import com.woowacourse.friendogly.presentation.base.Event import com.woowacourse.friendogly.presentation.base.emit +import kotlinx.coroutines.launch import java.time.LocalDate -class MyPageViewModel : BaseViewModel(), MyPageActionHandler { +class MyPageViewModel( + private val getPetsMineUseCase: GetPetsMineUseCase, +) : BaseViewModel(), MyPageActionHandler { private val _uiState: MutableLiveData = MutableLiveData(MyPageUiState()) val uiState: LiveData get() = _uiState @@ -16,18 +23,24 @@ class MyPageViewModel : BaseViewModel(), MyPageActionHandler { val navigateAction: LiveData> get() = _navigateAction init { - fetchDummy() + fetchPetMine() } - private fun fetchDummy() { + fun fetchPetMine() { val state = _uiState.value ?: return - _uiState.value = - state.copy( - nickname = "손흥민", - email = "tottenham@gmail.com", - dogs = dogs, - ) + viewModelScope.launch { + getPetsMineUseCase().onSuccess { pets -> + _uiState.value = + state.copy( + nickname = "손흥민", + email = "tottenham@gmail.com", + pets = pets, + ) + }.onFailure { + // TODO 예외 처리 + } + } } fun navigateToDogRegister() { @@ -77,5 +90,13 @@ class MyPageViewModel : BaseViewModel(), MyPageActionHandler { image = "https://petsstore.co.kr/web/product/big/202401/dc7c18de083f0ab58060b4ec82321028.jpg", ), ) + + fun factory(getPetsMineUseCase: GetPetsMineUseCase): ViewModelProvider.Factory { + return BaseViewModelFactory { _ -> + MyPageViewModel( + getPetsMineUseCase = getPetsMineUseCase, + ) + } + } } } diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/adapter/DogProfileAdapter.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/adapter/PetProfileAdapter.kt similarity index 62% rename from android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/adapter/DogProfileAdapter.kt rename to android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/adapter/PetProfileAdapter.kt index a5f7bb118..bcca4adda 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/adapter/DogProfileAdapter.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/adapter/PetProfileAdapter.kt @@ -5,13 +5,13 @@ import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView -import com.woowacourse.friendogly.databinding.ItemDogBinding -import com.woowacourse.friendogly.presentation.ui.mypage.Dog +import com.woowacourse.friendogly.databinding.ItemPetBinding +import com.woowacourse.friendogly.domain.model.Pet import com.woowacourse.friendogly.presentation.ui.mypage.MyPageActionHandler -class DogProfileAdapter( +class PetProfileAdapter( private val actionHandler: MyPageActionHandler, -) : ListAdapter(DogItemDiffCallback) { +) : ListAdapter(PetItemDiffCallback) { init { setHasStableIds(true) } @@ -21,7 +21,7 @@ class DogProfileAdapter( viewType: Int, ): ViewHolder { val inflater = LayoutInflater.from(parent.context) - val binding = ItemDogBinding.inflate(inflater, parent, false) + val binding = ItemPetBinding.inflate(inflater, parent, false) binding.actionHandler = actionHandler return ViewHolder(binding) } @@ -33,21 +33,21 @@ class DogProfileAdapter( holder.bind(getItem(position)) } - class ViewHolder(private val binding: ItemDogBinding) : RecyclerView.ViewHolder(binding.root) { - fun bind(item: Dog) { - binding.dog = item + class ViewHolder(private val binding: ItemPetBinding) : RecyclerView.ViewHolder(binding.root) { + fun bind(item: Pet) { + binding.pet = item } } - internal object DogItemDiffCallback : DiffUtil.ItemCallback() { + companion object PetItemDiffCallback : DiffUtil.ItemCallback() { override fun areItemsTheSame( - oldItem: Dog, - newItem: Dog, - ): Boolean = oldItem.name == newItem.name + oldItem: Pet, + newItem: Pet, + ): Boolean = oldItem.id == newItem.id override fun areContentsTheSame( - oldItem: Dog, - newItem: Dog, + oldItem: Pet, + newItem: Pet, ): Boolean = oldItem == newItem } } diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/registerdog/RegisterDogFragment.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/registerdog/RegisterDogFragment.kt index 30f477e40..510d8a020 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/registerdog/RegisterDogFragment.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/registerdog/RegisterDogFragment.kt @@ -13,6 +13,7 @@ import com.canhub.cropper.CropImageContract import com.canhub.cropper.CropImageContractOptions import com.canhub.cropper.CropImageOptions import com.woowacourse.friendogly.R +import com.woowacourse.friendogly.application.di.AppModule import com.woowacourse.friendogly.databinding.FragmentRegisterDogBinding import com.woowacourse.friendogly.presentation.base.BaseFragment import com.woowacourse.friendogly.presentation.base.observeEvent @@ -28,7 +29,9 @@ import java.util.Date class RegisterDogFragment : BaseFragment(R.layout.fragment_register_dog) { - private val viewModel: RegisterDogViewModel by viewModels() + private val viewModel: RegisterDogViewModel by viewModels { + RegisterDogViewModel.factory(postPetUseCase = AppModule.getInstance().postPetUseCase) + } private val navController by lazy { findNavController() } private lateinit var imagePickerLauncher: ActivityResultLauncher diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/registerdog/RegisterDogUiState.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/registerdog/RegisterDogUiState.kt index 3c1d5772f..57eaadb12 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/registerdog/RegisterDogUiState.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/registerdog/RegisterDogUiState.kt @@ -1,5 +1,7 @@ package com.woowacourse.friendogly.presentation.ui.registerdog +import com.woowacourse.friendogly.domain.model.Gender +import com.woowacourse.friendogly.domain.model.SizeType import okhttp3.MultipartBody import java.time.LocalDate @@ -14,9 +16,31 @@ enum class DogSize(val title: String) { SMALL("소형견"), MEDIUM("중형견"), LARGE("대형견"), + ; + + fun toSizeType(): SizeType { + return when (this) { + SMALL -> SizeType.SMALL + MEDIUM -> SizeType.MEDIUM + LARGE -> SizeType.LARGE + } + } } enum class DogGender(val title: String) { MAIL("수컷"), FEMALE("암컷"), + ; + + fun toGender(neutering: Boolean): Gender { + return when (this) { + MAIL -> { + if (neutering) Gender.MALE_NEUTERED else Gender.MALE + } + + FEMALE -> { + if (neutering) Gender.FEMALE_NEUTERED else Gender.FEMALE + } + } + } } diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/registerdog/RegisterDogViewModel.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/registerdog/RegisterDogViewModel.kt index 62b5b8d10..c3fa18f12 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/registerdog/RegisterDogViewModel.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/registerdog/RegisterDogViewModel.kt @@ -4,19 +4,26 @@ import android.graphics.Bitmap import androidx.lifecycle.LiveData import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope +import com.woowacourse.friendogly.domain.usecase.PostPetUseCase import com.woowacourse.friendogly.presentation.base.BaseViewModel +import com.woowacourse.friendogly.presentation.base.BaseViewModelFactory import com.woowacourse.friendogly.presentation.base.Event import com.woowacourse.friendogly.presentation.base.emit import com.woowacourse.friendogly.presentation.utils.addSourceList +import kotlinx.coroutines.launch +import kotlinx.datetime.LocalDate import okhttp3.MultipartBody -class RegisterDogViewModel : BaseViewModel() { +class RegisterDogViewModel( + private val postPetUseCase: PostPetUseCase, +) : BaseViewModel() { private val _uiState: MutableLiveData = MutableLiveData(RegisterDogUiState()) val uiState: LiveData get() = _uiState - private val _profileImage: MutableLiveData = - MutableLiveData(null) + private val _profileImage: MutableLiveData = MutableLiveData(null) val profileImage: LiveData get() = _profileImage val dogName = MutableLiveData("") @@ -93,7 +100,33 @@ class RegisterDogViewModel : BaseViewModel() { fun registerDog() { if (isProfileComplete.value == true) { - _navigateAction.emit(RegisterDogNavigationAction.NavigateToMyPage) + viewModelScope.launch { + val state = uiState.value ?: return@launch + val name = dogName.value ?: return@launch + val description = dogDescription.value ?: return@launch + val birthday = LocalDate(state.dogBirthdayYear, state.dogBirthdayMonth, 1) + + postPetUseCase( + name = name, + description = description, + birthday = birthday, + sizeType = dogSize.toSizeType(), + gender = dogGender.toGender(state.neutering), + imageUrl = "https://docs.api.com", + ).onSuccess { + _navigateAction.emit(RegisterDogNavigationAction.NavigateToMyPage) + }.onFailure { + // TODO 예외 처리 + } + } + } + } + + companion object { + fun factory(postPetUseCase: PostPetUseCase): ViewModelProvider.Factory { + return BaseViewModelFactory { _ -> + RegisterDogViewModel(postPetUseCase = postPetUseCase) + } } } } diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/api/ApiClient.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/api/ApiClient.kt index e11a326f6..294437fff 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/remote/api/ApiClient.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/api/ApiClient.kt @@ -13,7 +13,11 @@ class ApiClient { const val POST_MEMBER = BASE_URL } - object Pet + object Pet { + private const val BASE_URL = "/pets" + const val GET_PETS_MINE = "$BASE_URL/mine" + const val POST_PET = BASE_URL + } object Club { private const val BASE_URL = "/clubs" diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/api/MemberService.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/api/MemberService.kt index 945d28e46..883902773 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/remote/api/MemberService.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/api/MemberService.kt @@ -1,6 +1,7 @@ package com.woowacourse.friendogly.remote.api import com.woowacourse.friendogly.remote.model.request.PostMembersRequest +import com.woowacourse.friendogly.remote.model.response.BaseResponse import com.woowacourse.friendogly.remote.model.response.MemberResponse import retrofit2.http.Body import retrofit2.http.POST @@ -9,5 +10,5 @@ interface MemberService { @POST(ApiClient.Member.POST_MEMBER) suspend fun postMember( @Body body: PostMembersRequest, - ): MemberResponse + ): BaseResponse } diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/api/PetService.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/api/PetService.kt new file mode 100644 index 000000000..861dec16b --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/api/PetService.kt @@ -0,0 +1,18 @@ +package com.woowacourse.friendogly.remote.api + +import com.woowacourse.friendogly.remote.model.request.PostPetRequest +import com.woowacourse.friendogly.remote.model.response.BaseResponse +import com.woowacourse.friendogly.remote.model.response.PetResponse +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.POST + +interface PetService { + @POST(ApiClient.Pet.POST_PET) + suspend fun postPet( + @Body body: PostPetRequest, + ): BaseResponse + + @GET(ApiClient.Pet.GET_PETS_MINE) + suspend fun getPetsMine(): BaseResponse> +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/di/RemoteModule.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/di/RemoteModule.kt index 93825e0f7..4296269be 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/remote/di/RemoteModule.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/di/RemoteModule.kt @@ -5,6 +5,7 @@ import com.woowacourse.friendogly.local.di.LocalModule import com.woowacourse.friendogly.remote.api.BaseUrl import com.woowacourse.friendogly.remote.api.ClubService import com.woowacourse.friendogly.remote.api.MemberService +import com.woowacourse.friendogly.remote.api.PetService import com.woowacourse.friendogly.remote.interceptor.AuthorizationInterceptor import com.woowacourse.friendogly.remote.interceptor.ErrorResponseInterceptor import kotlinx.serialization.json.Json @@ -35,6 +36,16 @@ object RemoteModule { ).create(MemberService::class.java) } + fun createPetService( + baseUrl: BaseUrl, + localModule: LocalModule, + ): PetService { + return createRetrofit( + baseUrl, + localModule, + ).create(PetService::class.java) + } + private val json = Json { ignoreUnknownKeys = true diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/mapper/GenderDtoMapper.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/mapper/GenderDtoMapper.kt new file mode 100644 index 000000000..726846091 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/mapper/GenderDtoMapper.kt @@ -0,0 +1,23 @@ +package com.woowacourse.friendogly.remote.mapper + +import com.woowacourse.friendogly.data.model.GenderDto +import com.woowacourse.friendogly.remote.model.request.GenderRequest +import com.woowacourse.friendogly.remote.model.response.GenderResponse + +fun GenderResponse.toData(): GenderDto { + return when (this) { + GenderResponse.MALE -> GenderDto.MALE + GenderResponse.FEMALE -> GenderDto.FEMALE + GenderResponse.MALE_NEUTERED -> GenderDto.MALE_NEUTERED + GenderResponse.FEMALE_NEUTERED -> GenderDto.FEMALE_NEUTERED + } +} + +fun GenderDto.toRemote(): GenderRequest { + return when (this) { + GenderDto.MALE -> GenderRequest.MALE + GenderDto.FEMALE -> GenderRequest.FEMALE + GenderDto.MALE_NEUTERED -> GenderRequest.MALE_NEUTERED + GenderDto.FEMALE_NEUTERED -> GenderRequest.FEMALE_NEUTERED + } +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/mapper/PetDtoMapper.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/mapper/PetDtoMapper.kt new file mode 100644 index 000000000..80facec80 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/mapper/PetDtoMapper.kt @@ -0,0 +1,17 @@ +package com.woowacourse.friendogly.remote.mapper + +import com.woowacourse.friendogly.data.model.PetDto +import com.woowacourse.friendogly.remote.model.response.PetResponse + +fun PetResponse.toData(): PetDto { + return PetDto( + id = this.id, + memberId = this.memberId, + name = this.name, + description = this.description, + birthDate = this.birthDate, + sizeType = this.sizeType.toData(), + gender = this.gender.toData(), + imageUrl = this.imageUrl, + ) +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/mapper/PetsDtoMapper.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/mapper/PetsDtoMapper.kt new file mode 100644 index 000000000..5ecea0a7b --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/mapper/PetsDtoMapper.kt @@ -0,0 +1,13 @@ +package com.woowacourse.friendogly.remote.mapper + +import com.woowacourse.friendogly.data.model.PetsDto +import com.woowacourse.friendogly.remote.model.response.PetsResponse + +fun PetsResponse.toData(): PetsDto { + return PetsDto( + contents = + this.contents.map { petResponse -> + petResponse.toData() + }, + ) +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/mapper/SizeTypeDtoMapper.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/mapper/SizeTypeDtoMapper.kt new file mode 100644 index 000000000..93ccc0e84 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/mapper/SizeTypeDtoMapper.kt @@ -0,0 +1,21 @@ +package com.woowacourse.friendogly.remote.mapper + +import com.woowacourse.friendogly.data.model.SizeTypeDto +import com.woowacourse.friendogly.remote.model.request.SizeTypeRequest +import com.woowacourse.friendogly.remote.model.response.SizeTypeResponse + +fun SizeTypeResponse.toData(): SizeTypeDto { + return when (this) { + SizeTypeResponse.SMALL -> SizeTypeDto.SMALL + SizeTypeResponse.MEDIUM -> SizeTypeDto.MEDIUM + SizeTypeResponse.LARGE -> SizeTypeDto.LARGE + } +} + +fun SizeTypeDto.toRemote(): SizeTypeRequest { + return when (this) { + SizeTypeDto.SMALL -> SizeTypeRequest.SMALL + SizeTypeDto.MEDIUM -> SizeTypeRequest.MEDIUM + SizeTypeDto.LARGE -> SizeTypeRequest.LARGE + } +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/model/request/GenderRequest.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/request/GenderRequest.kt new file mode 100644 index 000000000..3f7fc7a37 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/request/GenderRequest.kt @@ -0,0 +1,19 @@ +package com.woowacourse.friendogly.remote.model.request + +import com.google.gson.annotations.SerializedName +import kotlinx.serialization.Serializable + +@Serializable +enum class GenderRequest { + @SerializedName("MALE") + MALE, + + @SerializedName("FEMALE") + FEMALE, + + @SerializedName("MALE_NEUTERED") + MALE_NEUTERED, + + @SerializedName("FEMALE_NEUTERED") + FEMALE_NEUTERED, +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/model/request/PostPetRequest.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/request/PostPetRequest.kt new file mode 100644 index 000000000..a1b94a4b5 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/request/PostPetRequest.kt @@ -0,0 +1,16 @@ +package com.woowacourse.friendogly.remote.model.request + +import com.woowacourse.friendogly.remote.util.LocalDateSerializer +import kotlinx.datetime.LocalDate +import kotlinx.serialization.Serializable + +@Serializable +data class PostPetRequest( + val name: String, + val description: String, + @Serializable(with = LocalDateSerializer::class) + val birthDate: LocalDate, + val sizeType: SizeTypeRequest, + val gender: GenderRequest, + val imageUrl: String, +) diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/model/request/SizeTypeRequest.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/request/SizeTypeRequest.kt new file mode 100644 index 000000000..992507fa4 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/request/SizeTypeRequest.kt @@ -0,0 +1,16 @@ +package com.woowacourse.friendogly.remote.model.request + +import com.google.gson.annotations.SerializedName +import kotlinx.serialization.Serializable + +@Serializable +enum class SizeTypeRequest { + @SerializedName("SMALL") + SMALL, + + @SerializedName("MEDIUM") + MEDIUM, + + @SerializedName("LARGE") + LARGE, +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/BaseResponse.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/BaseResponse.kt index d19a1df04..a48280fd0 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/BaseResponse.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/BaseResponse.kt @@ -4,6 +4,6 @@ import kotlinx.serialization.Serializable @Serializable data class BaseResponse( + val isSuccess: Boolean, val data: T, - val errorCode: String, ) diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/GenderResponse.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/GenderResponse.kt new file mode 100644 index 000000000..162cb6259 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/GenderResponse.kt @@ -0,0 +1,11 @@ +package com.woowacourse.friendogly.remote.model.response + +import kotlinx.serialization.Serializable + +@Serializable +enum class GenderResponse { + MALE, + FEMALE, + MALE_NEUTERED, + FEMALE_NEUTERED, +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/PetResponse.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/PetResponse.kt new file mode 100644 index 000000000..054234836 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/PetResponse.kt @@ -0,0 +1,18 @@ +package com.woowacourse.friendogly.remote.model.response + +import com.woowacourse.friendogly.remote.util.LocalDateSerializer +import kotlinx.datetime.LocalDate +import kotlinx.serialization.Serializable + +@Serializable +data class PetResponse( + val id: Long, + val memberId: Long, + val name: String, + val description: String, + @Serializable(with = LocalDateSerializer::class) + val birthDate: LocalDate, + val sizeType: SizeTypeResponse, + val gender: GenderResponse, + val imageUrl: String, +) diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/PetsResponse.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/PetsResponse.kt new file mode 100644 index 000000000..79157b9a5 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/PetsResponse.kt @@ -0,0 +1,8 @@ +package com.woowacourse.friendogly.remote.model.response + +import kotlinx.serialization.Serializable + +@Serializable +data class PetsResponse( + val contents: List, +) diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/SizeTypeResponse.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/SizeTypeResponse.kt new file mode 100644 index 000000000..09535c511 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/model/response/SizeTypeResponse.kt @@ -0,0 +1,10 @@ +package com.woowacourse.friendogly.remote.model.response + +import kotlinx.serialization.Serializable + +@Serializable +enum class SizeTypeResponse { + SMALL, + MEDIUM, + LARGE, +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/source/MemberDataSourceImpl.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/source/MemberDataSourceImpl.kt index d2e595173..f2cd52a51 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/remote/source/MemberDataSourceImpl.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/source/MemberDataSourceImpl.kt @@ -15,6 +15,6 @@ class MemberDataSourceImpl( ): Result = runCatching { val body = PostMembersRequest(name = name, email = email) - service.postMember(body = body).toData() + service.postMember(body = body).data.toData() } } diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/source/PetDataSourceImpl.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/source/PetDataSourceImpl.kt new file mode 100644 index 000000000..037895a20 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/source/PetDataSourceImpl.kt @@ -0,0 +1,40 @@ +package com.woowacourse.friendogly.remote.source + +import com.woowacourse.friendogly.data.model.GenderDto +import com.woowacourse.friendogly.data.model.PetDto +import com.woowacourse.friendogly.data.model.SizeTypeDto +import com.woowacourse.friendogly.data.source.PetDataSource +import com.woowacourse.friendogly.remote.api.PetService +import com.woowacourse.friendogly.remote.mapper.toData +import com.woowacourse.friendogly.remote.mapper.toRemote +import com.woowacourse.friendogly.remote.model.request.PostPetRequest +import kotlinx.datetime.LocalDate + +class PetDataSourceImpl(private val service: PetService) : PetDataSource { + override suspend fun getPetsMine(): Result> = + runCatching { + service.getPetsMine().data.map { petResponse -> petResponse.toData() } + } + + override suspend fun postPet( + name: String, + description: String, + birthday: LocalDate, + sizeType: SizeTypeDto, + gender: GenderDto, + imageUrl: String, + ): Result = + runCatching { + val body = + PostPetRequest( + name = name, + description = description, + birthDate = birthday, + sizeType = sizeType.toRemote(), + gender = gender.toRemote(), + imageUrl = imageUrl, + ) + + service.postPet(body = body).data.toData() + } +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/remote/util/LocalDateSerializer.kt b/android/app/src/main/java/com/woowacourse/friendogly/remote/util/LocalDateSerializer.kt new file mode 100644 index 000000000..2fc5cf995 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/remote/util/LocalDateSerializer.kt @@ -0,0 +1,27 @@ +package com.woowacourse.friendogly.remote.util + +import kotlinx.datetime.LocalDate +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +object LocalDateSerializer : KSerializer { + private const val SERIAL_NAME = "LocalDate" + + override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor(SERIAL_NAME, PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): LocalDate { + return LocalDate.parse(decoder.decodeString()) + } + + override fun serialize( + encoder: Encoder, + value: LocalDate, + ) { + encoder.encodeString(value.toString()) + } +} diff --git a/android/app/src/main/res/layout/fragment_my_page.xml b/android/app/src/main/res/layout/fragment_my_page.xml index 44f3c7406..56ca69754 100644 --- a/android/app/src/main/res/layout/fragment_my_page.xml +++ b/android/app/src/main/res/layout/fragment_my_page.xml @@ -5,6 +5,8 @@ + + @@ -121,17 +123,51 @@ + tools:listitem="@layout/item_pet" + tools:visibility="gone" /> + + + + + + + + + diff --git a/android/app/src/main/res/layout/item_dog.xml b/android/app/src/main/res/layout/item_pet.xml similarity index 91% rename from android/app/src/main/res/layout/item_dog.xml rename to android/app/src/main/res/layout/item_pet.xml index 1df95d6ad..ac125431d 100644 --- a/android/app/src/main/res/layout/item_dog.xml +++ b/android/app/src/main/res/layout/item_pet.xml @@ -8,8 +8,8 @@ + name="pet" + type="com.woowacourse.friendogly.domain.model.Pet" /> 프로필 편집 등록하기 + 등록하기를 통해 강아지를 추가해주세요 댕댕이 이름 diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index 7e17a57e6..4500ab977 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -49,7 +49,8 @@ retrofit = "2.11.0" retrofit2-kotlinx-serialization-converter = "1.0.0" # serialization -serialization = "1.6.0" +serialization = "1.6.3" +kotlinx-datetime = "0.4.0" # paging paging = "3.3.0" @@ -72,6 +73,7 @@ lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtim lifecycle-extensions = { group = "androidx.lifecycle", name = "lifecycle-extensions", version.ref = "lifecycle-extensions" } coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" } kotlinx-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" } +kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" } # android-library androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } @@ -113,7 +115,7 @@ retrofit2-kotlinx-serialization-converter = { module = "com.jakewharton.retrofit [bundles] android = ["androidx-constraintlayout", "androidx-activity", "androidx-appcompat", "androidx-core-ktx", "material", "image-cropper", "glide", "flextbox", "paging-runtime-ktx", "splashscreen"] -kotlin = ["lifecycle-runtime-ktx", "lifecycle-extensions", "coroutines-core", "kotlinx-serialization"] +kotlin = ["lifecycle-runtime-ktx", "lifecycle-extensions", "coroutines-core", "kotlinx-serialization", "kotlinx-datetime"] navigation = ["androidx-navigation-fragemnt", "androidx-navigation-ui"] google = ["google-services", "firebase-auth", "firebase-messaging", "firebase-bom", "google-auth"] network = ["retrofit-core", "okhttp-core", "okhttp-logging-interceptor", "retrofit2-kotlinx-serialization-converter"]