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 all 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
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package com.terning.data.datasource

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

interface HomeDataSource {
suspend fun getTodayIntern(): BaseResponse<List<HomeTodayInternResponseDto>>

suspend fun getRecommendIntern(
sortBy: String,
startYear: Int,
startMonth: Int
): BaseResponse<List<HomeRecommendInternResponseDto>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ 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.dto.response.HomeTodayInternResponseDto
import com.terning.data.service.HomeService
import javax.inject.Inject
Expand All @@ -11,4 +12,15 @@ class HomeDataSourceImpl @Inject constructor(
) : HomeDataSource {
override suspend fun getTodayIntern(): BaseResponse<List<HomeTodayInternResponseDto>> =
homeService.getHomeTodayIntern()

override suspend fun getRecommendIntern(
sortBy: String,
startYear: Int,
startMonth: Int
): BaseResponse<List<HomeRecommendInternResponseDto>> =
homeService.getRecommendIntern(
sortBy = sortBy,
startYear = startYear,
startMonth = startMonth
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
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("intershipAnnouncementId")
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(): HomeRecommendInternModel =
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
@@ -1,6 +1,7 @@
package com.terning.data.repositoryimpl

import com.terning.data.datasource.HomeDataSource
import com.terning.domain.entity.response.HomeRecommendInternModel
import com.terning.domain.entity.response.HomeTodayInternModel
import com.terning.domain.repository.HomeRepository
import javax.inject.Inject
Expand All @@ -14,4 +15,19 @@ class HomeRepositoryImpl @Inject constructor(
it.toHomeTodayInternList()
}
}

override suspend fun getRecommendIntern(
sortBy: String,
startYear: Int,
startMonth: Int
): Result<List<HomeRecommendInternModel>> =
runCatching {
homeDataSource.getRecommendIntern(
sortBy = sortBy,
startYear = startYear,
startMonth = startMonth
).result.map {
it.toRecommendInternEntity()
}
}
}
11 changes: 10 additions & 1 deletion data/src/main/java/com/terning/data/service/HomeService.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
package com.terning.data.service

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

interface HomeService {
@GET("api/v1/home/today")
suspend fun getHomeTodayIntern(): BaseResponse<List<HomeTodayInternResponseDto>>
}

@GET("api/v1/home")
suspend fun getRecommendIntern(
@Query("sortBy") sortBy: String,
@Query("startYear") startYear: Int,
@Query("startMonth") startMonth: Int,
): BaseResponse<List<HomeRecommendInternResponseDto>>
}
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
@@ -1,7 +1,14 @@
package com.terning.domain.repository

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

