Skip to content
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.flint.core.common.extension

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.ViewModel
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavHostController

/**
* 공용 뷰모델을 불러오기 위한 함수
* */
@Composable
inline fun <reified T : ViewModel> NavBackStackEntry.sharedViewModel(
navController: NavHostController,
): T {
val navGraphRoute = destination.parent?.route ?: return hiltViewModel()
val parentEntry = remember(this) {
navController.getBackStackEntry(navGraphRoute)
}
return hiltViewModel(parentEntry)
}
5 changes: 5 additions & 0 deletions app/src/main/java/com/flint/core/navigation/Route.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ interface Route {
val tempToken: String
) : Route

@Serializable
data class OnboardingGraph(
val tempToken: String
) : Route

@Serializable
data object OnboardingContent : Route

Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/com/flint/data/api/SearchApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.flint.data.api

import com.flint.data.dto.base.BaseResponse
import com.flint.data.dto.search.SearchBookmarkedContentsResponseDto
import com.flint.data.dto.search.SearchContentsResponseDto
import retrofit2.http.GET
import retrofit2.http.Query

Expand All @@ -12,4 +13,9 @@ interface SearchApi {
@Query("cursor") cursor: Int,
@Query("size") size: Int
) : BaseResponse<SearchBookmarkedContentsResponseDto>

@GET("/api/v1/search/contents")
suspend fun getSearchContentList(
@Query("keyword") keyword: String?
): BaseResponse<SearchContentsResponseDto>
}
6 changes: 6 additions & 0 deletions app/src/main/java/com/flint/data/api/UserApi.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.flint.data.api

import com.flint.data.dto.base.BaseResponse
import com.flint.data.dto.user.response.NicknameCheckResponseDto
import com.flint.data.dto.user.response.BookmarkedCollectionListResponseDto
import com.flint.data.dto.user.response.CreatedCollectionListResponseDto
import com.flint.data.dto.user.response.UserKeywordsResponseDto
import com.flint.data.dto.user.response.UserProfileResponseDto
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query

