From 0b68279432c09c9907c488de7680e8d4854bf012 Mon Sep 17 00:00:00 2001 From: soopeach Date: Tue, 12 Mar 2024 00:19:12 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[feat/register=5Freview]:=20=ED=9B=84?= =?UTF-8?q?=EA=B8=B0=20=EC=9E=91=EC=84=B1=20UseCase=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/datasource/RestaurantDataSource.kt | 3 + .../datasource/RestaurantDataSourceImpl.kt | 62 ++++++++++++++++--- .../org/gdsc/data/network/RestaurantAPI.kt | 8 +++ .../repository/RestaurantRepositoryImpl.kt | 9 +++ .../domain/repository/RestaurantRepository.kt | 4 +- .../gdsc/domain/usecase/PostReviewUseCase.kt | 14 +++++ 6 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 domain/src/main/java/org/gdsc/domain/usecase/PostReviewUseCase.kt diff --git a/data/src/main/java/org/gdsc/data/datasource/RestaurantDataSource.kt b/data/src/main/java/org/gdsc/data/datasource/RestaurantDataSource.kt index fa6022d7..962cddb9 100644 --- a/data/src/main/java/org/gdsc/data/datasource/RestaurantDataSource.kt +++ b/data/src/main/java/org/gdsc/data/datasource/RestaurantDataSource.kt @@ -2,6 +2,7 @@ package org.gdsc.data.datasource import androidx.paging.PagingData import kotlinx.coroutines.flow.Flow +import okhttp3.MultipartBody import org.gdsc.data.database.RegisteredRestaurant import org.gdsc.data.database.ReviewPaging import org.gdsc.data.model.RegisteredRestaurantResponse @@ -44,4 +45,6 @@ interface RestaurantDataSource { suspend fun getRestaurantReviews(restaurantId: Int): ReviewPaging + suspend fun postRestaurantReview(restaurantId: Int, reviewContent: String, reviewImages: List): Boolean + } \ No newline at end of file diff --git a/data/src/main/java/org/gdsc/data/datasource/RestaurantDataSourceImpl.kt b/data/src/main/java/org/gdsc/data/datasource/RestaurantDataSourceImpl.kt index c76c5670..56bd1719 100644 --- a/data/src/main/java/org/gdsc/data/datasource/RestaurantDataSourceImpl.kt +++ b/data/src/main/java/org/gdsc/data/datasource/RestaurantDataSourceImpl.kt @@ -10,6 +10,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import okhttp3.MultipartBody +import okhttp3.RequestBody import okhttp3.RequestBody.Companion.toRequestBody import org.gdsc.data.database.RegisteredRestaurant import org.gdsc.data.database.RestaurantByMapPagingSource @@ -40,7 +42,7 @@ class RestaurantDataSourceImpl @Inject constructor( private val db: RestaurantDatabase, ) : RestaurantDataSource { - private val coroutineScope : CoroutineScope = CoroutineScope(Dispatchers.IO) + private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO) override suspend fun getRestaurantLocationInfo( query: String, latitude: String, @@ -51,7 +53,10 @@ class RestaurantDataSourceImpl @Inject constructor( return restaurantAPI.getRestaurantLocationInfo(query, latitude, longitude, page).data } - override suspend fun getRecommendRestaurantInfo(recommendRestaurantId: Int, userLocation: UserLocation): RestaurantInfoResponse { + override suspend fun getRecommendRestaurantInfo( + recommendRestaurantId: Int, + userLocation: UserLocation + ): RestaurantInfoResponse { return restaurantAPI.getRecommendRestaurantInfo(recommendRestaurantId, userLocation).data } @@ -86,7 +91,8 @@ class RestaurantDataSourceImpl @Inject constructor( mapOf( "name" to restaurantRegistrationRequest.name.toRequestBody(), "introduce" to restaurantRegistrationRequest.introduce.toRequestBody(), - "categoryId" to restaurantRegistrationRequest.categoryId.toString().toRequestBody(), + "categoryId" to restaurantRegistrationRequest.categoryId.toString() + .toRequestBody(), "canDrinkLiquor" to restaurantRegistrationRequest.canDrinkLiquor.toString() .toRequestBody(), "goWellWithLiquor" to restaurantRegistrationRequest.goWellWithLiquor.toRequestBody(), @@ -117,7 +123,11 @@ class RestaurantDataSourceImpl @Inject constructor( @OptIn(ExperimentalPagingApi::class) override suspend fun getRestaurants( - userId: Int, locationData: Location, sortType: SortType, foodCategory: FoodCategory, drinkPossibility: DrinkPossibility + userId: Int, + locationData: Location, + sortType: SortType, + foodCategory: FoodCategory, + drinkPossibility: DrinkPossibility ): Flow> { val categoryFilter = when (foodCategory) { FoodCategory.INIT, FoodCategory.ETC -> null @@ -135,7 +145,7 @@ class RestaurantDataSourceImpl @Inject constructor( FoodCategory.INIT, FoodCategory.ETC -> String.Empty else -> foodCategory.key }, - isCanDrinkLiquor = isCanDrinkLiquor, + isCanDrinkLiquor = isCanDrinkLiquor, ) val restaurantSearchMapRequest = RestaurantSearchMapRequest(filter, locationData) @@ -155,9 +165,23 @@ class RestaurantDataSourceImpl @Inject constructor( ) { with(db.restaurantDao()) { when (sortType) { - SortType.DISTANCE -> getRegisteredRestaurantsSortedDistance(userId, categoryFilter, isCanDrinkLiquor) - SortType.RECENCY -> getRegisteredRestaurantsSortedRecent(userId, categoryFilter, isCanDrinkLiquor) - SortType.LIKED -> getRegisteredRestaurants(userId, categoryFilter, isCanDrinkLiquor) + SortType.DISTANCE -> getRegisteredRestaurantsSortedDistance( + userId, + categoryFilter, + isCanDrinkLiquor + ) + + SortType.RECENCY -> getRegisteredRestaurantsSortedRecent( + userId, + categoryFilter, + isCanDrinkLiquor + ) + + SortType.LIKED -> getRegisteredRestaurants( + userId, + categoryFilter, + isCanDrinkLiquor + ) } } @@ -173,7 +197,12 @@ class RestaurantDataSourceImpl @Inject constructor( } override suspend fun getRestaurantsByMap( - userLocation: Location?, startLocation: Location?, endLocation: Location?, sortType: SortType, foodCategory: FoodCategory?, drinkPossibility: DrinkPossibility? + userLocation: Location?, + startLocation: Location?, + endLocation: Location?, + sortType: SortType, + foodCategory: FoodCategory?, + drinkPossibility: DrinkPossibility? ): Flow> { val restaurantSearchMapRequest = RestaurantSearchMapRequest( userLocation = userLocation, @@ -196,7 +225,8 @@ class RestaurantDataSourceImpl @Inject constructor( config = PagingConfig( pageSize = 20, enablePlaceholders = true - )) { + ) + ) { RestaurantByMapPagingSource( restaurantAPI, restaurantSearchMapRequest @@ -208,4 +238,16 @@ class RestaurantDataSourceImpl @Inject constructor( return restaurantAPI.getRestaurantReviews(restaurantId).data } + override suspend fun postRestaurantReview( + restaurantId: Int, + reviewContent: String, + reviewImages: List + ): Boolean { + + return restaurantAPI.postRestaurantReview( + restaurantId, + MultipartBody.Part.createFormData("reviewContent", reviewContent), reviewImages + ).code == "RESTAURANT_REVIEW_CREATED" + } + } diff --git a/data/src/main/java/org/gdsc/data/network/RestaurantAPI.kt b/data/src/main/java/org/gdsc/data/network/RestaurantAPI.kt index 8b750a94..2d5ca9ea 100644 --- a/data/src/main/java/org/gdsc/data/network/RestaurantAPI.kt +++ b/data/src/main/java/org/gdsc/data/network/RestaurantAPI.kt @@ -81,4 +81,12 @@ interface RestaurantAPI { @Path("recommendRestaurantId") recommendRestaurantId: Int, ): Response + @Multipart + @POST("/api/v1/restaurant/{recommendRestaurantId}/review") + suspend fun postRestaurantReview( + @Path("recommendRestaurantId") recommendRestaurantId: Int, + @Part reviewContent: MultipartBody.Part, + @Part reviewImages: List, + ): Response + } \ No newline at end of file diff --git a/data/src/main/java/org/gdsc/data/repository/RestaurantRepositoryImpl.kt b/data/src/main/java/org/gdsc/data/repository/RestaurantRepositoryImpl.kt index 3cf41be6..a8cfa244 100644 --- a/data/src/main/java/org/gdsc/data/repository/RestaurantRepositoryImpl.kt +++ b/data/src/main/java/org/gdsc/data/repository/RestaurantRepositoryImpl.kt @@ -4,6 +4,7 @@ import androidx.paging.PagingData import androidx.paging.map import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import okhttp3.MultipartBody import org.gdsc.data.datasource.RestaurantDataSource import org.gdsc.domain.DrinkPossibility import org.gdsc.domain.FoodCategory @@ -125,4 +126,12 @@ class RestaurantRepositoryImpl @Inject constructor( override suspend fun getRestaurantReviews(restaurantId: Int): List { return restaurantDataSource.getRestaurantReviews(restaurantId).reviewList } + + override suspend fun postRestaurantReview( + restaurantId: Int, + reviewContent: String, + reviewImages: List + ): Boolean { + return restaurantDataSource.postRestaurantReview(restaurantId, reviewContent, reviewImages) + } } \ No newline at end of file diff --git a/domain/src/main/java/org/gdsc/domain/repository/RestaurantRepository.kt b/domain/src/main/java/org/gdsc/domain/repository/RestaurantRepository.kt index 3744acaa..e6bb650a 100644 --- a/domain/src/main/java/org/gdsc/domain/repository/RestaurantRepository.kt +++ b/domain/src/main/java/org/gdsc/domain/repository/RestaurantRepository.kt @@ -2,6 +2,7 @@ package org.gdsc.domain.repository import androidx.paging.PagingData import kotlinx.coroutines.flow.Flow +import okhttp3.MultipartBody import org.gdsc.domain.DrinkPossibility import org.gdsc.domain.FoodCategory import org.gdsc.domain.SortType @@ -13,7 +14,6 @@ import org.gdsc.domain.model.Review import org.gdsc.domain.model.UserLocation import org.gdsc.domain.model.request.ModifyRestaurantInfoRequest import org.gdsc.domain.model.request.RestaurantRegistrationRequest -import org.gdsc.domain.model.request.RestaurantSearchMapRequest import org.gdsc.domain.model.response.RestaurantInfoResponse interface RestaurantRepository { @@ -43,4 +43,6 @@ interface RestaurantRepository { suspend fun getRestaurantReviews(restaurantId: Int): List + suspend fun postRestaurantReview(restaurantId: Int, reviewContent: String, reviewImages: List): Boolean + } \ No newline at end of file diff --git a/domain/src/main/java/org/gdsc/domain/usecase/PostReviewUseCase.kt b/domain/src/main/java/org/gdsc/domain/usecase/PostReviewUseCase.kt new file mode 100644 index 00000000..2579c1ba --- /dev/null +++ b/domain/src/main/java/org/gdsc/domain/usecase/PostReviewUseCase.kt @@ -0,0 +1,14 @@ +package org.gdsc.domain.usecase + +import okhttp3.MultipartBody +import org.gdsc.domain.repository.RestaurantRepository +import javax.inject.Inject + +class PostReviewUseCase @Inject constructor( + private val restaurantRepository: RestaurantRepository +) { + + suspend operator fun invoke(restaurantId: Int, reviewContent: String, reviewImages: List): Boolean { + return restaurantRepository.postRestaurantReview(restaurantId, reviewContent, reviewImages) + } +} \ No newline at end of file From 3769f386d38698b48d6dca5e631ada5220cd334b Mon Sep 17 00:00:00 2001 From: soopeach Date: Tue, 12 Mar 2024 00:19:58 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[feat/register=5Freview]:=20=ED=9B=84?= =?UTF-8?q?=EA=B8=B0=20=EB=93=B1=EB=A1=9D=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/PhotoWillBeUploadedAdapter.kt | 64 ++++ .../RestaurantDetailFragment.kt | 75 ++++ .../viewmodel/RestaurantDetailViewModel.kt | 28 +- .../src/main/res/drawable/add_image_icon.png | Bin 0 -> 1082 bytes .../res/drawable/bg_rounded_6_main500.xml | 9 + .../src/main/res/drawable/delete_icon.png | Bin 0 -> 1032 bytes .../res/layout/fragment_restaurant_detail.xml | 319 ++++++++++-------- .../layout/item_photo_will_be_uploaded.xml | 25 ++ .../main/res/navigation/main_nav_graph.xml | 3 + 9 files changed, 384 insertions(+), 139 deletions(-) create mode 100644 presentation/src/main/java/org/gdsc/presentation/view/mypage/adapter/PhotoWillBeUploadedAdapter.kt create mode 100644 presentation/src/main/res/drawable/add_image_icon.png create mode 100644 presentation/src/main/res/drawable/bg_rounded_6_main500.xml create mode 100644 presentation/src/main/res/drawable/delete_icon.png create mode 100644 presentation/src/main/res/layout/item_photo_will_be_uploaded.xml diff --git a/presentation/src/main/java/org/gdsc/presentation/view/mypage/adapter/PhotoWillBeUploadedAdapter.kt b/presentation/src/main/java/org/gdsc/presentation/view/mypage/adapter/PhotoWillBeUploadedAdapter.kt new file mode 100644 index 00000000..62b1d820 --- /dev/null +++ b/presentation/src/main/java/org/gdsc/presentation/view/mypage/adapter/PhotoWillBeUploadedAdapter.kt @@ -0,0 +1,64 @@ +package org.gdsc.presentation.view.mypage.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.net.toUri +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import org.gdsc.presentation.databinding.ItemPhotoWillBeUploadedBinding + +class PhotoWillBeUploadedAdapter( + private val onDeleteButtonClicked: (String) -> Unit +) : + ListAdapter( + diffUtil + ) { + inner class PhotoWillBeUploadedViewHolder(private val binding: ItemPhotoWillBeUploadedBinding) : + RecyclerView.ViewHolder(binding.root) { + + fun bind(url: String) { + + Glide.with(binding.root) + .load(url.toUri()) + .into(binding.photoWillBeUploaded) + + binding.deleteButton.setOnClickListener { + onDeleteButtonClicked(url) + } + } + } + + companion object { + val diffUtil = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: String, newItem: String): Boolean { + return oldItem == newItem + } + + override fun areContentsTheSame(oldItem: String, newItem: String): Boolean { + return oldItem == newItem + } + } + } + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): PhotoWillBeUploadedViewHolder { + val inflater = LayoutInflater.from(parent.context) + return PhotoWillBeUploadedViewHolder( + ItemPhotoWillBeUploadedBinding.inflate( + inflater, + parent, + false + ) + ) + } + + override fun onBindViewHolder(holder: PhotoWillBeUploadedViewHolder, position: Int) { + holder.apply { + bind(getItem(position)) + } + } +} \ No newline at end of file diff --git a/presentation/src/main/java/org/gdsc/presentation/view/mypage/restaurantdetail/RestaurantDetailFragment.kt b/presentation/src/main/java/org/gdsc/presentation/view/mypage/restaurantdetail/RestaurantDetailFragment.kt index 724f0164..a9750e84 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/mypage/restaurantdetail/RestaurantDetailFragment.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/mypage/restaurantdetail/RestaurantDetailFragment.kt @@ -8,15 +8,26 @@ import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast +import androidx.core.net.toUri import androidx.fragment.app.activityViewModels +import androidx.fragment.app.setFragmentResultListener import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import com.bumptech.glide.Glide import com.google.android.material.tabs.TabLayoutMediator import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch +import okhttp3.MediaType +import okhttp3.MultipartBody +import okhttp3.RequestBody import org.gdsc.presentation.R import org.gdsc.presentation.databinding.FragmentRestaurantDetailBinding +import org.gdsc.presentation.utils.BitmapUtils.getCompressedBitmapFromUri +import org.gdsc.presentation.utils.BitmapUtils.saveBitmapToFile import org.gdsc.presentation.utils.CalculatorUtils +import org.gdsc.presentation.utils.repeatWhenUiStarted +import org.gdsc.presentation.view.mypage.adapter.PhotoWillBeUploadedAdapter import org.gdsc.presentation.view.mypage.adapter.RestaurantDetailPagerAdapter import org.gdsc.presentation.view.mypage.viewmodel.RestaurantDetailViewModel @@ -28,6 +39,10 @@ class RestaurantDetailFragment : Fragment() { private val viewModel: RestaurantDetailViewModel by activityViewModels() + private val adapter = PhotoWillBeUploadedAdapter { + viewModel.deletePhotoForReviewState(it) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -41,6 +56,66 @@ class RestaurantDetailFragment : Fragment() { setButtons() setTabLayout() observeData() + + repeatWhenUiStarted { + viewModel.photosForReviewState.collect { + adapter.submitList(it) + } + } + + binding.rvImageListWillBeUploaded.adapter = adapter + + binding.addImageIcon.setOnClickListener { + val directions = + RestaurantDetailFragmentDirections.actionRestaurantDetailFragmentToMultiImagePickerFragment() + + findNavController().navigate(directions) + } + + binding.btnRegister.setOnClickListener { + + val pictures = mutableListOf() + + viewModel.photosForReviewState.value.forEachIndexed { index, sUri -> + + sUri.toUri() + .getCompressedBitmapFromUri(requireContext()) + ?.saveBitmapToFile(requireContext(), "$index.jpg")?.let { imageFile -> + + val requestFile = + RequestBody.create( + MediaType.parse("image/png"), + imageFile + ) + + val body = + MultipartBody.Part.createFormData( + "reviewImages", + imageFile.name, + requestFile + ) + + pictures.add(body) + + } + + } + + viewModel.postReview( + binding.etReview.text.toString(), + pictures + ) { + binding.etReview.text.clear() + Toast.makeText(requireContext(), "후기가 등록되었습니다!", Toast.LENGTH_SHORT).show() + } + } + + setFragmentResultListener("pickImages") { _, bundle -> + val images = bundle.getStringArray("imagesUri") + viewModel.setPhotosForReviewState(images?.toList() ?: emptyList()) + + if (images.isNullOrEmpty()) return@setFragmentResultListener + } } private fun setButtons() { diff --git a/presentation/src/main/java/org/gdsc/presentation/view/mypage/viewmodel/RestaurantDetailViewModel.kt b/presentation/src/main/java/org/gdsc/presentation/view/mypage/viewmodel/RestaurantDetailViewModel.kt index 6cee9ab6..8e9639b8 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/mypage/viewmodel/RestaurantDetailViewModel.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/mypage/viewmodel/RestaurantDetailViewModel.kt @@ -5,12 +5,15 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch +import okhttp3.MultipartBody import org.gdsc.domain.model.Review import org.gdsc.domain.model.UserInfo import org.gdsc.domain.model.response.RestaurantInfoResponse import org.gdsc.domain.usecase.GetRestaurantInfoUseCase import org.gdsc.domain.usecase.GetRestaurantReviewsUseCase +import org.gdsc.domain.usecase.PostReviewUseCase import org.gdsc.domain.usecase.user.GetOtherUserInfoUseCase import org.gdsc.presentation.JmtLocationManager import javax.inject.Inject @@ -21,7 +24,8 @@ class RestaurantDetailViewModel private val jmtLocationManager: JmtLocationManager, private val getRestaurantInfoUseCase: GetRestaurantInfoUseCase, private val getOtherUserInfoUseCase: GetOtherUserInfoUseCase, - private val getRestaurantReviewsUseCase: GetRestaurantReviewsUseCase + private val getRestaurantReviewsUseCase: GetRestaurantReviewsUseCase, + private val postReviewUseCase: PostReviewUseCase ): ViewModel() { private var _restaurantInfo: MutableStateFlow = MutableStateFlow(null) @@ -36,6 +40,17 @@ class RestaurantDetailViewModel val reviews: StateFlow> get() = _reviews + private var _photosForReviewState: MutableStateFlow> = + MutableStateFlow(emptyList()) + val photosForReviewState = _photosForReviewState.asStateFlow() + + fun setPhotosForReviewState(images: List) { + _photosForReviewState.value = images + } + + fun deletePhotoForReviewState(image: String) { + _photosForReviewState.value = _photosForReviewState.value - image + } init { viewModelScope.launch { @@ -54,4 +69,15 @@ class RestaurantDetailViewModel } + fun postReview(content: String, pictures: List, onSuccess: () -> Unit) { + viewModelScope.launch { + val isSuccess = postReviewUseCase(1, content, pictures) + + if (isSuccess) { + _photosForReviewState.value = emptyList() + onSuccess() + } + } + } + } \ No newline at end of file diff --git a/presentation/src/main/res/drawable/add_image_icon.png b/presentation/src/main/res/drawable/add_image_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0fd53b1880948bdf14831d970e985c1eb66da749 GIT binary patch literal 1082 zcmV-A1jYM_P)19cT9M%P)} z$N^=*nk@H#M*O?QCH#cbFXX%qhgq9gR0Sm@9*=k7uoyvMU1Ist=dbV{4G`6?{m{{J zJXMF+2e7w-jPriC+Z`!c55#48gv8)sm$vTD-?h}SB(Lk;PR3Wz$WTE&aAR_MgmXTG zhjmZ@2M^R>qjN9;U)}~rCZ>JLw)lcMb)t1wSyX6sS>8xH7VGNJyhz>#IPg9wk|s|> z+WDIgi?9%0*1dKi{Auf>(sJx5ob5iDIxoP$&ak;PG*D0&zIypQPZznI^Sxo5;6)iQ zi3kW`lZF&U9u;YQJvEG67=@~x&Qx7TYjfIzN@74!lxGfyV^BTsL<60|yr4Be4Wk_` z&AM|&C8L32qm2<8ZnxJd%NJPj&y5%wC??u?eRsPQjMWOT(Ae;RUt3>~sX#0i>taCYa*PrhPG<>rG_B>znc5kPOhU9G`kLcmL`9thOhJZ>vAR!FfAn zpV~Upvr!b=hoXBKO-^hvItK&sn@kb2QP1knUxVX!9{4f3wA1eEW#A*+d-4h%K7S2* z;t5L@vSf?|6P6pWQaoX)0jtFmmKm@^JYk6eyTlWw8?aM6VX6VU#S^9(D1~^! z6a%FaPvo5o;T9~az8g|^XPfwEF^2nuyn6sQ`jcQY+C7Fy-Ue{f;>8C}vJ95dD&Ee& z2%bK3uHM0beqpNy3rR+sag1zcXYod5s;07*qoM6N<$g7Hc7 AVgLXD literal 0 HcmV?d00001 diff --git a/presentation/src/main/res/drawable/bg_rounded_6_main500.xml b/presentation/src/main/res/drawable/bg_rounded_6_main500.xml new file mode 100644 index 00000000..8b55e5d7 --- /dev/null +++ b/presentation/src/main/res/drawable/bg_rounded_6_main500.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/drawable/delete_icon.png b/presentation/src/main/res/drawable/delete_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..179c23a21160af69efdbd0e1645c2b60f2a52fc8 GIT binary patch literal 1032 zcmV+j1o!)iP)fS;K9TLXz*mD z9FRg0780O(FhwsUB2>U1JfWg4NOyd%+6CI}c2U4Dne6V&+xfoP_ukGMfd33;)=+Y} ztjern=fH}9g9MygvD@}%IEXW0V*!Cf-_X+zkJ)(>3LxU|Uz7?otz-};H3JePvyI^P zd%Zy;L(ypP@QE`OKj#)asM3ke0_H(N?GOUjuFM?vZhX`q&rtUZ(5ioYRqF9mm%wU( zLDS|GOO@>L%)}1qlF#*`kL|FU!1&mlvgvrV2qD@ISKhknD?xFy1l)YOD_ zAyw75!UAaZD8UtX((S46xTP6^4A%TJ- zx`=kkW!=CQ8jNf|OiyF`1jllZXnltc><@?VA^ZLq^4eQV&Hnbt~_AVcofv5@x1(h?i8w|8}`k?l99jpd9VL{|JLExr$I88+Vz+g;& z|G?0S$O*(PsEp05YC2Tuo%GM@~NP9~{!n4l^SBy&V_DkHHZoZFjZ=i{(`eDEg}|U5FtkpTB-H zrkkRax-=FSSTSLt(){~R$XOd0U`ukcE_noc*+F}P5g3PNx`wyoZ5jJUL>4NKS9VQI zPJ%6c7bGPm!3`wx$$c?4v|4HzX=(6wViN8>Xo1<;Z}A1FP&E}Comt$D^PM#upc>Wz zNZRD@@s`rPwjC>~r2$Ls6{X}~A_ywDBM+K@fQ+>ogHl*y;OgCed9hSqR+3>Y{%nL~2gn84~)gL2IX41YFwIx1c2^A!ougi!q!f)dW4IFT)_SYSMWGrRrWUOADy z>C-Vm!sA|7S}4_Fo~0a^B#PUm0zer9s5doBb30000 - + app:layout_constraintBottom_toTopOf="@id/divider" + app:layout_behavior="@string/appbar_scrolling_view_behavior"> - - - + app:layout_constraintBottom_toBottomOf="parent" + > - - - - - - - - - + + + + + + + + + + + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/ct_distance_and_category" + android:layout_marginTop="4dp"> + + + + + + + + + + + + + + - + - + - - - - - - - - - + - + app:layout_constraintTop_toTopOf="parent" + style="@style/text_medium_medium" + android:textColor="@color/grey900"/> - + app:layout_constraintTop_toBottomOf="@id/et_review" + android:layout_marginTop="27dp"/> - + app:layout_constraintBottom_toBottomOf="@id/add_image_icon" + style="@style/text_medium_medium" + android:textColor="@color/white"/> + + diff --git a/presentation/src/main/res/layout/item_photo_will_be_uploaded.xml b/presentation/src/main/res/layout/item_photo_will_be_uploaded.xml new file mode 100644 index 00000000..3bd94ed5 --- /dev/null +++ b/presentation/src/main/res/layout/item_photo_will_be_uploaded.xml @@ -0,0 +1,25 @@ + + + + + + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/navigation/main_nav_graph.xml b/presentation/src/main/res/navigation/main_nav_graph.xml index 83c8e114..37c1baa9 100644 --- a/presentation/src/main/res/navigation/main_nav_graph.xml +++ b/presentation/src/main/res/navigation/main_nav_graph.xml @@ -173,6 +173,9 @@ +