Skip to content

Commit

Permalink
[Merge] #79 -> develop
Browse files Browse the repository at this point in the history
[Feat/#79] ํƒ์ƒ‰ ๊ธฐ๋ณธ ๋ทฐ / ์กฐํšŒ์ˆ˜ ๋งŽ์€ ๊ณต๊ณ  ํ†ต์‹ 
  • Loading branch information
arinming authored Jul 16, 2024
2 parents 5eded85 + 4d3990d commit fd5dd93
Show file tree
Hide file tree
Showing 19 changed files with 277 additions and 32 deletions.
7 changes: 7 additions & 0 deletions app/src/main/java/com/terning/point/di/DataSourceModule.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.terning.point.di

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

@Binds
@Singleton
abstract fun bindSearchViewsDataSource(searchViewsDataSourceImpl: SearchDataSourceImpl):
SearchDataSource
}
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,7 +1,9 @@
package com.terning.point.di

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

@Binds
@Singleton
abstract fun bindSearchViewsRepository(searchViewsRepositoryImpl: SearchViewsRepositoryImpl): SearchRepository
}
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,6 +1,7 @@
package com.terning.point.di

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

@Provides
@Singleton
fun provideSearchService(@OPEN retrofit: Retrofit): SearchService =
retrofit.create(SearchService::class.java)
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,13 @@ fun TerningBasicTextField(
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(
onDone = {
keyboardController?.hide()
focusManager.clearFocus()
onDoneAction?.invoke()
if (value.isNotBlank()) {
keyboardController?.hide()
focusManager.clearFocus()
if (onDoneAction != null) {
onDoneAction()
}
}
}
),

Expand Down
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.SearchViewsResponseDto

interface SearchDataSource {
suspend fun getSearchViews(): BaseResponse<SearchViewsResponseDto>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.terning.data.datasourceimpl

import com.terning.data.datasource.SearchDataSource
import com.terning.data.dto.BaseResponse
import com.terning.data.dto.response.SearchViewsResponseDto
import com.terning.data.service.SearchService
import javax.inject.Inject

class SearchDataSourceImpl @Inject constructor(
private val searchService: SearchService,
) : SearchDataSource {
override suspend fun getSearchViews(): BaseResponse<SearchViewsResponseDto> =
searchService.getSearchViewsList()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.terning.data.dto.response

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

@Serializable
data class SearchViewsResponseDto(
@SerialName("internshipAnnouncementId")
val internshipAnnouncementId: Long,
@SerialName("companyImage")
val companyImage: String,
@SerialName("title")
val title: String,
) {


fun toSearchViewsEntity(): List<InternshipAnnouncement> {
return listOf(
InternshipAnnouncement(
announcementId = internshipAnnouncementId,
companyImage = companyImage,
title = title,
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.terning.data.repositoryimpl

import com.terning.data.datasource.SearchDataSource
import com.terning.domain.entity.response.InternshipAnnouncement
import com.terning.domain.repository.SearchRepository
import javax.inject.Inject

class SearchViewsRepositoryImpl @Inject constructor(
private val searchDataSource: SearchDataSource,
) : SearchRepository {
override suspend fun getSearchViewsList(): Result<List<InternshipAnnouncement>> =
runCatching {
searchDataSource.getSearchViews().result.toSearchViewsEntity()
}
}
10 changes: 10 additions & 0 deletions data/src/main/java/com/terning/data/service/SearchService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.terning.data.service

import com.terning.data.dto.BaseResponse
import com.terning.data.dto.response.SearchViewsResponseDto
import retrofit2.http.GET

interface SearchService {
@GET("api/v1/search/views")
suspend fun getSearchViewsList(): BaseResponse<SearchViewsResponseDto>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.terning.domain.entity.response

data class InternshipAnnouncement(
val title: String,
val companyImage: String,
val announcementId: Long,
)
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.InternshipAnnouncement

interface SearchRepository {
suspend fun getSearchViewsList(): Result<List<InternshipAnnouncement>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ fun InternScreen(
color = Grey200,
offsetY = 2.dp
),
onBackButtonClick = {},
onBackButtonClick = {
navController.navigateUp()
},
)
},
bottomBar = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,24 @@ 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.getValue
import androidx.compose.ui.Modifier
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.textfield.SearchTextField
import com.terning.core.designsystem.component.topappbar.LogoTopAppBar
import com.terning.core.designsystem.theme.Black
import com.terning.core.designsystem.theme.Grey100
import com.terning.core.designsystem.theme.TerningTheme
import com.terning.core.extension.noRippleClickable
import com.terning.core.state.UiState
import com.terning.domain.entity.response.InternshipAnnouncement
import com.terning.feature.R
import com.terning.feature.search.search.component.ImageSlider
import com.terning.feature.search.search.component.InternListType
Expand All @@ -29,16 +37,46 @@ import com.terning.feature.search.searchprocess.navigation.navigateSearchProcess
@Composable
fun SearchRoute(
navController: NavHostController,
viewModel: SearchViewModel = hiltViewModel(),
) {
SearchScreen(
navController = navController
)
val lifecycleOwner = LocalLifecycleOwner.current

val state by viewModel.state.collectAsStateWithLifecycle(lifecycleOwner = lifecycleOwner)

LaunchedEffect(key1 = true) {
viewModel.getSearchViews()
}

LaunchedEffect(viewModel.sideEffect, lifecycleOwner) {
viewModel.sideEffect.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle)
.collect { sideEffect ->
when (sideEffect) {
is SearchViewsSideEffect.Toast -> {
sideEffect.message
}
}
}
}

when (state.searchViewsList) {
is UiState.Loading -> {}
is UiState.Empty -> {}
is UiState.Failure -> {}
is UiState.Success -> {
SearchScreen(
navController = navController,
searchViewsList = (state.searchViewsList as UiState.Success<List<InternshipAnnouncement>>).data
)
}

}
}

@Composable
fun SearchScreen(
modifier: Modifier = Modifier,
navController: NavHostController,
searchViewsList: List<InternshipAnnouncement>,
) {
val images = listOf(
R.drawable.ic_nav_search,
Expand Down Expand Up @@ -91,13 +129,21 @@ fun SearchScreen(
color = Black
)

SearchInternList(type = InternListType.VIEW)
SearchInternList(
type = InternListType.VIEW,
searchViewsList = searchViewsList,
navController = navController
)
HorizontalDivider(
thickness = 4.dp,
modifier = Modifier.padding(vertical = 8.dp),
color = Grey100,
)
SearchInternList(type = InternListType.SCRAP)
SearchInternList(
type = InternListType.SCRAP,
searchViewsList = searchViewsList,
navController = navController
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.terning.feature.search.search

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.terning.core.state.UiState
import com.terning.domain.repository.SearchRepository
import com.terning.feature.R
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class SearchViewModel @Inject constructor(
private val searchRepository: SearchRepository,
) : ViewModel() {
private val _state: MutableStateFlow<SearchViewsState> = MutableStateFlow(SearchViewsState())
val state: StateFlow<SearchViewsState> = _state.asStateFlow()

private val _sideEffect: MutableSharedFlow<SearchViewsSideEffect> = MutableSharedFlow()
val sideEffect = _sideEffect.asSharedFlow()

init {
getSearchViews()
}

fun getSearchViews() {
viewModelScope.launch {
searchRepository.getSearchViewsList().onSuccess { searchViewsList ->
_state.value = _state.value.copy(
searchViewsList = UiState.Success(searchViewsList)
)
}.onFailure {
_sideEffect.emit(SearchViewsSideEffect.Toast(R.string.server_failure))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.terning.feature.search.search

import androidx.annotation.StringRes

sealed class SearchViewsSideEffect {
data class Toast(@StringRes val message: Int) : SearchViewsSideEffect()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.terning.feature.search.search

import com.terning.core.state.UiState
import com.terning.domain.entity.response.InternshipAnnouncement

data class SearchViewsState(
var searchViewsList: UiState<List<InternshipAnnouncement>> = UiState.Loading,
)
Loading

0 comments on commit fd5dd93

Please sign in to comment.