interface UserApi {
// 사용자 프로필 조회
Expand All @@ -16,6 +18,10 @@ interface UserApi {
): BaseResponse<UserProfileResponseDto>

// 닉네임 중복 체크
@GET("/api/v1/users/nickname/check")
suspend fun checkNickname(
@Query("nickname") nickname: String
): BaseResponse<NicknameCheckResponseDto>

// 사용자 북마크 컬렉션 조회
@GET("/api/v1/users/{userId}/bookmarked-collections")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.flint.data.dto.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class ContentSearchResponseDto(
@SerialName("data") val contents: List<ContentItemDto>,
@SerialName("meta") val meta: PageMetaDto,
)

// TODO: null 처리를 어떻게? 어떤거가 null가능인지
@Serializable
data class ContentItemDto(
@SerialName("contentId") val contentId: Long?,
@SerialName("title") val title: String?,
@SerialName("author") val author: String?,
@SerialName("posterUrl") val posterUrl: String?,
@SerialName("year") val year: Int?,
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

이거 서버샘들께 여쭤본 거 아니었나요? 👀
왜 다 nullable이죠

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

shelf에서 바꾸다가 까먹어서 nullable은 다 제거했습니당


@Serializable
data class PageMetaDto(
@SerialName("type") val type: String,
@SerialName("returned") val returned: Int,
@SerialName("currentPage") val currentPage: Int,
@SerialName("totalPages") val totalPages: Int,
@SerialName("totalElements") val totalElements: Int,
@SerialName("nextCursor") val nextCursor: String?,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.flint.data.dto.search

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class SearchContentsResponseDto(
@SerialName("contents")
val contents: List<Content>
) {
@Serializable
data class Content(
@SerialName("id")
val id: String,
@SerialName("title")
val title: String,
@SerialName("author")
val author: String,
@SerialName("posterUrl")
val posterUrl: String,
@SerialName("year")
val year: Int
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.flint.data.dto.user.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class NicknameCheckResponseDto(
@SerialName("available")
val available: Boolean
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.flint.domain.mapper.search

import com.flint.data.dto.search.SearchContentsResponseDto
import com.flint.domain.model.search.SearchContentItemModel
import com.flint.domain.model.search.SearchContentListModel
import kotlinx.collections.immutable.toImmutableList

fun SearchContentsResponseDto.toModel(): SearchContentListModel {
return SearchContentListModel(
contents = this.contents.map { it.toModel() }.toImmutableList()
)
}

private fun SearchContentsResponseDto.Content.toModel(): SearchContentItemModel{
return SearchContentItemModel(
id = id,
title = title,
author = author,
posterUrl = posterUrl,
year = year
)
}



10 changes: 10 additions & 0 deletions app/src/main/java/com/flint/domain/mapper/user/UserMapper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.flint.domain.mapper.user

import com.flint.data.dto.user.response.NicknameCheckResponseDto
import com.flint.domain.model.user.NicknameCheckModel

fun NicknameCheckResponseDto.toModel(): NicknameCheckModel {
return NicknameCheckModel(
isAvailable = this.available
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.flint.domain.model.search

import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf

data class SearchContentItemModel(
val id: String,
val title: String,
val author: String,
val posterUrl: String,
val year: Int,
)

data class SearchContentListModel(
val contents: ImmutableList<SearchContentItemModel>
) {
companion object {
val FakeList =
persistentListOf(
SearchContentItemModel(
id = "1",
title = "은하수를 여행하는 히치하이커를 위한 안내서",
author = "가스 제닝스",
posterUrl = "https://image.tmdb.org/t/p/w500/ib6v6qUXzez1x2qIOLN7C0yJNPQ.jpg",
year = 2005,
),
SearchContentItemModel(
id = "2",
title = "인터스텔라",
author = "크리스토퍼 놀란",
posterUrl = "https://image.tmdb.org/t/p/w500/ib6v6qUXzez1x2qIOLN7C0yJNPQ.jpg",
year = 2014,
),
SearchContentItemModel(
id = "3",
title = "인셉션",
author = "크리스토퍼 놀란",
posterUrl = "https://image.tmdb.org/t/p/w500/ib6v6qUXzez1x2qIOLN7C0yJNPQ.jpg",
year = 2010,
),
SearchContentItemModel(
id = "4",
title = "기생충",
author = "봉준호",
posterUrl = "https://image.tmdb.org/t/p/w500/ib6v6qUXzez1x2qIOLN7C0yJNPQ.jpg",
year = 2019,
),
SearchContentItemModel(
id = "5",
title = "어벤져스: 엔드게임",
author = "안소니 루소",
posterUrl = "https://image.tmdb.org/t/p/w500/ib6v6qUXzez1x2qIOLN7C0yJNPQ.jpg",
year = 2019,
),
SearchContentItemModel(
id = "6",
title = "다크 나이트",
author = "크리스토퍼 놀란",
posterUrl = "https://image.tmdb.org/t/p/w500/ib6v6qUXzez1x2qIOLN7C0yJNPQ.jpg",
year = 2008,
),
SearchContentItemModel(
id = "7",
title = "오펜하이머",
author = "크리스토퍼 놀란",
posterUrl = "https://image.tmdb.org/t/p/w500/ib6v6qUXzez1x2qIOLN7C0yJNPQ.jpg",
year = 2023,
),
SearchContentItemModel(
id = "8",
title = "괴물",
author = "봉준호",
posterUrl = "https://image.tmdb.org/t/p/w500/ib6v6qUXzez1x2qIOLN7C0yJNPQ.jpg",
year = 2006,
),
SearchContentItemModel(
id = "9",
title = "설국열차",
author = "봉준호",
posterUrl = "https://image.tmdb.org/t/p/w500/ib6v6qUXzez1x2qIOLN7C0yJNPQ.jpg",
year = 2013,
),
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.flint.domain.model.user

data class NicknameCheckModel(
val isAvailable: Boolean
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ package com.flint.domain.repository
import com.flint.core.common.util.suspendRunCatching
import com.flint.data.api.SearchApi
import com.flint.domain.mapper.content.toModel
import com.flint.domain.mapper.search.toModel
import com.flint.domain.model.content.ContentModel
import com.flint.domain.model.search.SearchContentListModel
import javax.inject.Inject

class SearchRepository @Inject constructor(
private val apiService: SearchApi,
) {
suspend fun getBookmarkedContentList(keyword: String, cursor: Int, size: Int): Result<List<ContentModel>> =
suspendRunCatching { apiService.getBookmarkedContentList(keyword, cursor, size).data.toModel() }

suspend fun getSearchContentList(keyword: String?): Result<SearchContentListModel> =
suspendRunCatching { apiService.getSearchContentList(keyword).data.toModel() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.flint.core.common.util.suspendRunCatching
import com.flint.data.api.UserApi
import com.flint.domain.mapper.collection.toModel
import com.flint.domain.mapper.user.toModel
import com.flint.domain.model.user.NicknameCheckModel
import com.flint.domain.model.collection.CollectionListModel
import com.flint.domain.model.user.KeywordListModel
import com.flint.domain.model.user.UserProfileResponseModel
Expand Down Expand Up @@ -33,4 +34,10 @@ class UserRepository @Inject constructor(
suspendRunCatching {
apiService.getUserBookmarkedCollections(userId ?: myTempUserId).data.toModel()
}

// 닉네임 중복 체크
suspend fun checkNickname(nickname: String): Result<NicknameCheckModel> =
suspendRunCatching {
apiService.checkNickname(nickname).data.toModel()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.flint.core.designsystem.component.button.FlintBasicButton
import com.flint.core.designsystem.component.button.FlintButtonState
import com.flint.core.designsystem.component.image.SelectedContentItem
Expand All @@ -36,7 +37,13 @@ fun OnboardingContentRoute(
paddingValues: PaddingValues,
navigateToOnboardingOtt: () -> Unit,
navigateUp: () -> Unit,
) {
viewModel: OnboardingViewModel = hiltViewModel(),
) {

LaunchedEffect(Unit) {
viewModel.getSearchContentList(null) // 인기 목록 받아오기
}

OnboardingContentScreen(
nickname = "User",
currentStep = 7,
Expand All @@ -60,9 +67,8 @@ fun OnboardingContentScreen(
modifier =
modifier
.fillMaxSize()
.background(color = FlintTheme.colors.background)
.statusBarsPadding(),
) {
.background(color = FlintTheme.colors.background),
) {
FlintBackTopAppbar(
onClick = onBackClick,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.flint.R
import com.flint.core.designsystem.component.button.FlintBasicButton
import com.flint.core.designsystem.component.button.FlintButtonState
Expand All @@ -28,7 +28,8 @@ fun OnboardingDoneRoute(
paddingValues: PaddingValues,
navigateToHome: () -> Unit,
navigateUp: () -> Unit,
) {
viewModel: OnboardingViewModel = hiltViewModel(),
) {
OnboardingDoneScreen(
onBackClick = navigateUp,
onNextClick = navigateToHome,
Expand All @@ -47,7 +48,6 @@ fun OnboardingDoneScreen(
modifier
.fillMaxSize()
.background(color = FlintTheme.colors.background)
.statusBarsPadding(),
) {
FlintBackTopAppbar(
onClick = onBackClick,
Expand Down
Loading