Skip to content

Commit

Permalink
Merge pull request #18 from nocap-stone-design/feature/#17-Buddy
Browse files Browse the repository at this point in the history
Feature/#17 buddy
  • Loading branch information
KDW03 authored Mar 23, 2023
2 parents 94fca13 + 992771f commit c6d24ab
Show file tree
Hide file tree
Showing 25 changed files with 533 additions and 173 deletions.
8 changes: 4 additions & 4 deletions .idea/deploymentTargetDropDown.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions buddy/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,16 @@ dependencies {
api project(path: ':common-ui')

implementation 'io.github.ParkSangGwon:tedimagepicker:1.2.8'

implementation 'de.hdodenhof:circleimageview:3.1.0'


// Navigation
api "androidx.navigation:navigation-fragment-ktx:$rootProject.nav_version"
api "androidx.navigation:navigation-ui-ktx:$rootProject.nav_version"

implementation "com.google.dagger:hilt-android:$rootProject.hiltVersion"
kapt "com.google.dagger:hilt-android-compiler:$rootProject.hiltVersion"

implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.8.0'
testImplementation 'junit:junit:4.13.2'
Expand Down
2 changes: 1 addition & 1 deletion buddy/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.INTERNET" />
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.nocapstone.buddyvet.buddy.data

import com.nocapstone.buddyvet.buddy.domain.entity.*
import com.nocapstone.common.data.dto.CommonResponse
import okhttp3.MultipartBody
import retrofit2.http.*

interface BuddyService {

@GET("buddies")
suspend fun readBuddyList(
@Header("Authorization") token: String
): CommonResponse<BuddyListResponse>

@POST("buddies")
suspend fun createBuddy(
@Header("Authorization") token: String,
@Body buddyRequest: BuddyRequest
): CommonResponse<BuddyId>

@GET("buddies/{buddyId}")
suspend fun readBuddyDetail(
@Header("Authorization") token: String,
@Path("buddyId") buddyId: Long,
): CommonResponse<BuddyDetailResponse>

//TODO Refactor PATCH


@DELETE("buddies/{buddyId}")
suspend fun deleteBuddy(
@Header("Authorization") token: String,
@Path("buddyId") buddyId: Long,
): CommonResponse<String?>

@POST("buddies/{buddyId}/image")
suspend fun uploadBuddyImg(
@Header("Authorization") token: String,
@Path("buddyId") buddyId: Long,
@Part image: MultipartBody.Part
): CommonResponse<String?>

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.nocapstone.buddyvet.buddy.di

import com.nocapstone.buddyvet.buddy.data.BuddyService
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
class NetworkModule {

@Singleton
@Provides
fun provideBuddyService(retrofit: Retrofit): BuddyService {
return retrofit.create(BuddyService::class.java)
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.nocapstone.buddyvet.buddy.domain.entity

data class BuddyListResponse(
val buddies: List<BuddyData>?
)

data class BuddyData(
val id: Int,
val kind: String,
val name: String,
val gender: String,
val profile: String,
val age: String
)

data class BuddyId(
val buddyId: Long
)

data class BuddyDetailResponse(
val buddy: BuddyDetailData
)

data class BuddyDetailData(
val kind: String,
val name: String,
val profile: String,
val birthDay: String,
val adoptDay: String,
val isNeutered: Boolean,
val gender: String
)
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package com.nocapstone.onboarding.domain
package com.nocapstone.buddyvet.buddy.domain.entity

data class BuddyRequest(
val kind : String,
var name : String = "name",
var bread : String = "bread",
var birthDay : String = "birthday",
var adoptDay : String = "adoptDay",
var isNeutered : Boolean = false,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.nocapstone.buddyvet.buddy.domain.usecase

import com.nocapstone.buddyvet.buddy.data.BuddyService
import com.nocapstone.buddyvet.buddy.domain.entity.BuddyData
import com.nocapstone.buddyvet.buddy.domain.entity.BuddyRequest
import okhttp3.MultipartBody
import javax.inject.Inject

class BuddyUseCase @Inject constructor(
private val buddyService: BuddyService
) {

suspend fun readBuddyList(token: String): List<BuddyData>? {
return buddyService.readBuddyList(token).data.buddies
}

suspend fun createBuddy(token: String, buddyRequest: BuddyRequest): Long {
return buddyService.createBuddy(token, buddyRequest).data.buddyId
}

suspend fun readBuddyDetail(token: String, buddyId: Long) {
buddyService.readBuddyDetail(token, buddyId)
}

suspend fun deleteBuddy(token: String, buddyId: Long) {
buddyService.deleteBuddy(token, buddyId)
}

suspend fun uploadBuddyImg(token: String, buddyId: Long, image: MultipartBody.Part) {
buddyService.uploadBuddyImg(token, buddyId, image)
}

}
136 changes: 122 additions & 14 deletions buddy/src/main/java/com/nocapstone/buddyvet/buddy/ui/BuddyViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,25 +1,133 @@
package com.nocapstone.buddyvet.buddy.ui

import android.content.Context
import android.net.Uri
import android.provider.OpenableColumns
import android.util.Log
import androidx.lifecycle.ViewModel
import com.nocapstone.buddyvet.buddy.util.BuddyType
import androidx.lifecycle.viewModelScope
import com.nocapstone.buddyvet.buddy.domain.entity.BuddyData
import com.nocapstone.buddyvet.buddy.domain.entity.BuddyRequest
import com.nocapstone.buddyvet.buddy.domain.usecase.BuddyUseCase
import com.nocapstone.common.domain.usecase.DataStoreUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.toRequestBody
import javax.inject.Inject

class BuddyViewModel : ViewModel() {
private val _selectType = MutableStateFlow(BuddyType.NULL)
val selectType: StateFlow<BuddyType> = _selectType
@HiltViewModel
class BuddyViewModel @Inject constructor(
@ApplicationContext private val context: Context,
private val buddyUseCase: BuddyUseCase,
private val dataStoreUseCase: DataStoreUseCase
) : ViewModel() {

private val _buddyList = MutableStateFlow<List<BuddyData>?>(null)
val buddyList: StateFlow<List<BuddyData>?> = _buddyList

/*
private val _newBuddy = MutableStateFlow<BuddyRequest?>(null)
val newBuddy : StateFlow<BuddyRequest?> = _newBuddy
*/

fun setSelectBuddyType(buddyType : BuddyType){
if (_selectType.value == buddyType){
_selectType.value = BuddyType.NULL
}else{
//_newBuddy.value = BuddyRequest(buddyType.kind)
_selectType.value = buddyType
val newBuddy: StateFlow<BuddyRequest?> = _newBuddy

private val _selectImgUri = MutableStateFlow<Uri?>(null)
val selectImgUri: StateFlow<Uri?> = _selectImgUri

fun setKind(kind: String) {
_newBuddy.value = BuddyRequest(kind)
}

fun setName(name: String) {
_newBuddy.value?.name = name
}

fun setBirthDay(birthDay: String) {
_newBuddy.value?.birthDay = birthDay
}

fun setAdoptDay(adoptDay: String) {
_newBuddy.value?.adoptDay = adoptDay
}

fun setNeutered(Neutered: Boolean) {
_newBuddy.value?.isNeutered = Neutered
}

fun setGender(gender: String) {
if (gender == "남자") {
_newBuddy.value?.gender = "M"
} else {
_newBuddy.value?.gender = "W"
}
}

fun setSelectImgUri(uri: Uri?) {
_selectImgUri.value = uri
}

fun readBuddyList() {
viewModelScope.launch {
val jwt = dataStoreUseCase.bearerJsonWebToken.first()!!
_buddyList.value = buddyUseCase.readBuddyList(jwt)
}
}

fun createBuddy() {
viewModelScope.launch {
try {
val jwt = dataStoreUseCase.bearerJsonWebToken.first()!!
val buddyId = buddyUseCase.createBuddy(jwt, _newBuddy.value!!)
if (_selectImgUri.value != null) {
uploadBuddyImg(jwt, buddyId)
}
} catch (e: Exception) {
Log.d("createBuddy", e.message.toString())
}
}
}

fun readBuddyDetail(buddyId: Long) {
viewModelScope.launch {
val jwt = dataStoreUseCase.bearerJsonWebToken.first()!!
buddyUseCase.readBuddyDetail(jwt, buddyId)
}
}

fun deleteBuddy(buddyId: Long) {
viewModelScope.launch {
val jwt = dataStoreUseCase.bearerJsonWebToken.first()!!
buddyUseCase.deleteBuddy(jwt, buddyId)
}
}

private fun uploadBuddyImg(token: String, buddyId: Long) {
viewModelScope.launch {
val imgUri = _selectImgUri.value!!
val inputStream = context.contentResolver.openInputStream(imgUri)
val byteArray = inputStream!!.readBytes()
val requestBody = byteArray.toRequestBody("multipart/form-data".toMediaTypeOrNull())
val image = MultipartBody.Part.createFormData(
"image",
getFileName(context, imgUri),
requestBody
)
buddyUseCase.uploadBuddyImg(token, buddyId, image)
}
}


private fun getFileName(context: Context, uri: Uri): String? {
val cursor = context.contentResolver.query(uri, null, null, null, null)
return cursor?.use {
it.moveToFirst()
val nameIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME)
return it.getString(nameIndex)
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,24 @@ class CompleteRegistrationFragment : Fragment() {

private val buddyViewModel: BuddyViewModel by viewModels({ requireActivity() })


override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentCompleteRegistrationBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

binding.apply {
this.viewModel = buddyViewModel
this.lifecycleOwner = viewLifecycleOwner
}

binding.next.setOnClickListener {
buddyViewModel.createBuddy()
LoginUtil.startMainActivity(requireActivity(), mainActivityClass)
}

Expand Down
Loading

0 comments on commit c6d24ab

Please sign in to comment.