Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT/#77] 홈 뷰 / 맞춤 공고 서버 통신 구현 #86

Merged
merged 20 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
0a582b5
[CHORE/#77] 데이터 형식 수정
Hyobeen-Park Jul 15, 2024
8da6f01
Merge remote-tracking branch 'origin/develop' into feat/#77-home-reco…
Hyobeen-Park Jul 15, 2024
8ccdc92
[FEAT/#77] 서버통신 틀 구현
Hyobeen-Park Jul 15, 2024
37dfa12
[FEAT/#77] 서버 통신 로직 구현
Hyobeen-Park Jul 15, 2024
fde4350
[FEAT/#77] 데이터 받아오는 로직 수정
Hyobeen-Park Jul 15, 2024
6b3d8f2
Merge remote-tracking branch 'origin/develop' into feat/#77-home-reco…
Hyobeen-Park Jul 15, 2024
3cf879a
[CHORE/#77] 더미 데이터 추가
Hyobeen-Park Jul 15, 2024
f95c598
[CHORE/#77] 코드 정리
Hyobeen-Park Jul 15, 2024
d5d7ddd
[CHORE/#77] 네이밍 수정
Hyobeen-Park Jul 15, 2024
583faee
[FEAT/#77] sideEffect 적용
Hyobeen-Park Jul 15, 2024
e4348f6
[CHORE/#77] 코드 정리
Hyobeen-Park Jul 16, 2024
ba35b80
[MOD/#77] 수정된 API 명세서 반영
Hyobeen-Park Jul 17, 2024
4956446
Merge remote-tracking branch 'origin/develop' into feat/#77-home-reco…
Hyobeen-Park Jul 17, 2024
05a686f
[CHORE/#77] 어노테이션 및 모듈 네이밍 수정
Hyobeen-Park Jul 17, 2024
60c003a
Merge remote-tracking branch 'origin/develop' into feat/#77-home-reco…
Hyobeen-Park Jul 17, 2024
df56048
Merge remote-tracking branch 'origin/develop' into feat/#77-home-reco…
Hyobeen-Park Jul 17, 2024
c1ccb62
[CHORE/#77] 명세서에 맞게 변수 수정 및 conflict 해결
Hyobeen-Park Jul 17, 2024
e6d2228
[CHORE/#77] dto 수정
Hyobeen-Park Jul 17, 2024
35de310
Merge remote-tracking branch 'origin/develop' into feat/#77-home-reco…
Hyobeen-Park Jul 17, 2024
65a599f
[CHORE/#77] enum class 분리
Hyobeen-Park Jul 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/src/main/java/com/terning/point/di/DataSourceModule.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.terning.point.di

import com.terning.data.datasource.HomeDataSource
import com.terning.data.datasource.MockDataSource
import com.terning.data.datasourceimpl.HomeDataSourceImpl
import com.terning.data.datasourceimpl.MockDataSourceImpl
import dagger.Binds
import dagger.Module
Expand All @@ -15,4 +17,8 @@ abstract class DataSourceModule {
@Binds
@Singleton
abstract fun bindMockDataSource(mockDataSourceImpl: MockDataSourceImpl): MockDataSource

@Binds
@Singleton
abstract fun bindRecommendInternDataSource(internDataSourceImpl: HomeDataSourceImpl): HomeDataSource
}
6 changes: 6 additions & 0 deletions app/src/main/java/com/terning/point/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.terning.point.di

import com.terning.data.repositoryimpl.HomeRepositoryImpl
import com.terning.data.repositoryimpl.MockRepositoryImpl
import com.terning.domain.repository.HomeRepository
import com.terning.domain.repository.MockRepository
import dagger.Binds
import dagger.Module
Expand All @@ -15,4 +17,8 @@ abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindMockRepository(mockRepositoryImpl: MockRepositoryImpl): MockRepository

@Binds
@Singleton
abstract fun bindInternRepository(homeRepositoryImpl: HomeRepositoryImpl): HomeRepository
}
5 changes: 5 additions & 0 deletions app/src/main/java/com/terning/point/di/ServiceModule.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.terning.point.di

import com.terning.data.service.HomeService
import com.terning.data.service.MockService
import com.terning.point.di.qualifier.OPEN
import dagger.Module
Expand All @@ -18,4 +19,8 @@ object ServiceModule {
fun provideMockService(@OPEN retrofit: Retrofit): MockService =
retrofit.create(MockService::class.java)

@Provides
@Singleton
fun provideInternService(@OPEN retrofit: Retrofit): HomeService =
retrofit.create(HomeService::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.terning.data.datasource

import com.terning.data.dto.BaseResponse
import com.terning.data.dto.response.HomeRecommendInternResponseDto

interface HomeDataSource {
suspend fun getRecommendIntern(sortBy: String): BaseResponse<HomeRecommendInternResponseDto>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
suspend fun getRecommendIntern(sortBy: String): BaseResponse<HomeRecommendInternResponseDto>
suspend fun getRecommendIntern(sortBy: String): BaseResponse<List<HomeRecommendInternResponseDto>>

API 명세서 확인해봤을땐 BaseResponseresult가 직접 리스트를 관리하는 것으로 보여서 이 방식대로 수정해야되지 않나 싶네요,,

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하!!! 감사합니다!!

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.terning.data.datasourceimpl

import com.terning.data.datasource.HomeDataSource
import com.terning.data.dto.BaseResponse
import com.terning.data.dto.response.HomeRecommendInternResponseDto
import com.terning.data.service.HomeService
import javax.inject.Inject

class HomeDataSourceImpl @Inject constructor(
private val homeService: HomeService
) : HomeDataSource {
override suspend fun getRecommendIntern(sortBy: String): BaseResponse<HomeRecommendInternResponseDto> =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BaseResponse로 감싸기 참고합니당!! 히

homeService.getRecommendIntern(sortBy = sortBy)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.terning.data.dto.response

import com.terning.domain.entity.response.HomeRecommendInternModel
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class HomeRecommendInternResponseDto(
@SerialName("internshipAnnouncementId")
val internshipAnnouncementId: Long,
@SerialName("title")
val title: String,
@SerialName("dDay")
val dDay: String,
@SerialName("workingPeriod")
val workingPeriod: String,
@SerialName("companyImage")
val companyImage: String,
@SerialName("isScrapped")
val isScrapped: Boolean,
) {
fun toRecommendInternEntity(): List<HomeRecommendInternModel> = listOf(
HomeRecommendInternModel(
internshipAnnouncementId = this.internshipAnnouncementId,
title = this.title,
dDay = this.dDay,
workingPeriod = this.workingPeriod,
companyImage = this.companyImage,
isScrapped = this.isScrapped,
)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.terning.data.repositoryimpl

import com.terning.data.datasource.HomeDataSource
import com.terning.domain.entity.response.HomeRecommendInternModel
import com.terning.domain.repository.HomeRepository
import javax.inject.Inject

class HomeRepositoryImpl @Inject constructor(
private val homeDataSource: HomeDataSource,
) : HomeRepository {
override suspend fun getRecommendIntern(sortBy: String): Result<List<HomeRecommendInternModel>> =
runCatching {
homeDataSource.getRecommendIntern(sortBy = sortBy).result.toRecommendInternEntity()
}
}
14 changes: 14 additions & 0 deletions data/src/main/java/com/terning/data/service/HomeService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.terning.data.service

import com.terning.data.dto.BaseResponse
import com.terning.data.dto.response.HomeRecommendInternResponseDto
import retrofit2.http.GET
import retrofit2.http.Query

interface HomeService {
@GET("api/v1/home")
suspend fun getRecommendIntern(
@Query("sortBy") sortBy: String,
): BaseResponse<HomeRecommendInternResponseDto>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기 줄바꿈 없애주시면 완벽할것가탕여 ㅎㅎ

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.terning.domain.entity.response

data class HomeRecommendInternModel(
val internshipAnnouncementId: Long,
val title: String,
val dDay: String,
val workingPeriod: String,
val companyImage: String,
val isScrapped: Boolean,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.terning.domain.repository

import com.terning.domain.entity.response.HomeRecommendInternModel

interface HomeRepository {
suspend fun getRecommendIntern(sortBy: String): Result<List<HomeRecommendInternModel>>
}
97 changes: 79 additions & 18 deletions feature/src/main/java/com/terning/feature/home/home/HomeRoute.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,40 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.flowWithLifecycle
import androidx.navigation.NavHostController
import com.terning.core.designsystem.component.bottomsheet.SortingBottomSheet
import com.terning.core.designsystem.component.button.SortingButton
import com.terning.core.designsystem.component.item.InternItemWithShadow
import com.terning.core.designsystem.component.item.InternItem
import com.terning.core.designsystem.component.topappbar.LogoTopAppBar
import com.terning.core.designsystem.theme.Black
import com.terning.core.designsystem.theme.Grey150
import com.terning.core.designsystem.theme.Grey200
import com.terning.core.designsystem.theme.TerningTheme
import com.terning.core.designsystem.theme.White
import com.terning.core.extension.customShadow
import com.terning.core.extension.toast
import com.terning.core.state.UiState
import com.terning.domain.entity.response.HomeRecommendInternModel
import com.terning.feature.R
import com.terning.feature.home.changefilter.navigation.navigateChangeFilter
import com.terning.feature.home.home.component.HomeFilteringEmptyIntern
Expand All @@ -51,14 +61,50 @@ const val NAME_END_LENGTH = 12

@Composable
fun HomeRoute(
navController: NavHostController
navController: NavHostController,
viewModel: HomeViewModel = hiltViewModel(),
) {
val currentSortBy: MutableState<Int> = remember {
mutableIntStateOf(0)
}

val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current

val recommendInternState by viewModel.recommendInternState.collectAsStateWithLifecycle(
lifecycleOwner = lifecycleOwner
)
LaunchedEffect(viewModel.homeSideEffect, lifecycleOwner) {
viewModel.homeSideEffect.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle)
.collect { sideEffect ->
when (sideEffect) {
is HomeSideEffect.ShowToast -> context.toast(sideEffect.message)
is HomeSideEffect.NavigateToChangeFilter -> navController.navigateChangeFilter()
}
}
}

LaunchedEffect(key1 = currentSortBy) {
viewModel.getRecommendInternsData(currentSortBy.value)

}

var recommendInternList = emptyList<HomeRecommendInternModel>()

when (recommendInternState) {
is UiState.Empty -> {}
is UiState.Loading -> {}
is UiState.Failure -> {}
is UiState.Success -> {
recommendInternList =
(recommendInternState as UiState.Success<List<HomeRecommendInternModel>>).data
}
}

HomeScreen(
currentSortBy,
onChangeFilterClick = { navController.navigateChangeFilter() }
onChangeFilterClick = { navController.navigateChangeFilter() },
recommendInternList = recommendInternList
)
}

Expand All @@ -67,11 +113,11 @@ fun HomeRoute(
fun HomeScreen(
currentSortBy: MutableState<Int>,
onChangeFilterClick: () -> Unit,
recommendInternList: List<HomeRecommendInternModel>,
viewModel: HomeViewModel = hiltViewModel(),
) {
val userNameState = viewModel.userName
val userScrapState by viewModel.scrapData.collectAsStateWithLifecycle()
val recommendInternData by viewModel.recommendInternData.collectAsStateWithLifecycle()
var sheetState by remember { mutableStateOf(false) }

if (sheetState) {
Expand Down Expand Up @@ -142,19 +188,9 @@ fun HomeScreen(
}
}

if (userNameState.internFilter != null && recommendInternData.isNotEmpty()) {
items(recommendInternData.size) { index ->
Box(
modifier = Modifier.padding(horizontal = 24.dp)
) {
InternItemWithShadow(
imageUrl = recommendInternData[index].imgUrl,
title = recommendInternData[index].title,
dateDeadline = recommendInternData[index].dDay.toString(),
workingPeriod = recommendInternData[index].workingPeriod.toString(),
isScraped = recommendInternData[index].isScrapped,
)
}
if (recommendInternList.isNotEmpty()) {
items(recommendInternList.size) { index ->
ShowRecommendIntern(homeRecommendInternModel = recommendInternList[index])
}
}
}
Expand All @@ -165,7 +201,7 @@ fun HomeScreen(
.padding(horizontal = 24.dp)
.fillMaxSize()
)
} else if (recommendInternData.isEmpty()) {
} else if (recommendInternList.isEmpty()) {
HomeRecommendEmptyIntern()
}
}
Expand Down Expand Up @@ -249,4 +285,29 @@ private fun ShowInternFilter(userNameState: UserNameState, onChangeFilterClick:
)
}
}
}

@Composable
private fun ShowRecommendIntern(homeRecommendInternModel: HomeRecommendInternModel) {
Box(
modifier = Modifier
.padding(horizontal = 24.dp)
.customShadow(
color = Grey200,
shadowRadius = 5.dp,
shadowWidth = 1.dp
)
.background(
color = White,
shape = RoundedCornerShape(10.dp)
)
) {
InternItem(
imageUrl = homeRecommendInternModel.companyImage,
title = homeRecommendInternModel.title,
dateDeadline = homeRecommendInternModel.dDay,
workingPeriod = homeRecommendInternModel.workingPeriod,
isScraped = homeRecommendInternModel.isScrapped,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.terning.feature.home.home

import androidx.annotation.StringRes

sealed class HomeSideEffect {
data class ShowToast(@StringRes val message: Int) : HomeSideEffect()
data object NavigateToChangeFilter : HomeSideEffect()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우왕...😗

}
Loading
Loading