interface HomeRepository {
suspend fun getHomeTodayInternList(): Result<List<HomeTodayInternModel>>

suspend fun getRecommendIntern(
sortBy: String,
startYear: Int,
startMonth: Int
): Result<List<HomeRecommendInternModel>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ fun ChangeFilterScreen(
viewModel: HomeViewModel = hiltViewModel(),
) {
val isGradeButtonValid = remember {
mutableStateOf(viewModel.userName.internFilter?.grade != null)
mutableStateOf(viewModel.userName.value.internFilter?.grade != null)
}

val isWorkingPeriodButtonValid = remember {
mutableStateOf(viewModel.userName.internFilter?.workingPeriod != null)
mutableStateOf(viewModel.userName.value.internFilter?.workingPeriod != null)
}

Scaffold(
Expand Down Expand Up @@ -77,9 +77,8 @@ fun ChangeFilterScreen(
)
ChangeFilteringRadioGroup(
filterType = 0,
internFilterData = viewModel.userName.internFilter,
internFilterData = viewModel.userName.value.internFilter,
onButtonClick = {
viewModel.setGrade(it)
isGradeButtonValid.value = true
}
)
Expand All @@ -105,9 +104,8 @@ fun ChangeFilterScreen(
)
ChangeFilteringRadioGroup(
filterType = 1,
internFilterData = viewModel.userName.internFilter,
internFilterData = viewModel.userName.value.internFilter,
onButtonClick = {
viewModel.setWorkingPeriod(it)
isWorkingPeriodButtonValid.value = true
}
)
Expand Down
75 changes: 69 additions & 6 deletions feature/src/main/java/com/terning/feature/home/home/HomeRoute.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.terning.feature.home.home
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
Expand All @@ -11,6 +12,7 @@ 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
Expand All @@ -33,18 +35,23 @@ 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.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.domain.entity.response.HomeTodayInternModel
import com.terning.feature.R
import com.terning.feature.home.changefilter.navigation.navigateChangeFilter
import com.terning.feature.home.home.component.HomeFilteringEmptyIntern
import com.terning.feature.home.home.component.HomeFilteringScreen
import com.terning.feature.home.home.component.HomeRecommendEmptyIntern
import com.terning.feature.home.home.component.HomeTodayEmptyIntern
import com.terning.feature.home.home.component.HomeTodayIntern
import com.terning.feature.home.home.model.UserNameState
Expand All @@ -55,7 +62,7 @@ const val NAME_END_LENGTH = 12
@Composable
fun HomeRoute(
navController: NavHostController,
viewModel: HomeViewModel = hiltViewModel()
viewModel: HomeViewModel = hiltViewModel(),
) {
val currentSortBy: MutableState<Int> = remember {
mutableIntStateOf(0)
Expand All @@ -65,6 +72,7 @@ fun HomeRoute(
val context = LocalContext.current

val homeTodayState by viewModel.homeTodayState.collectAsStateWithLifecycle()
val homeRecommendInternState by viewModel.homeRecommendInternState.collectAsStateWithLifecycle()

LaunchedEffect(viewModel.homeSideEffect, lifecycleOwner) {
viewModel.homeSideEffect.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle)
Expand All @@ -84,10 +92,31 @@ fun HomeRoute(
else -> emptyList()
}

val homeRecommendInternList = when (homeRecommendInternState) {
is UiState.Success -> {
(homeRecommendInternState as UiState.Success<List<HomeRecommendInternModel>>).data
}

else -> emptyList()
}

val userNameState = viewModel.userName

LaunchedEffect(currentSortBy) {
with(userNameState.value.internFilter) {
viewModel.getRecommendInternsData(
sortBy = currentSortBy.value,
startYear = this?.startYear ?: viewModel.currentYear,
startMonth = this?.startMonth ?: viewModel.currentMonth,
)
}
}

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

Expand All @@ -96,6 +125,7 @@ fun HomeRoute(
fun HomeScreen(
currentSortBy: MutableState<Int>,
homeTodayInternList: List<HomeTodayInternModel>,
recommendInternList: List<HomeRecommendInternModel>,
onChangeFilterClick: () -> Unit,
viewModel: HomeViewModel = hiltViewModel(),
) {
Expand Down Expand Up @@ -135,7 +165,7 @@ fun HomeScreen(
modifier = Modifier
.padding(bottom = 16.dp)
) {
ShowMainTitleWithName(userNameState)
ShowMainTitleWithName(userNameState.value)
ShowTodayIntern(homeTodayInternList = homeTodayInternList)
}
}
Expand All @@ -145,7 +175,7 @@ fun HomeScreen(
.background(White)
) {
ShowRecommendTitle()
ShowInternFilter(userNameState = userNameState, onChangeFilterClick)
ShowInternFilter(userNameState = userNameState.value, onChangeFilterClick)

HorizontalDivider(
thickness = 4.dp,
Expand All @@ -169,14 +199,22 @@ fun HomeScreen(
}
}
}

if (recommendInternList.isNotEmpty()) {
items(recommendInternList.size) { index ->
ShowRecommendIntern(homeRecommendInternModel = recommendInternList[index])
}
}
}

if (userNameState.internFilter == null) {
if (userNameState.value.internFilter == null) {
HomeFilteringEmptyIntern(
modifier = Modifier
.padding(horizontal = 24.dp)
.fillMaxSize()
)
} else if (recommendInternList.isEmpty()) {
HomeRecommendEmptyIntern()
}
}
}
Expand Down Expand Up @@ -255,4 +293,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,
)
}
}
Loading
Loading