Skip to content

Commit

Permalink
#23 [FEAT] 착한 밥상 조회 api 연결
Browse files Browse the repository at this point in the history
  • Loading branch information
gaeulzzang committed Nov 8, 2024
1 parent 0793bfb commit d2e3204
Show file tree
Hide file tree
Showing 13 changed files with 204 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.hackathon.alddeul_babsang.app.di

import com.hackathon.alddeul_babsang.data.datasource.BabsangDataSource
import com.hackathon.alddeul_babsang.data.datasource.ExampleDataSource
import com.hackathon.alddeul_babsang.data.datasource.UserPreferencesDataSource
import com.hackathon.alddeul_babsang.data.datasourceimpl.BabsangDataSourceImpl
import com.hackathon.alddeul_babsang.data.datasourceimpl.ExampleDataSourceImpl
import com.hackathon.alddeul_babsang.data.datasourceimpl.UserPreferencesDataSourceImpl
import dagger.Binds
Expand All @@ -21,4 +23,8 @@ abstract class DataSourceModule {
@Binds
@Singleton
abstract fun bindUserPreferencesDataSource(userPreferencesDataSourceImpl: UserPreferencesDataSourceImpl): UserPreferencesDataSource

@Binds
@Singleton
abstract fun bindBabsangDataSource(babsangDataSourceImpl: BabsangDataSourceImpl): BabsangDataSource
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.hackathon.alddeul_babsang.app.di

import com.hackathon.alddeul_babsang.data.repositoryimpl.BabsangRepositoryImpl
import com.hackathon.alddeul_babsang.data.repositoryimpl.ExampleRepositoryImpl
import com.hackathon.alddeul_babsang.data.repositoryimpl.UserPreferencesRepositoryImpl
import com.hackathon.alddeul_babsang.domain.repository.BabsangRepository
import com.hackathon.alddeul_babsang.domain.repository.ExampleRepository
import com.hackathon.alddeul_babsang.domain.repository.UserPreferencesRepository
import dagger.Binds
Expand All @@ -21,4 +23,8 @@ abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindUserPreferencesRepository(userPreferencesRepositoryImpl: UserPreferencesRepositoryImpl): UserPreferencesRepository

@Binds
@Singleton
abstract fun bindBabsangRepository(babsangRepositoryImpl: BabsangRepositoryImpl): BabsangRepository
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.hackathon.alddeul_babsang.app.di

import com.hackathon.alddeul_babsang.data.service.BabsangApiService
import com.sopt.data.service.ExampleApiService
import dagger.Module
import dagger.Provides
Expand All @@ -17,4 +18,10 @@ object ServiceModule {
fun provideExampleService(
@AlddeulRetrofit retrofit: Retrofit
): ExampleApiService = retrofit.create(ExampleApiService::class.java)

@Provides
@Singleton
fun provideBabsangService(
@AlddeulRetrofit retrofit: Retrofit
): BabsangApiService = retrofit.create(BabsangApiService::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.hackathon.alddeul_babsang.core_ui.component

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.hackathon.alddeul_babsang.core_ui.theme.Orange900

@Composable
fun LoadingCircleIndicator() {
Box(modifier = Modifier.fillMaxSize()) {
CircularProgressIndicator(
modifier = Modifier
.align(Alignment.Center),
color = Orange900
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.hackathon.alddeul_babsang.data.datasource

import com.hackathon.alddeul_babsang.data.dto.BaseResponse
import com.hackathon.alddeul_babsang.data.dto.response.ResponseBabsangDto

interface BabsangDataSource {
suspend fun getStores(): BaseResponse<List<ResponseBabsangDto>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.hackathon.alddeul_babsang.data.datasourceimpl

import com.hackathon.alddeul_babsang.data.datasource.BabsangDataSource
import com.hackathon.alddeul_babsang.data.dto.BaseResponse
import com.hackathon.alddeul_babsang.data.dto.response.ResponseBabsangDto
import com.hackathon.alddeul_babsang.data.service.BabsangApiService
import javax.inject.Inject

class BabsangDataSourceImpl @Inject constructor(
private val babsangApiService: BabsangApiService
) : BabsangDataSource {
override suspend fun getStores(): BaseResponse<List<ResponseBabsangDto>> {
return babsangApiService.getStores()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.hackathon.alddeul_babsang.data.dto.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.io.Serial

@Serializable
data class ResponseBabsangDto (
@SerialName("id") val id: Long,
@SerialName("name") val name: String,
@SerialName("category") val category: String,
@SerialName("address") val address: String,
@SerialName("contact") val contact: String,
@SerialName("imageUrl") val imageUrl: String? = null,
@SerialName("favorite") val favorite: Boolean,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.hackathon.alddeul_babsang.data.repositoryimpl

import com.hackathon.alddeul_babsang.data.datasource.BabsangDataSource
import com.hackathon.alddeul_babsang.data.dto.response.ResponseBabsangDto
import com.hackathon.alddeul_babsang.domain.repository.BabsangRepository
import javax.inject.Inject

class BabsangRepositoryImpl @Inject constructor(
private val babsangDataSource: BabsangDataSource
) : BabsangRepository{
override suspend fun getStores(): Result<List<ResponseBabsangDto>> {
return runCatching {
babsangDataSource.getStores().result ?: emptyList()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.hackathon.alddeul_babsang.data.service

import com.hackathon.alddeul_babsang.data.dto.BaseResponse
import com.hackathon.alddeul_babsang.data.dto.response.ResponseBabsangDto
import com.sopt.data.service.ApiKeyStorage.STORES
import retrofit2.http.GET

interface BabsangApiService {
@GET("/$STORES")
suspend fun getStores(): BaseResponse<List<ResponseBabsangDto>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.hackathon.alddeul_babsang.domain.repository

import com.hackathon.alddeul_babsang.data.dto.response.ResponseBabsangDto

interface BabsangRepository {
suspend fun getStores(): Result<List<ResponseBabsangDto>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@ import com.hackathon.alddeul_babsang.core_ui.theme.Orange900
import com.hackathon.alddeul_babsang.core_ui.theme.body2Regular
import com.hackathon.alddeul_babsang.core_ui.theme.body4Regular
import com.hackathon.alddeul_babsang.core_ui.theme.head4Bold
import com.hackathon.alddeul_babsang.data.dto.response.ResponseBabsangDto
import com.hackathon.alddeul_babsang.domain.entity.LikesEntity
import com.hackathon.alddeul_babsang.presentation.profile.screen.LikeItem

@Composable
fun BabsangItem(
onClick: () -> Unit = {},
data: LikesEntity
data: ResponseBabsangDto
) {
var isFavorite by remember { mutableStateOf(data.favorite) }

Expand Down Expand Up @@ -71,7 +72,7 @@ fun BabsangItem(
.clip(RoundedCornerShape(topStart = 14.dp, topEnd = 14.dp))
) {
// AsyncImage 로드
ReplaceImage2(data.codeName, data.avatar)
ReplaceImage2(data.category, data.imageUrl)
Image(
painter = painterResource(heartIconId),
contentDescription = null,
Expand All @@ -94,7 +95,7 @@ fun BabsangItem(
)
Spacer(modifier = Modifier.width(15.dp))
Text(
text = data.codeName,
text = data.category,
style = body2Regular,
color = Orange800,
modifier = Modifier
Expand All @@ -111,7 +112,7 @@ fun BabsangItem(
)
Spacer(modifier = Modifier.height(7.dp))
Text(
text = data.phone,
text = data.contact,
style = body4Regular,
color = Gray300,
modifier = Modifier.padding(start = 20.dp, bottom = 20.dp)
Expand All @@ -122,9 +123,9 @@ fun BabsangItem(
@Composable
fun ReplaceImage2(codeName: String, imageUrl: String?) {
val imageId = when (codeName) {
"경양식/일식" -> R.drawable.ic_japanese_food
"한식" -> R.drawable.ic_korean_food
"중식" -> R.drawable.ic_chinese_food
"WESTERN_JAPANESE" -> R.drawable.ic_japanese_food
"KOREAN" -> R.drawable.ic_korean_food
"CHINESE" -> R.drawable.ic_chinese_food
else -> R.drawable.ic_etc_food
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.hackathon.alddeul_babsang.presentation.babsang.screen

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
Expand All @@ -11,16 +10,16 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.Alignment
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
Expand All @@ -29,24 +28,31 @@ import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.hackathon.alddeul_babsang.R
import com.hackathon.alddeul_babsang.core_ui.component.LoadingCircleIndicator
import com.hackathon.alddeul_babsang.core_ui.theme.AlddeulBabsangTheme
import com.hackathon.alddeul_babsang.core_ui.theme.Gray900
import com.hackathon.alddeul_babsang.core_ui.theme.Orange800
import com.hackathon.alddeul_babsang.core_ui.theme.Orange900
import com.hackathon.alddeul_babsang.core_ui.theme.White
import com.hackathon.alddeul_babsang.core_ui.theme.head4Bold
import com.hackathon.alddeul_babsang.core_ui.theme.head6Semi
import com.hackathon.alddeul_babsang.presentation.babsang.navigation.BabsangNavigator
import com.hackathon.alddeul_babsang.presentation.report.screen.ReportItem
import com.hackathon.alddeul_babsang.util.UiState

@Composable
fun BabsangRoute(
navigator: BabsangNavigator
) {
val babsangListViewModel: BabsangViewModel = hiltViewModel()
val babsangViewModel: BabsangViewModel = hiltViewModel()
val systemUiController = rememberSystemUiController()

LaunchedEffect(Unit) {
babsangViewModel.getBabsang()
}

SideEffect {
systemUiController.setStatusBarColor(
color = White
Expand All @@ -55,7 +61,7 @@ fun BabsangRoute(

BabsangScreen(
onItemClick = { id -> navigator.navigateDetail(id) },
babsangViewModel = babsangListViewModel,
babsangViewModel = babsangViewModel,
)
}

Expand All @@ -65,6 +71,8 @@ fun BabsangScreen(
onItemClick: (Long) -> Unit = {},
babsangViewModel: BabsangViewModel,
) {
val getBabsangState by babsangViewModel.getBabsangState.collectAsStateWithLifecycle(UiState.Empty)

Scaffold(
topBar = {
CenterAlignedTopAppBar(
Expand Down Expand Up @@ -121,12 +129,49 @@ fun BabsangScreen(
style = head6Semi
)
}
items(babsangViewModel.mockBabsang) { item ->
BabsangItem(
onClick = { onItemClick(item.id) },
data = item
)
Spacer(modifier = Modifier.height(16.dp))
when (getBabsangState) {
is UiState.Loading -> {
item {
LoadingCircleIndicator()
}
}

is UiState.Success -> {
val data = (getBabsangState as UiState.Success).data
if (data.isEmpty()) {
item {
Text(
text = "밥상 데이터가 없어요",
style = head6Semi,
color = Orange900,
modifier = Modifier.padding(vertical = 20.dp)
)
}
} else {
itemsIndexed(data) { index, item ->
BabsangItem(
onClick = { onItemClick(item.id) },
data = item
)
if (index != data.size - 1) {
Spacer(modifier = Modifier.height(16.dp))
}
}
}
}

is UiState.Failure -> {
item {
Text(
text = (getBabsangState as UiState.Failure).msg,
style = head6Semi,
color = Orange900,
modifier = Modifier.padding(vertical = 20.dp)
)
}
}

else -> {}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,38 @@
package com.hackathon.alddeul_babsang.presentation.babsang.screen

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.hackathon.alddeul_babsang.data.dto.response.ResponseBabsangDto
import com.hackathon.alddeul_babsang.domain.entity.BabsangRecommendEntity
import com.hackathon.alddeul_babsang.domain.entity.LikesEntity
import com.hackathon.alddeul_babsang.domain.repository.BabsangRepository
import com.hackathon.alddeul_babsang.util.UiState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class BabsangViewModel @Inject constructor() : ViewModel() {
class BabsangViewModel @Inject constructor(
private val babsangRepository: BabsangRepository
) : ViewModel() {
private val _getBabsangState =
MutableStateFlow<UiState<List<ResponseBabsangDto>>>(UiState.Empty)
val getBabsangState: StateFlow<UiState<List<ResponseBabsangDto>>> = _getBabsangState

fun getBabsang() = viewModelScope.launch {
_getBabsangState.emit(UiState.Loading)
babsangRepository.getStores().fold(
onSuccess = {
_getBabsangState.emit(UiState.Success(it))
},
onFailure = {
_getBabsangState.emit(UiState.Failure(it.message.toString()))
}
)
}

val mockBabsangRecommendList = listOf(
BabsangRecommendEntity(
id = 1,
Expand Down

0 comments on commit d2e3204

Please sign in to comment.