diff --git a/data/src/main/java/org/gdsc/data/database/RegisteredRestaurant.kt b/data/src/main/java/org/gdsc/data/database/RegisteredRestaurant.kt index 757266b5..fd263de7 100644 --- a/data/src/main/java/org/gdsc/data/database/RegisteredRestaurant.kt +++ b/data/src/main/java/org/gdsc/data/database/RegisteredRestaurant.kt @@ -1,7 +1,9 @@ package org.gdsc.data.database +import androidx.room.Database import androidx.room.Entity import androidx.room.PrimaryKey +import androidx.room.RoomDatabase @Entity(tableName = "restaurant") data class RegisteredRestaurant( @@ -18,7 +20,9 @@ data class RegisteredRestaurant( val category: String, // 식당 카테고리 val userId: Int, // 식당 등록한 유저 id val userNickName: String, // 식당 등록한 유저 닉네임 - val userProfileImageUrl: String, // 식당 등록한 유저 프로필 이미지 + val userProfileImageUrl: String?, // 식당 등록한 유저 프로필 이미지 val canDrinkLiquor: Boolean, // 식당 주류 판매 여부 val differenceInDistance: String, // 식당과의 거리 + val groupId: Int, + val groupName: String, ) \ No newline at end of file diff --git a/data/src/main/java/org/gdsc/data/database/RestaurantDatabase.kt b/data/src/main/java/org/gdsc/data/database/RestaurantDatabase.kt index 10a53bfe..81b2afbd 100644 --- a/data/src/main/java/org/gdsc/data/database/RestaurantDatabase.kt +++ b/data/src/main/java/org/gdsc/data/database/RestaurantDatabase.kt @@ -4,8 +4,10 @@ import android.content.Context import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase -@Database(entities = [RegisteredRestaurant::class], version = 4) +@Database(entities = [RegisteredRestaurant::class], version = 5) abstract class RestaurantDatabase: RoomDatabase() { abstract fun restaurantDao(): RestaurantDao @@ -20,10 +22,18 @@ abstract class RestaurantDatabase: RoomDatabase() { context.applicationContext, RestaurantDatabase::class.java, DATABASE_NAME - ).build() + ) + .addMigrations(MIGRATION_4_5) + .build() INSTANCE = instance instance } } + private val MIGRATION_4_5 = object : Migration(4, 5) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE restaurant ADD COLUMN groupId INTEGER NOT NULL DEFAULT 0") + database.execSQL("ALTER TABLE restaurant ADD COLUMN groupName TEXT NOT NULL DEFAULT ''") + } + } } } \ No newline at end of file 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 c0417a97..3a953448 100644 --- a/data/src/main/java/org/gdsc/data/datasource/RestaurantDataSource.kt +++ b/data/src/main/java/org/gdsc/data/datasource/RestaurantDataSource.kt @@ -31,7 +31,7 @@ interface RestaurantDataSource { suspend fun postRestaurantLocationInfo(restaurantLocationInfo: RestaurantLocationInfo): String - suspend fun postRestaurantInfo(restaurantRegistrationRequest: RestaurantRegistrationRequest): String + suspend fun postRestaurantInfo(restaurantRegistrationRequest: RestaurantRegistrationRequest, groupId: Int): String suspend fun getRestaurants( userId: Int, locationData: Location, sortType: SortType, foodCategory: FoodCategory, drinkPossibility: DrinkPossibility @@ -51,6 +51,8 @@ interface RestaurantDataSource { suspend fun getRegisteredRestaurantsBySearch(keyword: String?, userLocation: Location?): Flow> + suspend fun getRegisteredRestaurantByMapWithLimitCount(sortType: SortType, currentGroup: Group?): List + suspend fun getRegisteredRestaurantsBySearchWithLimitCount(keyword: String?, userLocation: Location?, limit: Int): List suspend fun getRestaurantReviews(restaurantId: Int): ReviewPaging 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 2faa69fb..14c48b39 100644 --- a/data/src/main/java/org/gdsc/data/datasource/RestaurantDataSourceImpl.kt +++ b/data/src/main/java/org/gdsc/data/datasource/RestaurantDataSourceImpl.kt @@ -87,7 +87,10 @@ class RestaurantDataSourceImpl @Inject constructor( return restaurantAPI.postRestaurantLocationInfo(restaurantLocationInfo).data } - override suspend fun postRestaurantInfo(restaurantRegistrationRequest: RestaurantRegistrationRequest): String { + override suspend fun postRestaurantInfo( + restaurantRegistrationRequest: RestaurantRegistrationRequest, + groupId: Int, + ): String { runCatching { restaurantAPI.postRestaurantInfo( mapOf( @@ -100,7 +103,7 @@ class RestaurantDataSourceImpl @Inject constructor( "goWellWithLiquor" to restaurantRegistrationRequest.goWellWithLiquor.toRequestBody(), "recommendMenu" to restaurantRegistrationRequest.recommendMenu.toRequestBody(), "restaurantLocationId" to restaurantRegistrationRequest.restaurantLocationAggregateId.toRequestBody(), - "groupId" to "10".toRequestBody() + "groupId" to groupId.toString().toRequestBody() ), pictures = restaurantRegistrationRequest.pictures ) @@ -258,6 +261,20 @@ class RestaurantDataSourceImpl @Inject constructor( }.flow.cachedIn(coroutineScope) } + override suspend fun getRegisteredRestaurantByMapWithLimitCount( + sortType: SortType, + currentGroup: Group? + ): List { + return restaurantAPI.getRestaurantLocationInfoByMap( + page = 1, + size = 3, + sort = sortType.key, + RestaurantSearchRequest( + groupId = currentGroup?.groupId + ) + ).data.restaurants + } + override suspend fun getRegisteredRestaurantsBySearchWithLimitCount( keyword: String?, userLocation: Location?, diff --git a/data/src/main/java/org/gdsc/data/model/RegisteredRestaurantResponse.kt b/data/src/main/java/org/gdsc/data/model/RegisteredRestaurantResponse.kt index 735ae856..6f5b9f8d 100644 --- a/data/src/main/java/org/gdsc/data/model/RegisteredRestaurantResponse.kt +++ b/data/src/main/java/org/gdsc/data/model/RegisteredRestaurantResponse.kt @@ -44,11 +44,15 @@ data class RegisteredRestaurantResponse( @SerializedName("userNickName") val userNickName: String = "", // 식당 등록한 유저 닉네임 @SerializedName("userProfileImageUrl") - val userProfileImageUrl: String = "", // 식당 등록한 유저 프로필 이미지 + val userProfileImageUrl: String? = "", // 식당 등록한 유저 프로필 이미지 @SerializedName("canDrinkLiquor") val canDrinkLiquor: Boolean = false, // 식당 주류 판매 여부 @SerializedName("differenceInDistance") val differenceInDistance: String = "", // 식당과의 거리 + @SerializedName("groupId") + val groupId: Int = 0, + @SerializedName("groupName") + val groupName: String = "", ) { fun convertResponseToRegisteredRestaurant( userId: Int, @@ -70,6 +74,8 @@ data class RegisteredRestaurantResponse( userProfileImageUrl = userProfileImageUrl, canDrinkLiquor = canDrinkLiquor, differenceInDistance = differenceInDistance, + groupId = groupId, + groupName = groupName, ) } } 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 aa582bab..6bf2ba5c 100644 --- a/data/src/main/java/org/gdsc/data/repository/RestaurantRepositoryImpl.kt +++ b/data/src/main/java/org/gdsc/data/repository/RestaurantRepositoryImpl.kt @@ -47,8 +47,11 @@ class RestaurantRepositoryImpl @Inject constructor( return restaurantDataSource.postRestaurantLocationInfo(restaurantLocationInfo) } - override suspend fun postRestaurantInfo(restaurantRegistrationRequest: RestaurantRegistrationRequest): String { - return restaurantDataSource.postRestaurantInfo(restaurantRegistrationRequest) + override suspend fun postRestaurantInfo( + restaurantRegistrationRequest: RestaurantRegistrationRequest, + groupId: Int, + ): String { + return restaurantDataSource.postRestaurantInfo(restaurantRegistrationRequest, groupId) } override suspend fun getRestaurants( @@ -85,6 +88,8 @@ class RestaurantRepositoryImpl @Inject constructor( userProfileImageUrl = restaurant.userProfileImageUrl, canDrinkLiquor = restaurant.canDrinkLiquor, differenceInDistance = restaurant.differenceInDistance, + groupId = restaurant.groupId, + groupName = restaurant.groupName, ) restaurantTemp }, result.totalElementsCount @@ -134,6 +139,8 @@ class RestaurantRepositoryImpl @Inject constructor( userProfileImageUrl = restaurant.userProfileImageUrl, canDrinkLiquor = restaurant.canDrinkLiquor, differenceInDistance = restaurant.differenceInDistance, + groupId = restaurant.groupId, + groupName = restaurant.groupName, ) } } @@ -163,11 +170,42 @@ class RestaurantRepositoryImpl @Inject constructor( userProfileImageUrl = restaurant.userProfileImageUrl, canDrinkLiquor = restaurant.canDrinkLiquor, differenceInDistance = restaurant.differenceInDistance, + groupId = restaurant.groupId, + groupName = restaurant.groupName, ) } } } + override suspend fun getRegisteredRestaurantByMapWithLimitCount( + sortType: SortType, + currentGroup: Group? + ): List { + return restaurantDataSource.getRegisteredRestaurantByMapWithLimitCount(sortType, currentGroup) + .map { restaurant -> + RegisteredRestaurant( + id = restaurant.id, + name = restaurant.name, + placeUrl = restaurant.placeUrl, + phone = restaurant.phone, + address = restaurant.address, + roadAddress = restaurant.roadAddress, + x = restaurant.x, + y = restaurant.y, + restaurantImageUrl = restaurant.restaurantImageUrl, + introduce = restaurant.introduce, + category = restaurant.category, + userId = restaurant.id, + userNickName = restaurant.userNickName, + userProfileImageUrl = restaurant.userProfileImageUrl, + canDrinkLiquor = restaurant.canDrinkLiquor, + differenceInDistance = restaurant.differenceInDistance, + groupId = restaurant.groupId, + groupName = restaurant.groupName, + ) + } + } + override suspend fun getRestaurantReviews(restaurantId: Int): List { return restaurantDataSource.getRestaurantReviews(restaurantId).reviewList @@ -201,6 +239,8 @@ class RestaurantRepositoryImpl @Inject constructor( userProfileImageUrl = restaurant.userProfileImageUrl, canDrinkLiquor = restaurant.canDrinkLiquor, differenceInDistance = restaurant.differenceInDistance, + groupId = restaurant.groupId, + groupName = restaurant.groupName, ) } } diff --git a/domain/src/main/java/org/gdsc/domain/model/GroupPreview.kt b/domain/src/main/java/org/gdsc/domain/model/GroupPreview.kt index 434eea9e..be6cd228 100644 --- a/domain/src/main/java/org/gdsc/domain/model/GroupPreview.kt +++ b/domain/src/main/java/org/gdsc/domain/model/GroupPreview.kt @@ -2,8 +2,9 @@ package org.gdsc.domain.model data class GroupPreview( val groupId: Int, - val groupIntroduce: String, val groupName: String, + val groupProfileImageUrl: String, + val groupIntroduce: String, val memberCnt: Int, val restaurantCnt: Int ) \ No newline at end of file diff --git a/domain/src/main/java/org/gdsc/domain/model/RegisteredRestaurant.kt b/domain/src/main/java/org/gdsc/domain/model/RegisteredRestaurant.kt index ae8ad726..8b5d3ea9 100644 --- a/domain/src/main/java/org/gdsc/domain/model/RegisteredRestaurant.kt +++ b/domain/src/main/java/org/gdsc/domain/model/RegisteredRestaurant.kt @@ -14,7 +14,9 @@ data class RegisteredRestaurant( val category: String, // 식당 카테고리 val userId: Int, // 식당 등록한 유저 id val userNickName: String, // 식당 등록한 유저 닉네임 - val userProfileImageUrl: String, // 식당 등록한 유저 프로필 이미지 + val userProfileImageUrl: String?, // 식당 등록한 유저 프로필 이미지 val canDrinkLiquor: Boolean, // 식당 주류 판매 여부 val differenceInDistance: String, // 식당과의 거리 + val groupId: Int, + val groupName: String, ) diff --git a/domain/src/main/java/org/gdsc/domain/model/RestaurantLocationInfo.kt b/domain/src/main/java/org/gdsc/domain/model/RestaurantLocationInfo.kt index e955a6f4..99172ea2 100644 --- a/domain/src/main/java/org/gdsc/domain/model/RestaurantLocationInfo.kt +++ b/domain/src/main/java/org/gdsc/domain/model/RestaurantLocationInfo.kt @@ -27,6 +27,4 @@ data class RestaurantLocationInfo( val x: String, @SerializedName("y") val y: String, - @SerializedName("differenceInDistance") - val differenceInDistance: String ): java.io.Serializable \ 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 80e609d2..ee95ac9e 100644 --- a/domain/src/main/java/org/gdsc/domain/repository/RestaurantRepository.kt +++ b/domain/src/main/java/org/gdsc/domain/repository/RestaurantRepository.kt @@ -30,7 +30,7 @@ interface RestaurantRepository { suspend fun postRestaurantLocationInfo(restaurantLocationInfo: RestaurantLocationInfo): String - suspend fun postRestaurantInfo(restaurantRegistrationRequest: RestaurantRegistrationRequest): String + suspend fun postRestaurantInfo(restaurantRegistrationRequest: RestaurantRegistrationRequest, groupId: Int): String suspend fun getRestaurants( userId: Int, locationData: Location, sortType: SortType, foodCategory: FoodCategory, drinkPossibility: DrinkPossibility @@ -50,6 +50,10 @@ interface RestaurantRepository { suspend fun getRegisteredRestaurantsBySearch(keyword: String?, userLocation: Location?): Flow> + suspend fun getRegisteredRestaurantByMapWithLimitCount( + sortType: SortType,currentGroup: Group? + ): List + suspend fun getRestaurantReviews(restaurantId: Int): List suspend fun getRegisteredRestaurantsBySearchWithLimitCount(keyword: String?, userLocation: Location?, limit: Int): List diff --git a/domain/src/main/java/org/gdsc/domain/usecase/GetRestaurantMapWithLimitCountUseCase.kt b/domain/src/main/java/org/gdsc/domain/usecase/GetRestaurantMapWithLimitCountUseCase.kt new file mode 100644 index 00000000..a25698e3 --- /dev/null +++ b/domain/src/main/java/org/gdsc/domain/usecase/GetRestaurantMapWithLimitCountUseCase.kt @@ -0,0 +1,19 @@ +package org.gdsc.domain.usecase + +import org.gdsc.domain.SortType +import org.gdsc.domain.model.RegisteredRestaurant +import org.gdsc.domain.model.request.RestaurantSearchRequest +import org.gdsc.domain.model.response.Group +import org.gdsc.domain.repository.RestaurantRepository +import javax.inject.Inject + +class GetRestaurantMapWithLimitCountUseCase @Inject constructor( + private val restaurantRepository: RestaurantRepository +) { + suspend operator fun invoke( + sortType: SortType, + group: Group?, + ): List { + return restaurantRepository.getRegisteredRestaurantByMapWithLimitCount(sortType, group) + } +} \ No newline at end of file diff --git a/domain/src/main/java/org/gdsc/domain/usecase/PostRestaurantInfoUseCase.kt b/domain/src/main/java/org/gdsc/domain/usecase/PostRestaurantInfoUseCase.kt index 6dde4707..5cc52689 100644 --- a/domain/src/main/java/org/gdsc/domain/usecase/PostRestaurantInfoUseCase.kt +++ b/domain/src/main/java/org/gdsc/domain/usecase/PostRestaurantInfoUseCase.kt @@ -17,7 +17,8 @@ class PostRestaurantInfoUseCase @Inject constructor( canDrinkLiquor: Boolean, goWellWithLiquor: String, recommendMenu: String, - restaurantLocationAggregateIdg: String + restaurantLocationAggregateIdg: String, + groupId: Int, ): String { return restaurantRepository.postRestaurantInfo( RestaurantRegistrationRequest( @@ -30,6 +31,7 @@ class PostRestaurantInfoUseCase @Inject constructor( recommendMenu, restaurantLocationAggregateIdg ), + groupId, ) } } \ No newline at end of file diff --git a/presentation/src/main/java/org/gdsc/presentation/view/MainActivity.kt b/presentation/src/main/java/org/gdsc/presentation/view/MainActivity.kt index 2aeea933..6f2046a2 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/MainActivity.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/MainActivity.kt @@ -164,13 +164,13 @@ class MainActivity : BaseActivity() { binding.toolBar.isVisible = isVisible } - fun navigateToEditRestaurantInfo(restaurantId: Int) { - - val action = HomeFragmentDirections.actionHomeFragmentToRegisterRestaurantFragment( - targetRestaurantId = restaurantId - ) - navController.navigate(action) - } +// fun navigateToEditRestaurantInfo(restaurantId: Int) { +// +// val action = HomeFragmentDirections.actionHomeFragmentToRegisterRestaurantFragment( +// targetRestaurantId = restaurantId +// ) +// navController.navigate(action) +// } override fun onOptionsItemSelected(item: MenuItem): Boolean { if (item.itemId == android.R.id.home) { diff --git a/presentation/src/main/java/org/gdsc/presentation/view/WebAppInterface.kt b/presentation/src/main/java/org/gdsc/presentation/view/WebAppInterface.kt index 1225491e..a78ceae7 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/WebAppInterface.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/WebAppInterface.kt @@ -2,17 +2,56 @@ package org.gdsc.presentation.view import android.content.Context import android.webkit.JavascriptInterface -import android.widget.Toast -import org.gdsc.presentation.model.Route import org.json.JSONObject const val WEB_BASE_URL = "https://jmt-frontend-ad7b8.web.app/" +sealed class WebViewReceivedData { + data class Navigation( + val isVisible: Boolean + ): WebViewReceivedData() + + data class Back( + val enable: Boolean + ): WebViewReceivedData() + + data class Navigate( + val restaurantId: Int + ): WebViewReceivedData() + +} +sealed class WebViewBrideObject { + data class Token(val data: Any? = null): WebViewBrideObject() + data class Other(val data: WebViewReceivedData): WebViewBrideObject() + +} + +fun JSONObject.toWebViewBrideObject(): WebViewBrideObject { + return when(this.get("name")) { + "token" -> { + WebViewBrideObject.Token() + } + "navigation" -> { + val isVisible = JSONObject(this.get("data").toString()).get("isVisible") as Boolean + WebViewBrideObject.Other(WebViewReceivedData.Navigation(isVisible)) + } + "navigate" -> { + val groupId = JSONObject(this.get("data").toString()).get("groupId") as Int + WebViewBrideObject.Other(WebViewReceivedData.Navigate(groupId)) + } + // back + else -> { + val enable = JSONObject(this.get("data").toString()).get("enable") as Boolean + WebViewBrideObject.Other(WebViewReceivedData.Back(enable)) + } + } +} + class WebAppInterface( private val mContext: Context, private val slideUpBottomNavigationView: () -> Unit = {}, private val slideDownBottomNavigationView: () -> Unit = {}, - private val navigateToRestaurantEdit: (Int) -> Unit = {}, + private val navigateToRestaurantRegistration: (Int) -> Unit = {}, private val setAccessToken: () -> Unit = {}, private val setUserPosition: () -> Unit = {}, ) { @@ -28,8 +67,8 @@ class WebAppInterface( else slideDownBottomNavigationView() } - @JavascriptInterface - fun token() = setAccessToken() +// @JavascriptInterface +// fun token() = setAccessToken() // 딥링크 생성 필요 @JavascriptInterface @@ -37,20 +76,50 @@ class WebAppInterface( } // 데이터 구조는 다시 상의 후에 결정해서, 객체화 시키면 좋을 것으로 보임 +// @JavascriptInterface +// fun navigate(data: String) { +// val result = JSONObject(data) +// +// when(result.getString("route")) { +// Route.EDIT_RESTAURANT.route-> { +// val restaurantId = result.getString("restaurantId").toInt() +// navigateToRestaurantEdit(restaurantId) +// } +// } +// } + @JavascriptInterface - fun navigate(data: String) { - val result = JSONObject(data) + fun sendData(data: String) { + when (val result = JSONObject(data).toWebViewBrideObject()) { + is WebViewBrideObject.Token -> { + setAccessToken() + } + is WebViewBrideObject.Other -> { + when (val receivedData = result.data) { + is WebViewReceivedData.Navigation -> { + if (receivedData.isVisible) { + slideUpBottomNavigationView() + } else { + slideDownBottomNavigationView() + } + } + is WebViewReceivedData.Back -> { + if (receivedData.enable) { + + } else { - when(result.getString("route")) { - Route.EDIT_RESTAURANT.route-> { - val restaurantId = result.getString("restaurantId").toInt() - navigateToRestaurantEdit(restaurantId) + } + } + is WebViewReceivedData.Navigate -> { + navigateToRestaurantRegistration(receivedData.restaurantId) + } + } } } } // webView.canGoBack으로 뒤로가기 처리 완료해서 비워뒀습니다. - @JavascriptInterface - fun back(isEnableBack: Boolean) { - } +// @JavascriptInterface +// fun back(isEnableBack: Boolean) { +// } } diff --git a/presentation/src/main/java/org/gdsc/presentation/view/WebViewActivity.kt b/presentation/src/main/java/org/gdsc/presentation/view/WebViewActivity.kt index c94f8c0b..22625ede 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/WebViewActivity.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/WebViewActivity.kt @@ -5,6 +5,7 @@ import android.content.pm.ActivityInfo import android.net.http.SslError import android.os.Build import android.os.Bundle +import android.util.Log import android.view.WindowManager import android.webkit.PermissionRequest import android.webkit.SslErrorHandler @@ -13,43 +14,39 @@ import android.webkit.WebSettings import android.webkit.WebView import android.webkit.WebViewClient import androidx.activity.addCallback +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.viewModels +import androidx.lifecycle.lifecycleScope +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch import org.gdsc.presentation.databinding.ActivityWebViewBinding import org.gdsc.presentation.utils.repeatWhenUiStarted +import org.gdsc.presentation.view.webview.SpecificWebViewViewModel - +@AndroidEntryPoint class WebViewActivity : AppCompatActivity() { private lateinit var binding: ActivityWebViewBinding - private lateinit var webView:WebView + private lateinit var webView: WebView + + private val specificWebViewViewModel: SpecificWebViewViewModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityWebViewBinding.inflate(layoutInflater) setContentView(binding.root) -// webViewInit() - webView = binding.webView - setWebViewBackPress() - intent.extras?.let { - binding.webView.apply { - - repeatWhenUiStarted { - loadUrl(it.getString("url") ?: WEB_BASE_URL) - } + webViewInit() - settings.javaScriptEnabled = true - settings.domStorageEnabled = true - webViewClient = WebViewClient() - - addJavascriptInterface(WebAppInterface(context), "webviewBridge") - } - } + setWebViewBackPress() // val actionBar: ActionBar? = supportActionBar // actionBar!!.hide() } + private fun setWebViewBackPress() { this.onBackPressedDispatcher.addCallback(this) { if (binding.webView.canGoBack()) { @@ -60,14 +57,27 @@ class WebViewActivity : AppCompatActivity() { } } - fun webViewInit() { - val webSettings: WebSettings = webView.getSettings() - webSettings.javaScriptEnabled = true // allow the js + private fun webViewInit() { + + webView.apply { + loadUrl(WEB_BASE_URL + "group-create/name/") + + settings.javaScriptEnabled = true // allow the js + settings.domStorageEnabled = true + webViewClient = WebViewClient() + addJavascriptInterface(WebAppInterface(this@WebViewActivity, + setAccessToken = { + lifecycleScope.launch { + binding.webView.loadUrl( + "javascript:setAccessToken('${specificWebViewViewModel.getAccessToken()}')" + ) + } + }), "webviewBridge") + } + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) //화면이 계속 켜짐 requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_FULL_USER - webView.webViewClient = WebViewClient() - webView.addJavascriptInterface(WebAppInterface(this), "webviewBridge") } } diff --git a/presentation/src/main/java/org/gdsc/presentation/view/allsearch/SearchCategoryAllFragment.kt b/presentation/src/main/java/org/gdsc/presentation/view/allsearch/SearchCategoryAllFragment.kt index 090aa9ac..cd0ba0f6 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/allsearch/SearchCategoryAllFragment.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/allsearch/SearchCategoryAllFragment.kt @@ -8,13 +8,22 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.navigation.fragment.navArgs +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager +import androidx.viewbinding.ViewBinding import androidx.viewpager2.widget.ViewPager2 +import com.bumptech.glide.Glide import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collect import org.gdsc.domain.model.GroupInfo +import org.gdsc.domain.model.GroupPreview +import org.gdsc.domain.model.RegisteredRestaurant import org.gdsc.presentation.R +import org.gdsc.presentation.base.BaseViewHolder +import org.gdsc.presentation.base.ViewHolderBindListener import org.gdsc.presentation.databinding.FragmentSearchCategoryAllBinding +import org.gdsc.presentation.databinding.ItemSearchGroupBinding +import org.gdsc.presentation.databinding.ItemSearchRestaurantBinding import org.gdsc.presentation.utils.repeatWhenUiStarted import org.gdsc.presentation.view.allsearch.adapter.SearchCategoryGroupPreviewAdapter import org.gdsc.presentation.view.allsearch.adapter.SearchCategoryRestaurantAdapter @@ -24,14 +33,15 @@ import org.gdsc.presentation.view.allsearch.adapter.SearchCategoryRestaurantPrev class SearchCategoryAllFragment( private val searchKeyword: String ) : Fragment() { +): Fragment(), ViewHolderBindListener { private var _binding: FragmentSearchCategoryAllBinding? = null private val binding get() = _binding!! private val viewModel: AllSearchViewModel by activityViewModels() - private val searchCategoryRestaurantPreviewAdapter = SearchCategoryRestaurantPreviewAdapter() - private val searchCategoryGroupPreviewAdapter = SearchCategoryGroupPreviewAdapter() + private val searchCategoryRestaurantPreviewAdapter = SearchCategoryRestaurantPreviewAdapter(this) + private val searchCategoryGroupPreviewAdapter = SearchCategoryGroupPreviewAdapter(this) override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -111,4 +121,54 @@ class SearchCategoryAllFragment( _binding = null super.onDestroyView() } + + override fun onViewHolderBind(holder: BaseViewHolder, _item: Any) { + if (holder is SearchCategoryRestaurantPreviewAdapter.RestaurantsWithSearchPreviewViewHolder && _item is RegisteredRestaurant) { + val binding = ItemSearchRestaurantBinding.bind(holder.itemView) + binding.run { + Glide.with(root) + .load(_item.userProfileImageUrl) + .placeholder(R.drawable.base_profile_image) + .into(userProfileImage) + + groupName.text = _item.groupName + userName.text = _item.userNickName + + Glide.with(root) + .load(_item.restaurantImageUrl) + .placeholder(R.drawable.base_profile_image) + .into(restaurantImage) + + restaurantCategory.text = _item.category + restaurantName.text = _item.name + } + holder.itemView.setOnClickListener { + findNavController().navigate( + AllSearchContainerFragmentDirections.actionAllSearchContainerFragmentToRestaurantDetailFragment( + _item.id + ) + ) + } + } else if (holder is SearchCategoryGroupPreviewAdapter.GroupWithSearchPreviewViewHolder && _item is GroupPreview) { + val binding = ItemSearchGroupBinding.bind(holder.itemView) + binding.run { + Glide.with(root) + .load(_item.groupProfileImageUrl) + .placeholder(R.drawable.base_profile_image) + .into(ivGroupImage) + + tvGroupName.text = _item.groupName + tvIntroduction.text = _item.groupIntroduce + tvMemberCount.text = _item.memberCnt.toString() + tvRestaurantCount.text = _item.restaurantCnt.toString() + } + holder.itemView.setOnClickListener { + findNavController().navigate( + AllSearchContainerFragmentDirections.actionAllSearchContainerFragmentToMyGroupGroupDetail( + "group-detail/${_item.groupId}" + ) + ) + } + } + } } \ No newline at end of file diff --git a/presentation/src/main/java/org/gdsc/presentation/view/allsearch/SearchCategoryRestaurantFragment.kt b/presentation/src/main/java/org/gdsc/presentation/view/allsearch/SearchCategoryRestaurantFragment.kt index 6b0c2233..f3e943a5 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/allsearch/SearchCategoryRestaurantFragment.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/allsearch/SearchCategoryRestaurantFragment.kt @@ -7,27 +7,35 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager +import androidx.viewbinding.ViewBinding +import com.bumptech.glide.Glide import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collectLatest import org.gdsc.domain.DrinkPossibility import org.gdsc.domain.FoodCategory import org.gdsc.domain.SortType +import org.gdsc.domain.model.RegisteredRestaurant +import org.gdsc.presentation.R +import org.gdsc.presentation.base.BaseViewHolder +import org.gdsc.presentation.base.ViewHolderBindListener import org.gdsc.presentation.databinding.FragmentSearchCategoryRestaurantBinding +import org.gdsc.presentation.databinding.ItemSearchRestaurantBinding import org.gdsc.presentation.utils.repeatWhenUiStarted import org.gdsc.presentation.view.allsearch.adapter.SearchCategoryRestaurantAdapter @AndroidEntryPoint class SearchCategoryRestaurantFragment( private val searchKeyword: String -): Fragment() { +): Fragment(), ViewHolderBindListener { private var _binding: FragmentSearchCategoryRestaurantBinding? = null private val binding get() = _binding!! val viewModel: AllSearchViewModel by activityViewModels() - private val searchCategoryRestaurantAdapter = SearchCategoryRestaurantAdapter() + private val searchCategoryRestaurantAdapter = SearchCategoryRestaurantAdapter(this) override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -113,4 +121,33 @@ class SearchCategoryRestaurantFragment( _binding = null super.onDestroyView() } + + override fun onViewHolderBind(holder: BaseViewHolder, _item: Any) { + if (holder is SearchCategoryRestaurantAdapter.RestaurantsWithSearchViewHolder && _item is RegisteredRestaurant) { + val binding = ItemSearchRestaurantBinding.bind(holder.itemView) + binding.run { + Glide.with(root) + .load(_item.userProfileImageUrl) + .placeholder(R.drawable.base_profile_image) + .into(userProfileImage) + + userName.text = _item.userNickName + + Glide.with(root) + .load(_item.restaurantImageUrl) + .placeholder(R.drawable.base_profile_image) + .into(restaurantImage) + + restaurantCategory.text = _item.category + restaurantName.text = _item.name + } + holder.itemView.setOnClickListener { + findNavController().navigate( + AllSearchContainerFragmentDirections.actionAllSearchContainerFragmentToRestaurantDetailFragment( + _item.id + ) + ) + } + } + } } \ No newline at end of file diff --git a/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryGroupAdapter.kt b/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryGroupAdapter.kt index 19be5427..785270f8 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryGroupAdapter.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryGroupAdapter.kt @@ -8,10 +8,14 @@ import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import org.gdsc.domain.model.GroupPreview import org.gdsc.presentation.R +import org.gdsc.presentation.base.BaseViewHolder +import org.gdsc.presentation.base.ViewHolderBindListener import org.gdsc.presentation.databinding.ItemSearchGroupBinding -class SearchCategoryGroupAdapter() : - PagingDataAdapter( +class SearchCategoryGroupAdapter( + private val listener: ViewHolderBindListener, +) : + PagingDataAdapter( DiffCallback ) { @@ -26,8 +30,11 @@ class SearchCategoryGroupAdapter() : } class SearchCategoryGroupViewHolder( - private val binding: ItemSearchGroupBinding, - ) : RecyclerView.ViewHolder(binding.root) { + binding: ItemSearchGroupBinding, + listener: ViewHolderBindListener, + ) : BaseViewHolder( + binding, listener + ) { fun bind(item: GroupPreview) { binding.run { Glide.with(itemView.context) @@ -59,6 +66,6 @@ class SearchCategoryGroupAdapter() : ): SearchCategoryGroupViewHolder { val binding = ItemSearchGroupBinding.inflate(LayoutInflater.from(parent.context), parent, false) - return SearchCategoryGroupViewHolder(binding) + return SearchCategoryGroupViewHolder(binding, listener) } } \ No newline at end of file diff --git a/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryGroupPreviewAdapter.kt b/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryGroupPreviewAdapter.kt index 82423220..d200ec50 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryGroupPreviewAdapter.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryGroupPreviewAdapter.kt @@ -8,9 +8,13 @@ import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import org.gdsc.domain.model.GroupPreview import org.gdsc.presentation.R +import org.gdsc.presentation.base.BaseViewHolder +import org.gdsc.presentation.base.ViewHolderBindListener import org.gdsc.presentation.databinding.ItemSearchGroupBinding -class SearchCategoryGroupPreviewAdapter +class SearchCategoryGroupPreviewAdapter( + private val listener: ViewHolderBindListener +) : ListAdapter( diffCallback ) { @@ -34,22 +38,9 @@ class SearchCategoryGroupPreviewAdapter } class GroupWithSearchPreviewViewHolder( - private val binding: ItemSearchGroupBinding, - ): RecyclerView.ViewHolder(binding.root) { - fun bind(item: GroupPreview) { - binding.run { - Glide.with(itemView.context) - .load("https://picsum.photos/200") - .placeholder(R.drawable.base_profile_image) - .into(ivGroupImage) - - tvGroupName.text = item.groupName - tvIntroduction.text = item.groupIntroduce - tvMemberCount.text = item.memberCnt.toString() - tvRestaurantCount.text = item.restaurantCnt.toString() - } - } - } + binding: ItemSearchGroupBinding, + listener: ViewHolderBindListener + ): BaseViewHolder(binding, listener) override fun onBindViewHolder(holder: GroupWithSearchPreviewViewHolder, position: Int) { val item = getItem(position) @@ -63,7 +54,7 @@ class SearchCategoryGroupPreviewAdapter viewType: Int ): GroupWithSearchPreviewViewHolder { val binding = ItemSearchGroupBinding.inflate(LayoutInflater.from(parent.context), parent, false) - return GroupWithSearchPreviewViewHolder(binding) + return GroupWithSearchPreviewViewHolder(binding, listener) } } \ No newline at end of file diff --git a/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryRestaurantAdapter.kt b/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryRestaurantAdapter.kt index 90b39ed4..a973c690 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryRestaurantAdapter.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryRestaurantAdapter.kt @@ -9,10 +9,13 @@ import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import org.gdsc.domain.model.RegisteredRestaurant import org.gdsc.presentation.R +import org.gdsc.presentation.base.BaseViewHolder +import org.gdsc.presentation.base.ViewHolderBindListener import org.gdsc.presentation.databinding.ItemSearchRestaurantBinding -class SearchCategoryRestaurantAdapter - : PagingDataAdapter( +class SearchCategoryRestaurantAdapter( + private val listener: ViewHolderBindListener +) : PagingDataAdapter( diffCallback ) { @@ -36,27 +39,9 @@ class SearchCategoryRestaurantAdapter } class RestaurantsWithSearchViewHolder( - private val binding: ItemSearchRestaurantBinding, - ): RecyclerView.ViewHolder(binding.root) { - fun bind(item: RegisteredRestaurant) { - binding.run { - Glide.with(itemView.context) - .load(item.userProfileImageUrl) - .placeholder(R.drawable.base_profile_image) - .into(userProfileImage) - - userName.text = item.userNickName - - Glide.with(itemView.context) - .load(item.restaurantImageUrl) - .placeholder(R.drawable.base_profile_image) - .into(restaurantImage) - - restaurantCategory.text = item.category - restaurantName.text = item.name - } - } - } + binding: ItemSearchRestaurantBinding, + listener: ViewHolderBindListener + ): BaseViewHolder(binding, listener) override fun onBindViewHolder(holder: RestaurantsWithSearchViewHolder, position: Int) { val item = getItem(position) @@ -70,7 +55,7 @@ class SearchCategoryRestaurantAdapter viewType: Int ): RestaurantsWithSearchViewHolder { val binding = ItemSearchRestaurantBinding.inflate(LayoutInflater.from(parent.context), parent, false) - return RestaurantsWithSearchViewHolder(binding) + return RestaurantsWithSearchViewHolder(binding, listener) } fun setMaxItemCount(@IntRange(from = 1, to = Long.MAX_VALUE) maxItemCount: Int) { diff --git a/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryRestaurantPreviewAdapter.kt b/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryRestaurantPreviewAdapter.kt index 4bf2c7b1..82268213 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryRestaurantPreviewAdapter.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/allsearch/adapter/SearchCategoryRestaurantPreviewAdapter.kt @@ -8,9 +8,13 @@ import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import org.gdsc.domain.model.RegisteredRestaurant import org.gdsc.presentation.R +import org.gdsc.presentation.base.BaseViewHolder +import org.gdsc.presentation.base.ViewHolderBindListener import org.gdsc.presentation.databinding.ItemSearchRestaurantBinding -class SearchCategoryRestaurantPreviewAdapter +class SearchCategoryRestaurantPreviewAdapter( + private val listener: ViewHolderBindListener +) : ListAdapter( diffCallback ) { @@ -34,27 +38,11 @@ class SearchCategoryRestaurantPreviewAdapter } class RestaurantsWithSearchPreviewViewHolder( - private val binding: ItemSearchRestaurantBinding, - ): RecyclerView.ViewHolder(binding.root) { - fun bind(item: RegisteredRestaurant) { - binding.run { - Glide.with(itemView.context) - .load(item.userProfileImageUrl) - .placeholder(R.drawable.base_profile_image) - .into(userProfileImage) - - userName.text = item.userNickName - - Glide.with(itemView.context) - .load(item.restaurantImageUrl) - .placeholder(R.drawable.base_profile_image) - .into(restaurantImage) - - restaurantCategory.text = item.category - restaurantName.text = item.name - } - } - } + binding: ItemSearchRestaurantBinding, + listener: ViewHolderBindListener + ): BaseViewHolder( + binding, listener + ) override fun onBindViewHolder(holder: RestaurantsWithSearchPreviewViewHolder, position: Int) { val item = getItem(position) @@ -68,7 +56,7 @@ class SearchCategoryRestaurantPreviewAdapter viewType: Int ): RestaurantsWithSearchPreviewViewHolder { val binding = ItemSearchRestaurantBinding.inflate(LayoutInflater.from(parent.context), parent, false) - return RestaurantsWithSearchPreviewViewHolder(binding) + return RestaurantsWithSearchPreviewViewHolder(binding, listener) } } \ No newline at end of file diff --git a/presentation/src/main/java/org/gdsc/presentation/view/custom/BottomSheetDialog.kt b/presentation/src/main/java/org/gdsc/presentation/view/custom/BottomSheetDialog.kt index 44dff558..6d9466d7 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/custom/BottomSheetDialog.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/custom/BottomSheetDialog.kt @@ -34,11 +34,31 @@ class BottomSheetDialog { behavior.maxHeight = getBottomSheetDialogDefaultHeight() } - fun bindBuilder(binding: T, callback: T.(BottomSheetDialog) -> Unit) { + val isShowing: Boolean + get() { + return this.btmDlg.isShowing + } + + fun show() { + if (isShowing) return + this.btmDlg.show() + } + + fun dismiss() { + if (!isShowing) return + this.btmDlg.dismiss() + } + + fun bindBuilder( + binding: T, + callback: T.(BottomSheetDialog) -> Unit + ): org.gdsc.presentation.view.custom.BottomSheetDialog { this.customView = binding.root btmDlg.setContentView(this.customView!!) binding.callback(btmDlg) + return this } + private fun getBottomSheetDialogDefaultHeight(): Int { return getScreenRealHeight() * 70 / 100 } diff --git a/presentation/src/main/java/org/gdsc/presentation/view/group/MyGroupFragment.kt b/presentation/src/main/java/org/gdsc/presentation/view/group/MyGroupFragment.kt index c2602793..9fa2f338 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/group/MyGroupFragment.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/group/MyGroupFragment.kt @@ -9,9 +9,14 @@ import android.webkit.WebViewClient import androidx.activity.addCallback import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch import org.gdsc.presentation.databinding.FragmentMyGroupBinding import org.gdsc.presentation.utils.repeatWhenUiStarted +import org.gdsc.presentation.view.MainActivity import org.gdsc.presentation.view.WEB_BASE_URL import org.gdsc.presentation.view.WebAppInterface import org.gdsc.presentation.view.webview.SpecificWebViewViewModel @@ -23,6 +28,9 @@ class MyGroupFragment: Fragment() { private val specificWebViewViewModel: SpecificWebViewViewModel by viewModels() + private val parentActivity by lazy { requireActivity() as MainActivity } + private val navArgs by navArgs() + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -39,7 +47,7 @@ class MyGroupFragment: Fragment() { binding.webView.apply { repeatWhenUiStarted { - loadUrl(WEB_BASE_URL) + loadUrl(WEB_BASE_URL + navArgs.route) } settings.javaScriptEnabled = true @@ -47,7 +55,26 @@ class MyGroupFragment: Fragment() { webViewClient = WebViewClient() addJavascriptInterface(WebAppInterface( - requireContext() + mContext = requireContext(), + slideUpBottomNavigationView = { + parentActivity.slideUpBottomNavigationView() + }, + slideDownBottomNavigationView ={ + parentActivity.slideDownBottomNavigationView() + }, + navigateToRestaurantRegistration = { groupId -> + findNavController().navigate( + MyGroupFragmentDirections + .actionMyGroupFragmentToSearchRestaurantLocationInfoFragment(groupId) + ) + }, + setAccessToken = { + viewLifecycleOwner.lifecycleScope.launch { + binding.webView.loadUrl( + "javascript:setAccessToken('${specificWebViewViewModel.getAccessToken()}')" + ) + } + } ), "webviewBridge") } diff --git a/presentation/src/main/java/org/gdsc/presentation/view/home/HomeFragment.kt b/presentation/src/main/java/org/gdsc/presentation/view/home/HomeFragment.kt index 051282dd..6078d376 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/home/HomeFragment.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/home/HomeFragment.kt @@ -13,6 +13,8 @@ import androidx.core.content.res.ResourcesCompat import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.ConcatAdapter import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -24,10 +26,6 @@ import com.naver.maps.map.CameraUpdate import com.naver.maps.map.MapView import com.naver.maps.map.Projection import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import org.gdsc.domain.DrinkPossibility @@ -42,6 +40,7 @@ import org.gdsc.presentation.base.ViewHolderBindListener import org.gdsc.presentation.databinding.ContentSheetEmptyGroupBinding import org.gdsc.presentation.databinding.ContentSheetGroupSelectBinding import org.gdsc.presentation.databinding.FragmentHomeBinding +import org.gdsc.presentation.databinding.ItemMapWithRestaurantBinding import org.gdsc.presentation.model.ResultState import org.gdsc.presentation.utils.repeatWhenUiStarted import org.gdsc.presentation.view.WebViewActivity @@ -55,45 +54,48 @@ class HomeFragment : Fragment(), ViewHolderBindListener { private var _binding: FragmentHomeBinding? = null private val binding get() = _binding!! - val viewModel: HomeViewModel by viewModels() + private val viewModel: HomeViewModel by viewModels() private lateinit var mapView: MapView - // TODO : titleAdapter 문구 정리 필요 - private val recommendPopularRestaurantTitleAdapter by lazy { RecommendPopularRestaurantTitleAdapter("그룹에서 인기가 많아요") } - private val recommendPopularRestaurantWrapperAdapter by lazy { RecommendPopularRestaurantWrapperAdapter(recommendPopularRestaurantList)} + private val bottomSheetDialog by lazy { + BottomSheetDialog(requireContext()) + .bindBuilder( + ContentSheetEmptyGroupBinding.inflate(LayoutInflater.from(requireContext())) + ) { dialog -> + with(dialog) { + binding.groupHeader.isVisible = false + dialog.setCancelable(false) + dialog.behavior.isDraggable = false + createGroupButton.setOnClickListener { + startActivity( + Intent(requireContext(), WebViewActivity::class.java) + ) + } + searchGroupButton.setOnClickListener { + dialog.dismiss() + findNavController().navigate( + HomeFragmentDirections.actionHomeFragmentToAllSearchFragment() + ) + } + show() + } + } + } + private val restaurantFilterAdapter by lazy { RestaurantFilterAdapter(this) } - private val restaurantListAdapter by lazy { MapMarkerWithRestaurantsAdatper() } - private val mapMarkerAdapter by lazy { MapMarkerWithRestaurantsAdatper() } + private val restaurantListAdapter by lazy { MapMarkerWithRestaurantsAdatper(this) } + private val mapMarkerAdapter by lazy { MapMarkerWithRestaurantsAdatper(this) } private val emptyAdapter by lazy { EmptyAdapter() } private lateinit var concatAdapter: ConcatAdapter private val recommendPopularRestaurantList = listOf() - private val standardBottomSheetBehavior by lazy { BottomSheetBehavior.from(binding.bottomSheet) } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentHomeBinding.inflate(inflater, container, false) - - setMap(savedInstanceState) - observeState() - - concatAdapter = if (recommendPopularRestaurantList.isNotEmpty()) { - ConcatAdapter( - recommendPopularRestaurantTitleAdapter, - recommendPopularRestaurantWrapperAdapter, - restaurantFilterAdapter, - restaurantListAdapter - ) - } else { - ConcatAdapter( - restaurantFilterAdapter, - restaurantListAdapter - ) - } - return binding.root } @@ -105,8 +107,17 @@ class HomeFragment : Fragment(), ViewHolderBindListener { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + setMap(savedInstanceState) + observeState() + + concatAdapter = ConcatAdapter( + restaurantFilterAdapter, + restaurantListAdapter + ) + setRestaurantListBottomSheet() setGroup() + setView() } @@ -115,7 +126,8 @@ class HomeFragment : Fragment(), ViewHolderBindListener { val sortSpinner = holder.itemView.findViewById(R.id.sort_spinner) val foodSpinner = holder.itemView.findViewById(R.id.food_category_spinner) - val drinkSpinner = holder.itemView.findViewById(R.id.drink_possibility_spinner) + val drinkSpinner = + holder.itemView.findViewById(R.id.drink_possibility_spinner) sortSpinner.setMenu(SortType.getAllText()) { viewModel.setSortType(SortType.values()[it.itemId]) @@ -144,15 +156,49 @@ class HomeFragment : Fragment(), ViewHolderBindListener { drinkSpinner.setMenuTitle(it.text) } } + } else if (holder is MapMarkerWithRestaurantsAdatper.RestaurantsWithMapViewHolder && _item is RegisteredRestaurant) { + + val binding = ItemMapWithRestaurantBinding.bind(holder.itemView) + binding.run { + Glide.with(root) + .load(_item.userProfileImageUrl) + .placeholder(R.drawable.base_profile_image) + .into(userProfileImage) + + userName.text = _item.userNickName + + Glide.with(root) + .load(_item.restaurantImageUrl) + .placeholder(R.drawable.base_profile_image) + .into(restaurantImage) + + restaurantCategory.text = _item.category + drinkAvailability.text = if (_item.canDrinkLiquor) "주류 가능" else "주류 불가능" + + restaurantName.text = _item.name + restaurantDesc.text = _item.introduce + } + holder.itemView.setOnClickListener { + findNavController().navigate( + HomeFragmentDirections.actionHomeFragmentToRestaurantDetailFragment( + _item.id + ) + ) + } + + } + } + + private fun setView() { + binding.groupSearch.setOnClickListener { + findNavController().navigate(HomeFragmentDirections.actionHomeFragmentToAllSearchFragment()) } } private fun setGroup() { binding.groupArrow.setOnClickListener { - repeatWhenUiStarted { - viewModel.getMyGroup().let { groupList -> - viewModel.setGroupList(groupList) - } + lifecycleScope.launch { + viewModel.requestGroupList() } BottomSheetDialog(requireContext()) @@ -168,8 +214,10 @@ class HomeFragment : Fragment(), ViewHolderBindListener { if (holder is GroupSelectAdapter.GroupSelectViewHolder && _item is Group) { with(holder.itemView) { findViewById(R.id.group_name).text = _item.groupName - findViewById(R.id.select_button).isVisible = _item.isSelected - Glide.with(this).load(_item.groupProfileImageUrl).into(findViewById(R.id.group_image)) + findViewById(R.id.select_button).isVisible = + _item.isSelected + Glide.with(this).load(_item.groupProfileImageUrl) + .into(findViewById(R.id.group_image)) setOnClickListener { // TODO GroupList : 추후에 Room에 Current Group 넣어주게 되면, 반영해야 하는 부분 @@ -188,10 +236,11 @@ class HomeFragment : Fragment(), ViewHolderBindListener { with(dialog) { val groupSelectAdapter = GroupSelectAdapter(listener) viewModel.myGroupList.value.let { - when(it) { + when (it) { is ResultState.OnSuccess -> { groupSelectAdapter.submitList(it.response ?: emptyList()) } + else -> {} } } @@ -218,14 +267,14 @@ class HomeFragment : Fragment(), ViewHolderBindListener { naverMap.uiSettings.isZoomControlEnabled = false naverMap.uiSettings.isScaleBarEnabled = false - repeatWhenUiStarted { + lifecycleScope.launch { viewModel.registeredPagingDataByMap().collect { mapMarkerAdapter.submitData(it) } } - repeatWhenUiStarted { + lifecycleScope.launch { val location = viewModel.getCurrentLocation() location?.let { val cameraUpdate = CameraUpdate.scrollTo(LatLng(it.latitude, it.longitude)) @@ -236,7 +285,8 @@ class HomeFragment : Fragment(), ViewHolderBindListener { naverMap.moveCamera(zoom) } - mapMarkerAdapter.registerAdapterDataObserver(object: RecyclerView.AdapterDataObserver() { + mapMarkerAdapter.registerAdapterDataObserver(object : + RecyclerView.AdapterDataObserver() { override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { super.onItemRangeInserted(positionStart, itemCount) markerManager.updateDataList(mapMarkerAdapter.snapshot().items) @@ -258,26 +308,51 @@ class HomeFragment : Fragment(), ViewHolderBindListener { val projection: Projection = naverMap.projection val topLeft: LatLng = projection.fromScreenLocation(PointF(0F, 0F)) - val bottomRight: LatLng = projection.fromScreenLocation(PointF(naverMap.width.toFloat(), naverMap.height.toFloat())) - - viewModel.setStartLocation(Location(topLeft.longitude.toString(), topLeft.latitude.toString())) - viewModel.setEndLocation(Location(bottomRight.longitude.toString(), bottomRight.latitude.toString())) + val bottomRight: LatLng = projection.fromScreenLocation( + PointF( + naverMap.width.toFloat(), + naverMap.height.toFloat() + ) + ) + + viewModel.setStartLocation( + Location( + topLeft.longitude.toString(), + topLeft.latitude.toString() + ) + ) + viewModel.setEndLocation( + Location( + bottomRight.longitude.toString(), + bottomRight.latitude.toString() + ) + ) } } } private fun setRestaurantListBottomSheet() { + + binding.registButton.setOnClickListener { + findNavController().navigate(HomeFragmentDirections.actionHomeFragmentToSearchRestaurantLocationInfoFragment( + viewModel.currentGroup.value?.groupId ?: 0 + )) + } binding.scrollUpButton.setOnClickListener { binding.recyclerView.scrollToPosition(0) } binding.registRestaurantButton.setOnClickListener { - // TODO : 식당 등록 버튼 클릭 시 동작 정의 필요 - Log.d("testLog", "식당 등록 버튼 클릭") + findNavController().navigate(HomeFragmentDirections.actionHomeFragmentToSearchRestaurantLocationInfoFragment( + viewModel.currentGroup.value?.groupId ?: 0 + )) } + + val standardBottomSheetBehavior by lazy { BottomSheetBehavior.from(binding.bottomSheet) } + restaurantListAdapter.addLoadStateListener { loadState -> if (loadState.append.endOfPaginationReached) { if (restaurantListAdapter.itemCount < 1) { @@ -294,10 +369,12 @@ class HomeFragment : Fragment(), ViewHolderBindListener { object : BottomSheetBehavior.BottomSheetCallback() { fun setBottomSheetRelatedView(isExpanded: Boolean) { viewModel.currentGroup.value.let { - val isNotFullExpanded = isExpanded.not() || it == null || it.restaurantCnt == 0 + val isNotFullExpanded = + isExpanded.not() || it == null || it.restaurantCnt == 0 with(binding) { - binding.bottomSheetActionButtons.isVisible = isExpanded && it != null && it.restaurantCnt != 0 + binding.bottomSheetActionButtons.isVisible = + isExpanded && it != null && it.restaurantCnt != 0 bottomSheetHandle.isVisible = isNotFullExpanded bottomSheetHandleSpace.isVisible = isNotFullExpanded mapOptionContainer.isVisible = isNotFullExpanded @@ -328,65 +405,48 @@ class HomeFragment : Fragment(), ViewHolderBindListener { } } - override fun onSlide(bottomSheet: View, slideOffset: Float) { } + override fun onSlide(bottomSheet: View, slideOffset: Float) {} }) - - CoroutineScope(Dispatchers.Main).launch { - delay(1000) - if (standardBottomSheetBehavior.state != BottomSheetBehavior.STATE_COLLAPSED) - standardBottomSheetBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED - } } private fun observeState() { - repeatWhenUiStarted { - viewModel.registeredPagingDataByGroup().collect { + lifecycleScope.launch { + viewModel.registeredPagingDataByList().collect { restaurantListAdapter.submitData(it) } } - repeatWhenUiStarted { - viewModel.setSortType(SortType.DISTANCE) - } + lifecycleScope.launch { + val data = viewModel.getRestaurantMapWithLimitCount(SortType.DISTANCE, viewModel.currentGroup.value) - repeatWhenUiStarted { - viewModel.myGroupList.collect { - binding.groupName.text + if (data.isNullOrEmpty().not()) { + + // TODO : titleAdapter 문구 정리 필요 + val recommendPopularRestaurantTitleAdapter = RecommendPopularRestaurantTitleAdapter("그룹에서 인기가 많아요") + val recommendPopularRestaurantWrapperAdapter = RecommendPopularRestaurantWrapperAdapter(data) + + concatAdapter.addAdapter(0, recommendPopularRestaurantTitleAdapter) + concatAdapter.addAdapter(1, recommendPopularRestaurantWrapperAdapter) } } repeatWhenUiStarted { - viewModel.getMyGroup().let { groupList -> - viewModel.setGroupList(groupList) - } + viewModel.setSortType(SortType.DISTANCE) + } + + lifecycleScope.launch { + viewModel.requestGroupList() } repeatWhenUiStarted { viewModel.myGroupList.collect { state -> - when(state) { + when (state) { is ResultState.OnSuccess -> { val groupList = state.response - if (groupList.isNullOrEmpty()) { - viewModel.setCurrentGroup(null) - - BottomSheetDialog(requireContext()) - .bindBuilder( - ContentSheetEmptyGroupBinding.inflate(LayoutInflater.from(requireContext())) - ) { dialog -> - with(dialog) { - binding.groupHeader.isVisible = false - dialog.setCancelable(false) - dialog.behavior.isDraggable = false - createGroupButton.setOnClickListener { - startActivity( - Intent(requireContext(), WebViewActivity::class.java) - ) - } - show() - } - } + if (groupList.isEmpty()) { + bottomSheetDialog.show() } else { groupList.forEach { if (it.isSelected) { @@ -394,6 +454,7 @@ class HomeFragment : Fragment(), ViewHolderBindListener { return@forEach } } + bottomSheetDialog.dismiss() } } @@ -413,11 +474,13 @@ class HomeFragment : Fragment(), ViewHolderBindListener { } if (it.restaurantCnt == 0) { - binding.bottomSheet.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT + binding.bottomSheet.layoutParams.height = + ViewGroup.LayoutParams.WRAP_CONTENT binding.recyclerView.isVisible = false binding.registLayout.isVisible = true } else { - binding.bottomSheet.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT + binding.bottomSheet.layoutParams.height = + ViewGroup.LayoutParams.MATCH_PARENT binding.recyclerView.isVisible = true binding.registLayout.isVisible = false } @@ -427,8 +490,40 @@ class HomeFragment : Fragment(), ViewHolderBindListener { } } + + override fun onStart() { + super.onStart() + mapView.onStart() + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } + + override fun onStop() { + super.onStop() + mapView.onStop() + } + + override fun onLowMemory() { + super.onLowMemory() + mapView.onLowMemory() + } + override fun onDestroyView() { _binding = null super.onDestroyView() + mapView.onDestroy() } } \ No newline at end of file diff --git a/presentation/src/main/java/org/gdsc/presentation/view/home/HomeViewModel.kt b/presentation/src/main/java/org/gdsc/presentation/view/home/HomeViewModel.kt index 0f331a0d..79f6c27e 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/home/HomeViewModel.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/home/HomeViewModel.kt @@ -1,11 +1,9 @@ package org.gdsc.presentation.view.home -import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.paging.PagingData import androidx.paging.cachedIn -import com.naver.maps.geometry.LatLng import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow @@ -25,6 +23,7 @@ import org.gdsc.domain.model.RegisteredRestaurant import org.gdsc.domain.model.ScreenLocation import org.gdsc.domain.model.response.Group import org.gdsc.domain.usecase.GetMyGroupUseCase +import org.gdsc.domain.usecase.GetRestaurantMapWithLimitCountUseCase import org.gdsc.domain.usecase.GetRestaurantsByMapUseCase import org.gdsc.domain.usecase.PostSelectGroupUseCase import org.gdsc.presentation.JmtLocationManager @@ -37,6 +36,7 @@ class HomeViewModel @Inject constructor( private val getRestaurantsByMapUseCase: GetRestaurantsByMapUseCase, private val getMyGroupUseCase: GetMyGroupUseCase, private val postSelectGroupUserCase: PostSelectGroupUseCase, + private val getRestaurantMapWithLimitCountUseCase: GetRestaurantMapWithLimitCountUseCase, ) : ViewModel() { suspend fun getCurrentLocation() = locationManager.getCurrentLocation() @@ -85,8 +85,8 @@ class HomeViewModel @Inject constructor( get() = _myGroupList - private var _currentGroup = MutableStateFlow(null) - val currentGroup: StateFlow + private var _currentGroup: MutableStateFlow = MutableStateFlow(Group(0, "", "", "", "", 0, 0, false, false)) + val currentGroup: StateFlow get() = _currentGroup @@ -118,7 +118,7 @@ class HomeViewModel @Inject constructor( _myGroupList.value = ResultState.OnSuccess(groupList) } - fun setCurrentGroup(group: Group?) { + fun setCurrentGroup(group: Group) { _currentGroup.value = group } @@ -143,7 +143,7 @@ class HomeViewModel @Inject constructor( } @OptIn(ExperimentalCoroutinesApi::class) - suspend fun registeredPagingDataByGroup(): Flow> { + suspend fun registeredPagingDataByList(): Flow> { return run { return@run combine( @@ -159,8 +159,12 @@ class HomeViewModel @Inject constructor( }.cachedIn(viewModelScope) } - suspend fun getMyGroup(): List { - return getMyGroupUseCase() + suspend fun getRestaurantMapWithLimitCount(sortType: SortType, group: Group?): List { + return getRestaurantMapWithLimitCountUseCase(sortType, group) + } + + suspend fun requestGroupList() { + _myGroupList.value = ResultState.OnSuccess(getMyGroupUseCase()) } suspend fun selectGroup(groupID: Int) { diff --git a/presentation/src/main/java/org/gdsc/presentation/view/home/MapMarkerWithRestaurantsAdatper.kt b/presentation/src/main/java/org/gdsc/presentation/view/home/MapMarkerWithRestaurantsAdatper.kt index f05fa295..8c5336aa 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/home/MapMarkerWithRestaurantsAdatper.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/home/MapMarkerWithRestaurantsAdatper.kt @@ -8,9 +8,13 @@ import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import org.gdsc.domain.model.RegisteredRestaurant import org.gdsc.presentation.R +import org.gdsc.presentation.base.BaseViewHolder +import org.gdsc.presentation.base.ViewHolderBindListener import org.gdsc.presentation.databinding.ItemMapWithRestaurantBinding -class MapMarkerWithRestaurantsAdatper +class MapMarkerWithRestaurantsAdatper( + private val listener: ViewHolderBindListener +) : PagingDataAdapter( diffCallback ) { @@ -33,30 +37,10 @@ class MapMarkerWithRestaurantsAdatper } class RestaurantsWithMapViewHolder( - private val binding: ItemMapWithRestaurantBinding, - ): RecyclerView.ViewHolder(binding.root) { - fun bind(item: RegisteredRestaurant) { - binding.run { - Glide.with(itemView.context) - .load(item.userProfileImageUrl) - .placeholder(R.drawable.base_profile_image) - .into(userProfileImage) + binding: ItemMapWithRestaurantBinding, + listener: ViewHolderBindListener + ): BaseViewHolder(binding, listener) - userName.text = item.userNickName - - Glide.with(itemView.context) - .load(item.restaurantImageUrl) - .placeholder(R.drawable.base_profile_image) - .into(restaurantImage) - - restaurantCategory.text = item.category - drinkAvailability.text = if (item.canDrinkLiquor) "주류 가능" else "주류 불가능" - - restaurantName.text = item.name - restaurantDesc.text = item.introduce - } - } - } override fun onBindViewHolder(holder: RestaurantsWithMapViewHolder, position: Int) { val item = getItem(position) if (item != null) { @@ -68,7 +52,7 @@ class MapMarkerWithRestaurantsAdatper parent: ViewGroup, viewType: Int ): RestaurantsWithMapViewHolder { - val binding = ItemMapWithRestaurantBinding.inflate(LayoutInflater.from(parent.context), parent, false) - return RestaurantsWithMapViewHolder(binding) + val binding = ItemMapWithRestaurantBinding.inflate(LayoutInflater.from(parent.context), parent, false,) + return RestaurantsWithMapViewHolder(binding, listener) } } \ No newline at end of file diff --git a/presentation/src/main/java/org/gdsc/presentation/view/mypage/RegisteredRestaurantFragment.kt b/presentation/src/main/java/org/gdsc/presentation/view/mypage/RegisteredRestaurantFragment.kt index e6192167..b66ca3e2 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/mypage/RegisteredRestaurantFragment.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/mypage/RegisteredRestaurantFragment.kt @@ -6,24 +6,36 @@ import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.lifecycle.lifecycleScope +import androidx.navigation.findNavController import androidx.paging.LoadState import androidx.recyclerview.widget.LinearLayoutManager +import androidx.viewbinding.ViewBinding +import com.bumptech.glide.Glide import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import org.gdsc.domain.DrinkPossibility import org.gdsc.domain.FoodCategory import org.gdsc.domain.SortType +import org.gdsc.domain.model.RegisteredRestaurant +import org.gdsc.presentation.R +import org.gdsc.presentation.base.BaseViewHolder +import org.gdsc.presentation.base.ViewHolderBindListener import org.gdsc.presentation.view.mypage.adapter.RegisteredRestaurantPagingDataAdapter import org.gdsc.presentation.databinding.FragmentRegisteredRestaurantBinding +import org.gdsc.presentation.databinding.ItemRegisteredRestaurantBinding +import org.gdsc.presentation.utils.CalculatorUtils import org.gdsc.presentation.utils.repeatWhenUiStarted +import org.gdsc.presentation.view.custom.FlexibleCornerImageView import org.gdsc.presentation.view.mypage.viewmodel.MyPageViewModel @AndroidEntryPoint -class RegisteredRestaurantFragment : Fragment() { +class RegisteredRestaurantFragment : Fragment(), ViewHolderBindListener { private var _binding: FragmentRegisteredRestaurantBinding? = null private val binding get() = _binding!! @@ -45,7 +57,7 @@ class RegisteredRestaurantFragment : Fragment() { observeState() setSpinners() - myRestaurantAdapter = RegisteredRestaurantPagingDataAdapter() + myRestaurantAdapter = RegisteredRestaurantPagingDataAdapter(this) binding.registeredRestaurantRecyclerView.layoutManager = LinearLayoutManager(requireContext()) binding.registeredRestaurantRecyclerView.adapter = myRestaurantAdapter @@ -122,4 +134,35 @@ class RegisteredRestaurantFragment : Fragment() { super.onDestroyView() } + override fun onViewHolderBind(holder: BaseViewHolder, _item: Any) { + if (holder is RegisteredRestaurantPagingDataAdapter.RestaurantViewHolder && _item is RegisteredRestaurant) { + val binding = ItemRegisteredRestaurantBinding.bind(holder.itemView) + with(binding) { + restaurantName.text = _item.name + restaurantCategory.text = _item.category + userName.text = _item.userNickName + + restaurantDistance.text = binding.root.context.getString( + R.string.distance_from_current_location, + CalculatorUtils.getDistanceWithLength(_item.differenceInDistance.toInt()) + ) + + Glide.with(holder.itemView) + .load(_item.userProfileImageUrl) + .placeholder(R.drawable.base_profile_image) + .into(userProfileImage) + + Glide.with(holder.itemView) + .load(_item.restaurantImageUrl) + .placeholder(R.drawable.ig_restaurant_placeholder) + .into(restaurantImage) + } + holder.itemView.setOnClickListener { + val action = MyPageFragmentDirections + .actionMyPageFragmentToRestaurantDetailFragment(_item.id) + binding.root.findNavController().navigate(action) + } + } + } + } \ No newline at end of file diff --git a/presentation/src/main/java/org/gdsc/presentation/view/mypage/adapter/RegisteredRestaurantPagingDataAdapter.kt b/presentation/src/main/java/org/gdsc/presentation/view/mypage/adapter/RegisteredRestaurantPagingDataAdapter.kt index 594fa413..c69a7c52 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/mypage/adapter/RegisteredRestaurantPagingDataAdapter.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/mypage/adapter/RegisteredRestaurantPagingDataAdapter.kt @@ -8,11 +8,15 @@ import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import org.gdsc.domain.model.RegisteredRestaurant import org.gdsc.presentation.R +import org.gdsc.presentation.base.BaseViewHolder import org.gdsc.presentation.base.Const +import org.gdsc.presentation.base.ViewHolderBindListener import org.gdsc.presentation.databinding.ItemRegisteredRestaurantBinding import org.gdsc.presentation.utils.CalculatorUtils -class RegisteredRestaurantPagingDataAdapter : PagingDataAdapter( +class RegisteredRestaurantPagingDataAdapter( + private val listener: ViewHolderBindListener +) : PagingDataAdapter( diffCallback ) { @@ -26,11 +30,10 @@ class RegisteredRestaurantPagingDataAdapter : PagingDataAdapter(binding, listener) } - -class RestaurantViewHolder(private val binding: ItemRegisteredRestaurantBinding) : RecyclerView.ViewHolder(binding.root) { - fun bind(item: RegisteredRestaurant) { - with(binding) { - item.let { - restaurantName.text = it.name - restaurantCategory.text = it.category - userName.text = it.userNickName - - restaurantDistance.text = binding.root.context.getString( - R.string.distance_from_current_location, - CalculatorUtils.getDistanceWithLength(it.differenceInDistance.toInt()) - ) - - Glide.with(root) - .load(it.userProfileImageUrl) - .placeholder(R.drawable.base_profile_image) - .into(userProfileImage) - - Glide.with(root) - .load(it.restaurantImageUrl) - .placeholder(R.drawable.ig_restaurant_placeholder) - .into(restaurantImage) - } - } - } -} \ 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 ee66e82e..7098c44a 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 @@ -15,6 +15,7 @@ import androidx.fragment.app.activityViewModels import androidx.fragment.app.setFragmentResultListener import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs import com.bumptech.glide.Glide import com.google.android.material.tabs.TabLayoutMediator import dagger.hilt.android.AndroidEntryPoint @@ -44,6 +45,8 @@ class RestaurantDetailFragment : Fragment() { private val parentActivity by lazy { activity as MainActivity } + private val navArgs by navArgs() + private val adapter = PhotoWillBeUploadedAdapter { viewModel.deletePhotoForReviewState(it) } @@ -145,6 +148,19 @@ class RestaurantDetailFragment : Fragment() { } private fun observeData() { + viewLifecycleOwner.lifecycleScope.launch { + viewModel.init(navArgs.restaurantId) + } + + lifecycleScope.launch { + viewModel.restaurantIdState.collect { + if (it != -1) { + viewModel.setData() + binding.btnRegister.isEnabled = true + } + } + } + viewLifecycleOwner.lifecycleScope.launch { viewModel.restaurantInfo.collect { it?.let { notNullRestaurantInfo -> @@ -197,5 +213,8 @@ class RestaurantDetailFragment : Fragment() { binding.restaurantDetailPager.currentItem = category } - + override fun onDestroy() { + super.onDestroy() + viewModel.onDataCleared() + } } \ No newline at end of file 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 8e9639b8..b2be98bf 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 @@ -52,26 +52,48 @@ class RestaurantDetailViewModel _photosForReviewState.value = _photosForReviewState.value - image } - init { - viewModelScope.launch { + val restaurantIdState: StateFlow + get() = _restaurantIdState + private var _restaurantIdState: MutableStateFlow = MutableStateFlow(-1) + + fun init(id:Int) { + _restaurantIdState.value = id + } + fun setData() { + viewModelScope.launch { val currentLocation = jmtLocationManager.getCurrentLocation() - val restaurantInfo = getRestaurantInfoUseCase(1, currentLocation?.longitude.toString(), currentLocation?.latitude.toString()) + val restaurantInfo = getRestaurantInfoUseCase(restaurantIdState.value, currentLocation?.longitude.toString(), currentLocation?.latitude.toString()) _restaurantInfo.value = restaurantInfo val userInfo = getOtherUserInfoUseCase(restaurantInfo.userId) _authorInfo.value = userInfo - val reviews = getRestaurantReviewsUseCase(1) + val reviews = getRestaurantReviewsUseCase(restaurantIdState.value) _reviews.value = reviews - } - } +// init { +// viewModelScope.launch { +// +// val currentLocation = jmtLocationManager.getCurrentLocation() +// val restaurantInfo = getRestaurantInfoUseCase(state.value, currentLocation?.longitude.toString(), currentLocation?.latitude.toString()) +// _restaurantInfo.value = restaurantInfo +// +// val userInfo = getOtherUserInfoUseCase(restaurantInfo.userId) +// _authorInfo.value = userInfo +// +// val reviews = getRestaurantReviewsUseCase(1) +// _reviews.value = reviews +// +// } +// +// } + fun postReview(content: String, pictures: List, onSuccess: () -> Unit) { viewModelScope.launch { - val isSuccess = postReviewUseCase(1, content, pictures) + val isSuccess = postReviewUseCase(restaurantIdState.value, content, pictures) if (isSuccess) { _photosForReviewState.value = emptyList() @@ -80,4 +102,10 @@ class RestaurantDetailViewModel } } + fun onDataCleared() { + _restaurantInfo.value = null + _authorInfo.value = null + _reviews.value = emptyList() + } + } \ No newline at end of file diff --git a/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/ConfirmRestaurantRegistrationFragment.kt b/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/ConfirmRestaurantRegistrationFragment.kt index 376acb3f..04c14051 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/ConfirmRestaurantRegistrationFragment.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/ConfirmRestaurantRegistrationFragment.kt @@ -29,6 +29,7 @@ class ConfirmRestaurantRegistrationFragment : Fragment() { private var _binding: FragmentConfirmRestaurantRegistrationBinding? = null private val binding get() = _binding!! private val navArgs by navArgs() + private val groupId by lazy { navArgs.groupId } private lateinit var mapView: MapView @@ -52,7 +53,10 @@ class ConfirmRestaurantRegistrationFragment : Fragment() { binding.selectButton.setOnClickListener { val action = ConfirmRestaurantRegistrationFragmentDirections - .actionConfirmRestaurantRegistrationFragmentToRegisterRestaurantFragment(navArgs.restaurantLocationInfo) + .actionConfirmRestaurantRegistrationFragmentToRegisterRestaurantFragment( + groupId, + navArgs.restaurantLocationInfo + ) findNavController().navigate(action) } diff --git a/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/RegisterRestaurantFragment.kt b/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/RegisterRestaurantFragment.kt index 090ccd7d..2462fe80 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/RegisterRestaurantFragment.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/RegisterRestaurantFragment.kt @@ -49,6 +49,7 @@ class RegisterRestaurantFragment : BaseFragment() { private val viewModel: RegisterRestaurantViewModel by viewModels() private val navArgs by navArgs() + private val groupId by lazy { navArgs.groupId } private val foodCategoryDialog by lazy { FoodCategoryBottomSheetDialog { selectedItem -> @@ -341,7 +342,6 @@ class RegisterRestaurantFragment : BaseFragment() { MediaType.parse("image/png"), imageFile ) - val body = MultipartBody.Part.createFormData( "pictures", @@ -358,6 +358,7 @@ class RegisterRestaurantFragment : BaseFragment() { lifecycleScope.launch(Dispatchers.IO) { viewModel.registerRestaurant( pictures, + groupId, navArgs.restaurantLocationInfo ?: throw Exception() ) { restaurantId -> diff --git a/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/SearchRestaurantLocationInfoFragment.kt b/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/SearchRestaurantLocationInfoFragment.kt index f7b8829c..bf0ced5d 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/SearchRestaurantLocationInfoFragment.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/SearchRestaurantLocationInfoFragment.kt @@ -1,6 +1,7 @@ package org.gdsc.presentation.view.restaurantregistration import android.os.Bundle +import android.util.Log import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View @@ -9,6 +10,7 @@ import androidx.annotation.DrawableRes import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint @@ -29,6 +31,10 @@ class SearchRestaurantLocationInfoFragment : Fragment() { private var _binding: FragmentSearchRestaurantLocationInfoBinding? = null private val binding get() = _binding!! private val viewModel: SearchRestaurantLocationInfoViewModel by viewModels() + + private val navArgs: SearchRestaurantLocationInfoFragmentArgs by navArgs() + private val groupId by lazy { navArgs.groupId } + private val adapter by lazy { RestaurantLocationInfoAdapter { viewLifecycleOwner.lifecycleScope.launch { @@ -36,8 +42,9 @@ class SearchRestaurantLocationInfoFragment : Fragment() { val action = SearchRestaurantLocationInfoFragmentDirections .actionSearchRestaurantLocationInfoFragmentToConfirmRestaurantRegistrationFragment( + groupId, canRegister, - it + it, ) findNavController().navigate(action) } diff --git a/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/viewmodel/RegisterRestaurantViewModel.kt b/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/viewmodel/RegisterRestaurantViewModel.kt index 2a051002..e540d895 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/viewmodel/RegisterRestaurantViewModel.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/restaurantregistration/viewmodel/RegisterRestaurantViewModel.kt @@ -154,6 +154,7 @@ class RegisterRestaurantViewModel @Inject constructor( fun registerRestaurant( pictures: List, + groupId: Int, restaurantLocationInfo: RestaurantLocationInfo, actionAfterRegisterSuccess: (String) -> Unit = {} ) { @@ -170,7 +171,8 @@ class RegisterRestaurantViewModel @Inject constructor( recommendMenu = recommendMenuListState.value.joinToString(" ") { "#$it" }, - restaurantLocationAggregateIdg = restaurantLocationInfoId + restaurantLocationAggregateIdg = restaurantLocationInfoId, + groupId = groupId, ) actionAfterRegisterSuccess(restaurantId) diff --git a/presentation/src/main/java/org/gdsc/presentation/view/webview/SpecificWebViewFragment.kt b/presentation/src/main/java/org/gdsc/presentation/view/webview/SpecificWebViewFragment.kt index bd7646cc..49579132 100644 --- a/presentation/src/main/java/org/gdsc/presentation/view/webview/SpecificWebViewFragment.kt +++ b/presentation/src/main/java/org/gdsc/presentation/view/webview/SpecificWebViewFragment.kt @@ -57,7 +57,7 @@ class SpecificWebViewFragment : Fragment() { parentActivity.slideDownBottomNavigationView() }, { - parentActivity.navigateToEditRestaurantInfo(it) +// parentActivity.navigateToEditRestaurantInfo(it) }, { repeatWhenUiStarted { diff --git a/presentation/src/main/res/drawable/ic_apple.xml b/presentation/src/main/res/drawable/ic_apple.xml new file mode 100644 index 00000000..aaed5892 --- /dev/null +++ b/presentation/src/main/res/drawable/ic_apple.xml @@ -0,0 +1,9 @@ + + + diff --git a/presentation/src/main/res/drawable/ic_jmt_logo_grey.xml b/presentation/src/main/res/drawable/ic_jmt_logo_grey.xml new file mode 100644 index 00000000..afc5705d --- /dev/null +++ b/presentation/src/main/res/drawable/ic_jmt_logo_grey.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/presentation/src/main/res/drawable/ic_jmt_logo_main.xml b/presentation/src/main/res/drawable/ic_jmt_logo_main.xml new file mode 100644 index 00000000..db319929 --- /dev/null +++ b/presentation/src/main/res/drawable/ic_jmt_logo_main.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/presentation/src/main/res/drawable/ic_jmt_logo_title_main.xml b/presentation/src/main/res/drawable/ic_jmt_logo_title_main.xml new file mode 100644 index 00000000..ee28d6d2 --- /dev/null +++ b/presentation/src/main/res/drawable/ic_jmt_logo_title_main.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/presentation/src/main/res/drawable/ic_jmt_logo_title_white.xml b/presentation/src/main/res/drawable/ic_jmt_logo_title_white.xml new file mode 100644 index 00000000..7814d9ca --- /dev/null +++ b/presentation/src/main/res/drawable/ic_jmt_logo_title_white.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/presentation/src/main/res/drawable/ic_jmt_logo_white.xml b/presentation/src/main/res/drawable/ic_jmt_logo_white.xml new file mode 100644 index 00000000..0dc31c61 --- /dev/null +++ b/presentation/src/main/res/drawable/ic_jmt_logo_white.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/presentation/src/main/res/drawable/jmt_logo_small.xml b/presentation/src/main/res/drawable/jmt_logo_small.xml deleted file mode 100644 index 388625a3..00000000 --- a/presentation/src/main/res/drawable/jmt_logo_small.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/presentation/src/main/res/drawable/jmt_splash_logo.xml b/presentation/src/main/res/drawable/jmt_splash_logo.xml deleted file mode 100644 index 7990b4a3..00000000 --- a/presentation/src/main/res/drawable/jmt_splash_logo.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/presentation/src/main/res/layout/activity_splash.xml b/presentation/src/main/res/layout/activity_splash.xml index 0f2b7bcd..2e9c865e 100644 --- a/presentation/src/main/res/layout/activity_splash.xml +++ b/presentation/src/main/res/layout/activity_splash.xml @@ -4,34 +4,47 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="@color/main500" tools:context=".login.SplashActivity"> - + android:layout_height="wrap_content" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent"/> + app:layout_constraintBottom_toTopOf="@+id/titls"/> + + + app:layout_constraintTop_toBottomOf="@+id/barrie"/> diff --git a/presentation/src/main/res/layout/fragment_home.xml b/presentation/src/main/res/layout/fragment_home.xml index 959a44f5..49bdf6d8 100644 --- a/presentation/src/main/res/layout/fragment_home.xml +++ b/presentation/src/main/res/layout/fragment_home.xml @@ -13,7 +13,7 @@ android:layout_width="match_parent" android:layout_height="65dp" android:layout_weight="0" - android:paddingHorizontal="@dimen/default_spacing" + android:paddingStart="@dimen/default_spacing" android:background="@color/white"> diff --git a/presentation/src/main/res/layout/fragment_login.xml b/presentation/src/main/res/layout/fragment_login.xml index ba9ae47b..0f709fac 100644 --- a/presentation/src/main/res/layout/fragment_login.xml +++ b/presentation/src/main/res/layout/fragment_login.xml @@ -6,19 +6,18 @@ android:layout_height="match_parent" tools:context=".login.LoginFragment"> - + android:layout_height="wrap_content" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent"/> @@ -27,12 +26,11 @@ android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="16dp" - android:src="@drawable/login_jmt_title" + android:src="@drawable/ic_jmt_logo_title_main" + android:layout_marginBottom="16dp" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintBottom_toBottomOf="parent" /> + app:layout_constraintBottom_toTopOf="@+id/barrie"/> + android:layout_marginBottom="16dp" + app:layout_constraintBottom_toTopOf="@+id/apple_login_btn"> - + android:minHeight="56dp" + android:gravity="center" + android:clickable="true" + android:layout_marginHorizontal="20dp" + android:backgroundTint="@color/black" + android:background="@drawable/bg_rounded_border_8_grey200" + android:orientation="horizontal" + android:layout_marginBottom="56dp" + app:layout_constraintBottom_toBottomOf="parent"> + + + + \ No newline at end of file diff --git a/presentation/src/main/res/layout/fragment_registered_restaurant.xml b/presentation/src/main/res/layout/fragment_registered_restaurant.xml index 554af6c2..7f710640 100644 --- a/presentation/src/main/res/layout/fragment_registered_restaurant.xml +++ b/presentation/src/main/res/layout/fragment_registered_restaurant.xml @@ -85,11 +85,10 @@ android:orientation="vertical"> diff --git a/presentation/src/main/res/layout/item_empty_.xml b/presentation/src/main/res/layout/item_empty_.xml index 33c32198..30e41bf1 100644 --- a/presentation/src/main/res/layout/item_empty_.xml +++ b/presentation/src/main/res/layout/item_empty_.xml @@ -5,15 +5,14 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> + app:layout_constraintStart_toStartOf="parent" /> + + + + + + + + + + + + + + + + + + + @@ -183,6 +223,9 @@ android:name="org.gdsc.presentation.view.mypage.restaurantdetail.RestaurantDetailFragment" android:label="fragment_restaurant_detail" tools:layout="@layout/fragment_restaurant_detail" > +