diff --git a/core/common/src/main/java/com/teamwiney/core/common/model/WineSmell.kt b/core/common/src/main/java/com/teamwiney/core/common/model/WineSmell.kt new file mode 100644 index 00000000..a5cfab09 --- /dev/null +++ b/core/common/src/main/java/com/teamwiney/core/common/model/WineSmell.kt @@ -0,0 +1,23 @@ +package com.teamwiney.core.common.model + +enum class WineSmell(val type: String, val value: String, val korName: String) { + FRUIT("FRUIT", "FRUIT", "과일향"), + BERRY("FRUIT", "BERRY", "베리류"), + LEMONANDLIME("FRUIT", "LEMONANDLIME", "레몬/라임"), + APPLEPEAR("FRUIT", "APPLEPEAR", "사과/배"), + PEACHPLUM("FRUIT", "PEACHPLUM", "복숭아/자두"), + TROPICALFRUIT("FRUIT", "TROPICALFRUIT", "열대과일"), + FLOWER("NATURAL", "FLOWER", "꽃향"), + GRASSWOOD("NATURAL", "GRASSWOOD", "풀/나무"), + HERB("NATURAL", "HERB", "허브향"), + OAK("OAK", "OAK", "오크향"), + SPICE("OAK", "SPICE", "향신료"), + NUTS("OAK", "NUTS", "견과류"), + VANILLA("OAK", "VANILLA", "바닐라"), + CHOCOLATE("OAK", "CHOCOLATE", "초콜릿"), + FLINT("OTHER", "FLINT", "부싯돌"), + BREAD("OTHER", "BREAD", "빵"), + RUBBER("OTHER", "RUBBER", "고무"), + EARTHASH("OTHER", "EARTASH", "흙/재"), + MEDICINE("OTHER", "MEDICNE", "약품") +} \ No newline at end of file diff --git a/data/src/main/java/com/teamwiney/data/datasource/TastingNoteDataSource.kt b/data/src/main/java/com/teamwiney/data/datasource/TastingNoteDataSource.kt index b9616316..7afceeb7 100644 --- a/data/src/main/java/com/teamwiney/data/datasource/TastingNoteDataSource.kt +++ b/data/src/main/java/com/teamwiney/data/datasource/TastingNoteDataSource.kt @@ -11,7 +11,6 @@ import com.teamwiney.data.network.model.response.TastingNoteIdRes import kotlinx.coroutines.flow.Flow import okhttp3.MultipartBody import okhttp3.RequestBody -import retrofit2.http.Part interface TastingNoteDataSource { @@ -32,8 +31,7 @@ interface TastingNoteDataSource { fun deleteTastingNote(noteId: Int): Flow>> fun postTastingNote( - wineNoteWriteRequest: HashMap, - smellKeywordList: List, + request: RequestBody, multipartFiles: List, ): Flow>> } \ No newline at end of file diff --git a/data/src/main/java/com/teamwiney/data/datasource/TastingNoteDataSourceImpl.kt b/data/src/main/java/com/teamwiney/data/datasource/TastingNoteDataSourceImpl.kt index 9d2789f7..e636bc74 100644 --- a/data/src/main/java/com/teamwiney/data/datasource/TastingNoteDataSourceImpl.kt +++ b/data/src/main/java/com/teamwiney/data/datasource/TastingNoteDataSourceImpl.kt @@ -66,17 +66,10 @@ class TastingNoteDataSourceImpl @Inject constructor( }.flowOn(ioDispatcher) override fun postTastingNote( - wineNoteWriteRequest: HashMap, - smellKeywordList: List, + request: RequestBody, multipartFiles: List ): Flow>> = flow { - emit( - tastingNoteService.postTastingNote( - wineNoteWriteRequest, - smellKeywordList, - multipartFiles - ) - ) + emit(tastingNoteService.postTastingNote(request, multipartFiles)) }.flowOn(ioDispatcher) } \ No newline at end of file diff --git a/data/src/main/java/com/teamwiney/data/di/DataModule.kt b/data/src/main/java/com/teamwiney/data/di/DataModule.kt index 815fd2e9..271d75f6 100644 --- a/data/src/main/java/com/teamwiney/data/di/DataModule.kt +++ b/data/src/main/java/com/teamwiney/data/di/DataModule.kt @@ -1,5 +1,6 @@ package com.teamwiney.data.di +import android.content.Context import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import com.teamwiney.data.datasource.AuthDataSource @@ -22,6 +23,7 @@ import com.teamwiney.data.repository.wine.WineRepositoryImpl import dagger.Module import dagger.Provides import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.CoroutineDispatcher import javax.inject.Singleton @@ -67,8 +69,9 @@ object DataModule { @Provides @Singleton fun providesTastingNotRepository( - tastingNoteDataSource: TastingNoteDataSource - ): TastingNoteRepository = TastingNoteRepositoryImpl(tastingNoteDataSource) + tastingNoteDataSource: TastingNoteDataSource, + @ApplicationContext context: Context + ): TastingNoteRepository = TastingNoteRepositoryImpl(tastingNoteDataSource, context) @Provides @Singleton diff --git a/data/src/main/java/com/teamwiney/data/network/service/TastingNoteService.kt b/data/src/main/java/com/teamwiney/data/network/service/TastingNoteService.kt index 5863c090..13bb9012 100644 --- a/data/src/main/java/com/teamwiney/data/network/service/TastingNoteService.kt +++ b/data/src/main/java/com/teamwiney/data/network/service/TastingNoteService.kt @@ -16,10 +16,8 @@ import retrofit2.http.GET import retrofit2.http.Multipart import retrofit2.http.POST import retrofit2.http.Part -import retrofit2.http.PartMap import retrofit2.http.Path import retrofit2.http.Query -import java.util.PrimitiveIterator.OfInt interface TastingNoteService { @@ -58,8 +56,7 @@ interface TastingNoteService { @Multipart @POST("/tasting-notes") suspend fun postTastingNote( - @PartMap wineNoteWriteRequest: HashMap, - @Part smellKeywordList: List, + @Part("request") request: RequestBody, @Part multipartFiles: List, ): ApiResult> } \ No newline at end of file diff --git a/data/src/main/java/com/teamwiney/data/repository/tastingnote/TastingNoteRepository.kt b/data/src/main/java/com/teamwiney/data/repository/tastingnote/TastingNoteRepository.kt index f93c104a..00e77c4a 100644 --- a/data/src/main/java/com/teamwiney/data/repository/tastingnote/TastingNoteRepository.kt +++ b/data/src/main/java/com/teamwiney/data/repository/tastingnote/TastingNoteRepository.kt @@ -1,5 +1,6 @@ package com.teamwiney.data.repository.tastingnote +import android.net.Uri import com.teamwiney.core.common.base.ResponseWrapper import com.teamwiney.core.common.`typealias`.BaseResponse import com.teamwiney.data.network.adapter.ApiResult @@ -10,8 +11,6 @@ import com.teamwiney.data.network.model.response.TastingNoteDetail import com.teamwiney.data.network.model.response.TastingNoteFilters import com.teamwiney.data.network.model.response.TastingNoteIdRes import kotlinx.coroutines.flow.Flow -import okhttp3.MultipartBody -import okhttp3.RequestBody interface TastingNoteRepository { @@ -40,8 +39,21 @@ interface TastingNoteRepository { fun deleteTastingNote(noteId: Int): Flow> fun postTastingNote( - wineNoteWriteRequest: HashMap, - smellKeywordList: List, - multipartFiles: List, + wineId: Long, + officialAlcohol: Double, + alcohol: Int, + color: String, + sweetness: Int, + acidity: Int, + body: Int, + tannin: Int, + finish: Int, + memo: String, + rating: Int, + vintage: String, + price: String, + buyAgain: Boolean?, + smellKeywordList: List, + imgUris: List ): Flow>> } \ No newline at end of file diff --git a/data/src/main/java/com/teamwiney/data/repository/tastingnote/TastingNoteRepositoryImpl.kt b/data/src/main/java/com/teamwiney/data/repository/tastingnote/TastingNoteRepositoryImpl.kt index 2c04ee38..d95e6263 100644 --- a/data/src/main/java/com/teamwiney/data/repository/tastingnote/TastingNoteRepositoryImpl.kt +++ b/data/src/main/java/com/teamwiney/data/repository/tastingnote/TastingNoteRepositoryImpl.kt @@ -1,5 +1,7 @@ package com.teamwiney.data.repository.tastingnote +import android.content.Context +import android.net.Uri import com.teamwiney.core.common.base.ResponseWrapper import com.teamwiney.core.common.`typealias`.BaseResponse import com.teamwiney.data.datasource.TastingNoteDataSource @@ -10,13 +12,22 @@ import com.teamwiney.data.network.model.response.TastingNote import com.teamwiney.data.network.model.response.TastingNoteDetail import com.teamwiney.data.network.model.response.TastingNoteFilters import com.teamwiney.data.network.model.response.TastingNoteIdRes +import com.teamwiney.data.util.fileFromContentUri +import com.teamwiney.data.util.resizeAndSaveImage +import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.flow.Flow +import okhttp3.MediaType.Companion.toMediaType import okhttp3.MultipartBody import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.asRequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONArray +import org.json.JSONObject import javax.inject.Inject class TastingNoteRepositoryImpl @Inject constructor( - private val tastingNoteDataSource: TastingNoteDataSource + private val tastingNoteDataSource: TastingNoteDataSource, + @ApplicationContext private val context: Context ) : TastingNoteRepository { override fun getTasteAnalysis(): Flow>> = @@ -50,14 +61,49 @@ class TastingNoteRepositoryImpl @Inject constructor( tastingNoteDataSource.deleteTastingNote(noteId) override fun postTastingNote( - wineNoteWriteRequest: HashMap, - smellKeywordList: List, - multipartFiles: List + wineId: Long, + officialAlcohol: Double, + alcohol: Int, + color: String, + sweetness: Int, + acidity: Int, + body: Int, + tannin: Int, + finish: Int, + memo: String, + rating: Int, + vintage: String, + price: String, + buyAgain: Boolean?, + smellKeywordList: List, + imgUris: List ): Flow>> { - return tastingNoteDataSource.postTastingNote( - wineNoteWriteRequest, - smellKeywordList, - multipartFiles - ) + val jsonObjectBuilder = JSONObject().apply { + put("wineId", wineId) + put("officialAlcohol", officialAlcohol) + put("alcohol", alcohol) + put("color", color) + put("sweetness", sweetness) + put("acidity", acidity) + put("body", body) + put("tannin", tannin) + put("finish", finish) + put("memo", memo) + put("rating", rating) + if (vintage.isNotEmpty()) put("vintage", vintage.toInt()) + if (price.isNotEmpty()) put("price", price.toInt()) + buyAgain?.let { put("buyAgain", it) } + put("smellKeywordList", JSONArray().apply { smellKeywordList.forEach { put(it) } }) + } + + val request = jsonObjectBuilder.toString().toRequestBody("application/json".toMediaType()) + val multipartFiles = imgUris.map { + val originalFile = fileFromContentUri(context, it) + val compressedFile = resizeAndSaveImage(context, originalFile) + val requestBody: RequestBody = compressedFile.asRequestBody("image/*".toMediaType()) + MultipartBody.Part.createFormData("multipartFiles", compressedFile.name, requestBody) + } + + return tastingNoteDataSource.postTastingNote(request, multipartFiles) } } \ No newline at end of file diff --git a/data/src/main/java/com/teamwiney/data/util/FileExt.kt b/data/src/main/java/com/teamwiney/data/util/FileExt.kt index 2cd41d27..493d17a2 100644 --- a/data/src/main/java/com/teamwiney/data/util/FileExt.kt +++ b/data/src/main/java/com/teamwiney/data/util/FileExt.kt @@ -11,11 +11,9 @@ import java.security.SecureRandom import java.util.* fun fileFromContentUri(context: Context, contentUri: Uri): File { - // Preparing Temp file name val fileExtension = getFileExtension(context, contentUri) val fileName = "temp_file" + if (fileExtension != null) ".$fileExtension" else "" - // Creating Temp file val tempFile = File(context.cacheDir, fileName) tempFile.createNewFile() @@ -97,7 +95,7 @@ private fun createFile(context: Context): File { val storageDir = context.cacheDir - return File(storageDir, fileName) + return File(storageDir, "${fileName}.jpg") } private fun generateRandomFileName(length: Int): String { diff --git a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoColorAndFlavorScreen.kt b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoColorAndFlavorScreen.kt index 0e980924..ac03975a 100644 --- a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoColorAndFlavorScreen.kt +++ b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoColorAndFlavorScreen.kt @@ -5,6 +5,8 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -16,7 +18,6 @@ import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.BasicTextField @@ -61,15 +62,15 @@ import com.teamwiney.ui.components.WButton import com.teamwiney.ui.components.bottomBorder import com.teamwiney.ui.theme.LocalColors import com.teamwiney.ui.theme.WineyTheme -import kotlinx.coroutines.Job -data class WineSmell( +data class WineSmellKeyword( val title: String, val options: List, ) data class WineSmellOption( val name: String, + val value: String, var isSelected: Boolean = false ) @@ -113,8 +114,9 @@ fun NoteWineInfoColorAndSmellScreen( updateThumbX = { viewModel.updateThumbX(it) }, ) { viewModel.updateColor(it) } HeightSpacer(35.dp) - WineFavorPicker( - wineSmells = uiState.wineSmells, + WineFlavorPicker( + wineSmellKeywords = uiState.wineSmellKeywords, + isWineSmellKeywordSelected = viewModel::isWineSmellSelected, updateWineSmell = { wineSmellOption -> viewModel.updateWineSmells(wineSmellOption) }, @@ -146,8 +148,9 @@ fun NoteWineInfoColorAndSmellScreen( } @Composable -private fun WineFavorPicker( - wineSmells: List, +private fun WineFlavorPicker( + wineSmellKeywords: List, + isWineSmellKeywordSelected: (WineSmellOption) -> Boolean, updateWineSmell: (WineSmellOption) -> Unit = {}, navigateToStandardSmell: () -> Unit ) { Column( @@ -194,41 +197,46 @@ private fun WineFavorPicker( Column( verticalArrangement = Arrangement.spacedBy(25.dp) ) { - wineSmells.forEach { - WineSmellContainer(wineSmell = it, updateWineSmell = updateWineSmell) + wineSmellKeywords.forEach { + WineSmellContainer( + wineSmellKeyword = it, + isWineSmellKeywordSelected = isWineSmellKeywordSelected, + updateWineSmell = updateWineSmell + ) } } } } +@OptIn(ExperimentalLayoutApi::class) @Composable private fun WineSmellContainer( - wineSmell: WineSmell, + wineSmellKeyword: WineSmellKeyword, + isWineSmellKeywordSelected: (WineSmellOption) -> Boolean, updateWineSmell: (WineSmellOption) -> Unit = {} ) { Column( verticalArrangement = Arrangement.spacedBy(14.dp) ) { Text( - text = wineSmell.title, + text = wineSmellKeyword.title, modifier = Modifier.padding(start = 24.dp), style = WineyTheme.typography.bodyB2, color = WineyTheme.colors.gray_500 ) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(5.dp) + FlowRow( + modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), + horizontalArrangement = Arrangement.spacedBy(5.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) ) { - Spacer(modifier = Modifier.width(14.dp)) - wineSmell.options.forEach { + wineSmellKeyword.options.forEach { NoteFeatureText( name = it.name, - enable = it.isSelected, + enable = isWineSmellKeywordSelected(it), ) { updateWineSmell(it.copy(isSelected = !it.isSelected)) } } - Spacer(modifier = Modifier.width(14.dp)) } } } diff --git a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoFlavorScreen.kt b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoFlavorScreen.kt index aa024dbf..1dfb4f85 100644 --- a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoFlavorScreen.kt +++ b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoFlavorScreen.kt @@ -105,7 +105,7 @@ fun NoteWineInfoFlavorScreen( HeightSpacer(30.dp) WineTasteSlider( score = uiState.wineNote.alcohol, - onValueChange = { viewModel.updateWineNoteAlcohol(it) }, + onValueChange = { viewModel.updateAlcohol(it) }, title = "알코올", subTitle = "알코올 세기의 정도" ) diff --git a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoLevelScreen.kt b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoLevelScreen.kt index ceda493b..b49749f3 100644 --- a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoLevelScreen.kt +++ b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoLevelScreen.kt @@ -175,16 +175,24 @@ fun NoteWineInfoLevelScreen( .weight(1f), contentAlignment = Alignment.Center ) { - NumberPicker( - value = uiState.wineNote.alcohol, - onValueChange = { - viewModel.updateAlcohol(it) - }, - range = 0..20, - textStyle = WineyTheme.typography.title1.copy( - color = WineyTheme.colors.gray_50 + Row(verticalAlignment = Alignment.CenterVertically) { + NumberPicker( + value = uiState.wineNote.officialAlcohol.toInt(), + onValueChange = { + viewModel.updateOfficialAlcohol(it.toDouble()) + }, + range = 0..20, + textStyle = WineyTheme.typography.title1.copy( + color = WineyTheme.colors.gray_50 + ) ) - ) + Text( + text = "°", + style = WineyTheme.typography.title1.copy( + color = WineyTheme.colors.gray_50 + ) + ) + } } Row( modifier = Modifier.padding(horizontal = 24.dp), diff --git a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteContract.kt b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteContract.kt index 3f94073c..726e62ca 100644 --- a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteContract.kt +++ b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteContract.kt @@ -1,8 +1,5 @@ package com.teamwiney.notewrite -import androidx.compose.runtime.mutableStateListOf -import androidx.compose.runtime.remember -import androidx.compose.ui.graphics.Color import androidx.navigation.NavOptions import androidx.paging.LoadState import androidx.paging.LoadStates @@ -10,6 +7,7 @@ import androidx.paging.PagingData import com.teamwiney.core.common.base.UiEffect import com.teamwiney.core.common.base.UiEvent import com.teamwiney.core.common.base.UiState +import com.teamwiney.core.common.model.WineSmell import com.teamwiney.data.network.model.response.SearchWine import com.teamwiney.data.network.model.response.Wine import com.teamwiney.notewrite.model.WineNote @@ -36,47 +34,25 @@ class NoteWriteContract { val selectedWineInfo: Wine = Wine.default(), val wineNote: WineNote = WineNote.default(), val hintPopupOpen: Boolean = false, - val wineSmells: List = listOf( - WineSmell( + val wineSmellKeywords: List = listOf( + WineSmellKeyword( title = "과일향", - options = listOf( - WineSmellOption("과일향"), - WineSmellOption("베리류"), - WineSmellOption("레몬/라임"), - WineSmellOption("사과/배"), - WineSmellOption("복숭아/자두") - ) + options = WineSmell.values().filter { it.type == "FRUIT" }.map { WineSmellOption(it.korName, it.value) } ), - WineSmell( + WineSmellKeyword( title = "내추럴", - options = listOf( - WineSmellOption("꽃향"), - WineSmellOption("풀/나무"), - WineSmellOption("허브향") - ) + options = WineSmell.values().filter { it.type == "NATURAL" }.map { WineSmellOption(it.korName, it.value) } ), - WineSmell( + WineSmellKeyword( title = "오크향", - options = listOf( - WineSmellOption("오크향"), - WineSmellOption("향신로"), - WineSmellOption("견과류"), - WineSmellOption("바닐라"), - WineSmellOption("초콜릿") - ) + options = WineSmell.values().filter { it.type == "OAK" }.map { WineSmellOption(it.korName, it.value) } ), - WineSmell( + WineSmellKeyword( title = "기타", - options = listOf( - WineSmellOption("부싯돌"), - WineSmellOption("빵"), - WineSmellOption("고무"), - WineSmellOption("흙/재"), - WineSmellOption("약품") - ) - ), + options = WineSmell.values().filter { it.type == "OTHER" }.map { WineSmellOption(it.korName, it.value) } + ) ), - val thumbX: Float = 0f, + val thumbX: Float = 0f ) : UiState sealed class Event : UiEvent { diff --git a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteSelectWineScreen.kt b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteSelectWineScreen.kt index b3293e81..e814a6bb 100644 --- a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteSelectWineScreen.kt +++ b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteSelectWineScreen.kt @@ -19,7 +19,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -49,14 +48,13 @@ fun NoteWriteSelectWineScreen( val uiState by viewModel.uiState.collectAsStateWithLifecycle() val effectFlow = viewModel.effect - // Device Width - val deviceWidth = LocalContext.current.resources.displayMetrics.widthPixels - val selectedWine = uiState.selectedWine BackHandler { if (bottomSheetState.bottomSheetState.isVisible) { bottomSheetState.hideBottomSheet() + } else { + appState.navController.navigateUp() } } diff --git a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteViewModel.kt b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteViewModel.kt index 8abad09c..c5149562 100644 --- a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteViewModel.kt +++ b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteViewModel.kt @@ -1,6 +1,5 @@ package com.teamwiney.notewrite -import android.content.Context import android.net.Uri import android.util.Log import androidx.compose.ui.graphics.Color @@ -16,28 +15,18 @@ import com.teamwiney.data.network.model.response.SearchWine import com.teamwiney.data.pagingsource.SearchWinesPagingSource import com.teamwiney.data.repository.tastingnote.TastingNoteRepository import com.teamwiney.data.repository.wine.WineRepository -import com.teamwiney.data.util.fileFromContentUri -import com.teamwiney.data.util.resizeAndSaveImage -import com.teamwiney.data.util.toPlainRequestBody -import com.teamwiney.notewrite.model.SmellKeyword import dagger.hilt.android.lifecycle.HiltViewModel -import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.MultipartBody -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.asRequestBody import javax.inject.Inject @HiltViewModel class NoteWriteViewModel @Inject constructor( private val wineRepository: WineRepository, - private val tastingNoteRepository: TastingNoteRepository, - @ApplicationContext private val context: Context, + private val tastingNoteRepository: TastingNoteRepository ) : BaseViewModel( initialState = NoteWriteContract.State() ) { @@ -79,46 +68,26 @@ class NoteWriteViewModel @Inject constructor( } } - fun writeTastingNote() = viewModelScope.launch { - /** List형태 MultiPart 설정 */ - val smellKeywordList: ArrayList = - ArrayList().apply { - currentState.wineNote.smellKeywordList.forEach { - add(MultipartBody.Part.createFormData("smellKeywordList", it)) - } - } - - /** 단일 인자 MultiPart 설정 */ - val wineNoteWriteRequest = hashMapOf() - with(currentState.wineNote) { - wineNoteWriteRequest["wineId"] = wineId.toString().toPlainRequestBody() - wineNoteWriteRequest["alcohol"] = alcohol.toString().toPlainRequestBody() - wineNoteWriteRequest["color"] = colorToHexString(color).toPlainRequestBody() - wineNoteWriteRequest["sweetness"] = sweetness.toString().toPlainRequestBody() - wineNoteWriteRequest["acidity"] = acidity.toString().toPlainRequestBody() - wineNoteWriteRequest["body"] = body.toString().toPlainRequestBody() - wineNoteWriteRequest["tannin"] = body.toString().toPlainRequestBody() - wineNoteWriteRequest["finish"] = body.toString().toPlainRequestBody() - wineNoteWriteRequest["memo"] = memo.toPlainRequestBody() - if (vintage.isNotEmpty()) { - wineNoteWriteRequest["vintage"] = vintage.toPlainRequestBody() - } - if (price.isNotEmpty()) { - wineNoteWriteRequest["price"] = price.toPlainRequestBody() - } - buyAgain?.let { - wineNoteWriteRequest["buyAgain"] = buyAgain.toString().toPlainRequestBody() - } - } - - /** TODO 이미지 파일 변환 */ - val multipartFiles = convertImageToMultipartFile() + val wineNote = currentState.wineNote tastingNoteRepository.postTastingNote( - wineNoteWriteRequest = wineNoteWriteRequest, - smellKeywordList = smellKeywordList, - multipartFiles = multipartFiles + wineId = wineNote.wineId, + officialAlcohol = wineNote.officialAlcohol, + alcohol = wineNote.alcohol, + color = colorToHexString(wineNote.color), + sweetness = wineNote.sweetness, + acidity = wineNote.acidity, + body = wineNote.body, + tannin = wineNote.tannin, + finish = wineNote.finish, + memo = wineNote.memo, + rating = wineNote.rating, + vintage = wineNote.vintage, + price = wineNote.price, + buyAgain = wineNote.buyAgain, + smellKeywordList = wineNote.smellKeywordList, + imgUris = wineNote.imgs ).onStart { updateState(currentState.copy(isLoading = true)) }.collectLatest { @@ -140,15 +109,6 @@ class NoteWriteViewModel @Inject constructor( } } - private fun convertImageToMultipartFile(): List { - return currentState.wineNote.imgs.map { - val originalFile = fileFromContentUri(context, it) - val compressedFile = resizeAndSaveImage(context, originalFile) - val requestBody: RequestBody = compressedFile.asRequestBody("image/*".toMediaType()) - MultipartBody.Part.createFormData("multipartFile", compressedFile.name, requestBody) - } - } - private fun colorToHexString(color: Color): String { val argb = color.toArgb() val red = (argb shr 16 and 0xFF).toString(16).padStart(2, '0') @@ -168,6 +128,10 @@ class NoteWriteViewModel @Inject constructor( updateState(currentState.copy(hintPopupOpen = false)) } + fun updateOfficialAlcohol(officialAlcohol: Double) = viewModelScope.launch { + updateState(currentState.copy(wineNote = currentState.wineNote.copy(officialAlcohol = officialAlcohol))) + } + fun updateVintage(vintage: String) = viewModelScope.launch { updateState(currentState.copy(wineNote = currentState.wineNote.copy(vintage = vintage))) } @@ -293,29 +257,22 @@ class NoteWriteViewModel @Inject constructor( updateState(currentState.copy(wineNote = currentState.wineNote.copy(finish = finish))) } - fun updateWineNoteAlcohol(alcohol: Int) = viewModelScope.launch { - updateState(currentState.copy(wineNote = currentState.wineNote.copy(alcohol = alcohol))) - } - fun updateWineSmells(wineSmellOption: WineSmellOption) = viewModelScope.launch { - val wineSmells = currentState.wineSmells.toMutableList() - wineSmells.find { it.options.any { it.name == wineSmellOption.name } } - ?.let { wineSmell -> - val index = wineSmells.indexOfFirst { it.title == wineSmell.title } - wineSmells[index] = wineSmell.copy( - options = wineSmell.options.map { - if (it.name == wineSmellOption.name) { - wineSmellOption - } else { - it - } - } - ) - } - updateState(currentState.copy(wineSmells = wineSmells)) + val wineNote = currentState.wineNote + val updatedSmellKeywordList = if (wineNote.smellKeywordList.contains(wineSmellOption.value)) { + wineNote.smellKeywordList.filter { it != wineSmellOption.value } + } else { + wineNote.smellKeywordList + wineSmellOption.value + } + updateState(currentState.copy(wineNote = wineNote.copy(smellKeywordList = updatedSmellKeywordList))) } fun updateThumbX(thumbX: Float) = viewModelScope.launch { updateState(currentState.copy(thumbX = thumbX)) } + + fun isWineSmellSelected(wineSmellOption: WineSmellOption): Boolean { + val wineNote = currentState.wineNote + return wineNote.smellKeywordList.contains(wineSmellOption.value) + } } \ No newline at end of file diff --git a/feature/note/src/main/java/com/teamwiney/notewrite/model/WineNote.kt b/feature/note/src/main/java/com/teamwiney/notewrite/model/WineNote.kt index 27e7ff6f..df514e5d 100644 --- a/feature/note/src/main/java/com/teamwiney/notewrite/model/WineNote.kt +++ b/feature/note/src/main/java/com/teamwiney/notewrite/model/WineNote.kt @@ -26,7 +26,7 @@ data class WineNote( return WineNote( wineId = 0, vintage = "", - officialAlcohol = 0.0, + officialAlcohol = 12.0, price = "", color = Color.Red, sweetness = 0,