Skip to content

Commit 5640208

Browse files
authored
Merge pull request #65 from YAPP-Github/BOOK-161-feature/#64
feat: 내서재 동적 검색 API 연동 및 임시 도서 상세 화면 구현
2 parents 7ca3f8b + 7544a69 commit 5640208

File tree

30 files changed

+709
-149
lines changed

30 files changed

+709
-149
lines changed

app/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ dependencies {
5555
projects.feature.search,
5656
projects.feature.settings,
5757
projects.feature.webview,
58+
projects.feature.detail,
5859

5960
libs.androidx.activity.compose,
6061
libs.androidx.startup,

core/data/api/src/main/kotlin/com/ninecraft/booket/core/data/api/repository/BookRepository.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,9 @@ interface BookRepository {
2323
bookStatus: String,
2424
): Result<BookUpsertModel>
2525

26-
suspend fun getLibrary(): Result<LibraryModel>
26+
suspend fun getLibrary(
27+
status: String?,
28+
page: Int,
29+
size: Int,
30+
): Result<LibraryModel>
2731
}

core/data/impl/src/main/kotlin/com/ninecraft/booket/core/data/impl/mapper/ResponseToModel.kt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,19 @@ import com.ninecraft.booket.core.model.BookDetailModel
55
import com.ninecraft.booket.core.model.BookSearchModel
66
import com.ninecraft.booket.core.model.BookSummaryModel
77
import com.ninecraft.booket.core.model.BookUpsertModel
8+
import com.ninecraft.booket.core.model.LibraryBookSummaryModel
9+
import com.ninecraft.booket.core.model.LibraryBooksModel
810
import com.ninecraft.booket.core.model.LibraryModel
11+
import com.ninecraft.booket.core.model.PageInfoModel
912
import com.ninecraft.booket.core.model.UserProfileModel
1013
import com.ninecraft.booket.core.network.response.BookDetailResponse
1114
import com.ninecraft.booket.core.network.response.BookSearchResponse
1215
import com.ninecraft.booket.core.network.response.BookSummary
1316
import com.ninecraft.booket.core.network.response.BookUpsertResponse
17+
import com.ninecraft.booket.core.network.response.LibraryBookSummary
18+
import com.ninecraft.booket.core.network.response.LibraryBooks
1419
import com.ninecraft.booket.core.network.response.LibraryResponse
20+
import com.ninecraft.booket.core.network.response.PageInfo
1521
import com.ninecraft.booket.core.network.response.UserProfileResponse
1622

1723
internal fun UserProfileResponse.toModel(): UserProfileModel {
@@ -89,15 +95,42 @@ internal fun BookUpsertResponse.toModel(): BookUpsertModel {
8995

9096
internal fun LibraryResponse.toModel(): LibraryModel {
9197
return LibraryModel(
98+
books = books.toModel(),
99+
totalCount = totalCount,
100+
beforeReadingCount = beforeReadingCount,
101+
readingCount = readingCount,
102+
completedCount = completedCount,
103+
)
104+
}
105+
106+
internal fun LibraryBooks.toModel(): LibraryBooksModel {
107+
return LibraryBooksModel(
108+
content = content.map { it.toModel() },
109+
page = page.toModel(),
110+
)
111+
}
112+
113+
internal fun LibraryBookSummary.toModel(): LibraryBookSummaryModel {
114+
return LibraryBookSummaryModel(
92115
userBookId = userBookId,
93116
userId = userId,
94117
bookIsbn = bookIsbn,
95118
bookTitle = bookTitle,
96119
bookAuthor = bookAuthor,
97120
status = status,
121+
recordCount = recordCount,
98122
coverImageUrl = coverImageUrl,
99123
publisher = publisher,
100124
createdAt = createdAt,
101125
updatedAt = updatedAt,
102126
)
103127
}
128+
129+
internal fun PageInfo.toModel(): PageInfoModel {
130+
return PageInfoModel(
131+
size = size,
132+
number = number,
133+
totalElements = totalElements,
134+
totalPages = totalPages,
135+
)
136+
}

core/data/impl/src/main/kotlin/com/ninecraft/booket/core/data/impl/repository/DefaultBookRepository.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ internal class DefaultBookRepository @Inject constructor(
3939
service.upsertBook(BookUpsertRequest(bookIsbn, bookStatus)).toModel()
4040
}
4141

42-
override suspend fun getLibrary() = runSuspendCatching {
43-
service.getLibrary().toModel()
42+
override suspend fun getLibrary(status: String?, page: Int, size: Int) = runSuspendCatching {
43+
service.getLibrary(status, page, size).toModel()
4444
}
4545
}

core/model/src/main/kotlin/com/ninecraft/booket/core/model/LibraryModel.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,38 @@ import androidx.compose.runtime.Stable
44

55
@Stable
66
data class LibraryModel(
7+
val books: LibraryBooksModel = LibraryBooksModel(),
8+
val totalCount: Int = 0,
9+
val beforeReadingCount: Int = 0,
10+
val readingCount: Int = 0,
11+
val completedCount: Int = 0,
12+
)
13+
14+
@Stable
15+
data class LibraryBooksModel(
16+
val content: List<LibraryBookSummaryModel> = emptyList(),
17+
val page: PageInfoModel = PageInfoModel(),
18+
)
19+
20+
@Stable
21+
data class LibraryBookSummaryModel(
722
val userBookId: String = "",
823
val userId: String = "",
924
val bookIsbn: String = "",
1025
val bookTitle: String = "",
1126
val bookAuthor: String = "",
1227
val status: String = "",
28+
val recordCount: Int = 0,
1329
val coverImageUrl: String = "",
1430
val publisher: String = "",
1531
val createdAt: String = "",
1632
val updatedAt: String = "",
1733
)
34+
35+
@Stable
36+
data class PageInfoModel(
37+
val size: Int = 0,
38+
val number: Int = 0,
39+
val totalElements: Int = 0,
40+
val totalPages: Int = 0,
41+
)

core/network/src/main/kotlin/com/ninecraft/booket/core/network/response/LibraryResponse.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,28 @@ import kotlinx.serialization.Serializable
55

66
@Serializable
77
data class LibraryResponse(
8+
@SerialName("books")
9+
val books: LibraryBooks,
10+
@SerialName("totalCount")
11+
val totalCount: Int = 0,
12+
@SerialName("beforeReadingCount")
13+
val beforeReadingCount: Int,
14+
@SerialName("readingCount")
15+
val readingCount: Int,
16+
@SerialName("completedCount")
17+
val completedCount: Int,
18+
)
19+
20+
@Serializable
21+
data class LibraryBooks(
22+
@SerialName("content")
23+
val content: List<LibraryBookSummary>,
24+
@SerialName("page")
25+
val page: PageInfo,
26+
)
27+
28+
@Serializable
29+
data class LibraryBookSummary(
830
@SerialName("userBookId")
931
val userBookId: String,
1032
@SerialName("userId")
@@ -17,6 +39,8 @@ data class LibraryResponse(
1739
val bookAuthor: String,
1840
@SerialName("status")
1941
val status: String,
42+
@SerialName("recordCount")
43+
val recordCount: Int = 0,
2044
@SerialName("coverImageUrl")
2145
val coverImageUrl: String,
2246
@SerialName("publisher")
@@ -26,3 +50,15 @@ data class LibraryResponse(
2650
@SerialName("updatedAt")
2751
val updatedAt: String,
2852
)
53+
54+
@Serializable
55+
data class PageInfo(
56+
@SerialName("size")
57+
val size: Int,
58+
@SerialName("number")
59+
val number: Int,
60+
@SerialName("totalElements")
61+
val totalElements: Int,
62+
@SerialName("totalPages")
63+
val totalPages: Int,
64+
)

core/network/src/main/kotlin/com/ninecraft/booket/core/network/service/ReedService.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,10 @@ interface ReedService {
5555
suspend fun upsertBook(@Body bookUpsertRequest: BookUpsertRequest): BookUpsertResponse
5656

5757
@GET("api/v1/books/my-library")
58-
suspend fun getLibrary(): LibraryResponse
58+
suspend fun getLibrary(
59+
@Query("status") status: String? = null,
60+
@Query("page") page: Int,
61+
@Query("size") size: Int,
62+
@Query("sort") sort: String = "date_desc",
63+
): LibraryResponse
5964
}

feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt renamed to core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/InfinityLazyColumn.kt

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
1-
package com.ninecraft.booket.feature.search.component
1+
package com.ninecraft.booket.core.ui.component
22

33
import android.annotation.SuppressLint
4+
import androidx.compose.foundation.background
45
import androidx.compose.foundation.gestures.FlingBehavior
56
import androidx.compose.foundation.gestures.ScrollableDefaults
67
import androidx.compose.foundation.layout.Arrangement
8+
import androidx.compose.foundation.layout.Box
79
import androidx.compose.foundation.layout.Column
810
import androidx.compose.foundation.layout.PaddingValues
11+
import androidx.compose.foundation.layout.Row
12+
import androidx.compose.foundation.layout.Spacer
13+
import androidx.compose.foundation.layout.fillMaxWidth
14+
import androidx.compose.foundation.layout.height
915
import androidx.compose.foundation.layout.padding
16+
import androidx.compose.foundation.layout.width
1017
import androidx.compose.foundation.lazy.LazyColumn
1118
import androidx.compose.foundation.lazy.LazyListScope
1219
import androidx.compose.foundation.lazy.LazyListState
1320
import androidx.compose.foundation.lazy.items
1421
import androidx.compose.foundation.lazy.rememberLazyListState
22+
import androidx.compose.foundation.shape.RoundedCornerShape
1523
import androidx.compose.material3.Surface
1624
import androidx.compose.material3.Text
1725
import androidx.compose.runtime.Composable
@@ -27,13 +35,12 @@ import androidx.compose.ui.Modifier
2735
import androidx.compose.ui.tooling.preview.Preview
2836
import androidx.compose.ui.unit.dp
2937
import com.ninecraft.booket.core.designsystem.theme.ReedTheme
30-
import com.ninecraft.booket.core.model.BookSummaryModel
3138

3239
// 기기에서 평균적으로 한 화면에 보이는 아이템 개수
3340
private const val LIMIT_COUNT = 6
3441

3542
@Composable
36-
internal fun InfinityLazyColumn(
43+
fun InfinityLazyColumn(
3744
modifier: Modifier = Modifier,
3845
state: LazyListState = rememberLazyListState(),
3946
contentPadding: PaddingValues = PaddingValues(0.dp),
@@ -117,16 +124,39 @@ private fun InfinityLazyColumnPreview() {
117124
verticalArrangement = Arrangement.spacedBy(8.dp),
118125
content = {
119126
items(contents, key = { it }) {
120-
BookItem(
121-
book = BookSummaryModel(
122-
title = "여름은 오래 그곳에 남아",
123-
author = "마쓰이에 마사시",
124-
publisher = "비채",
125-
coverImageUrl = "https://example.com/sample-book-cover.jpg",
126-
isbn = "978-89-7337-932-5",
127-
),
128-
onBookClick = {},
129-
)
127+
Row(
128+
modifier = Modifier
129+
.fillMaxWidth()
130+
.padding(
131+
horizontal = ReedTheme.spacing.spacing5,
132+
vertical = ReedTheme.spacing.spacing4,
133+
),
134+
verticalAlignment = Alignment.CenterVertically,
135+
) {
136+
Box(
137+
modifier = Modifier
138+
.width(68.dp)
139+
.height(100.dp)
140+
.background(
141+
color = ReedTheme.colors.contentTertiary,
142+
shape = RoundedCornerShape(ReedTheme.radius.sm),
143+
),
144+
)
145+
Spacer(Modifier.width(ReedTheme.spacing.spacing4))
146+
Column {
147+
Text(
148+
text = "Title",
149+
color = ReedTheme.colors.contentPrimary,
150+
style = ReedTheme.typography.body1SemiBold,
151+
)
152+
Spacer(Modifier.height(ReedTheme.spacing.spacing1))
153+
Text(
154+
text = "Description",
155+
color = ReedTheme.colors.contentTertiary,
156+
style = ReedTheme.typography.label1Medium,
157+
)
158+
}
159+
}
130160
}
131161
},
132162
)

feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/LoadStateFooter.kt renamed to core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/LoadStateFooter.kt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.ninecraft.booket.feature.search.component
1+
package com.ninecraft.booket.core.ui.component
22

33
import androidx.compose.foundation.layout.Arrangement
44
import androidx.compose.foundation.layout.Box
@@ -15,11 +15,10 @@ import androidx.compose.ui.Modifier
1515
import androidx.compose.ui.res.stringResource
1616
import androidx.compose.ui.unit.dp
1717
import com.ninecraft.booket.core.designsystem.theme.ReedTheme
18-
import com.ninecraft.booket.feature.search.FooterState
19-
import com.ninecraft.booket.feature.search.R
18+
import com.ninecraft.booket.core.ui.R
2019

2120
@Composable
22-
internal fun LoadStateFooter(
21+
fun LoadStateFooter(
2322
footerState: FooterState,
2423
onRetryClick: () -> Unit,
2524
modifier: Modifier = Modifier,
@@ -56,7 +55,7 @@ internal fun LoadStateFooter(
5655

5756
is FooterState.End -> {
5857
Text(
59-
text = stringResource(R.string.no_more_results),
58+
text = stringResource(R.string.no_more_result),
6059
color = ReedTheme.colors.contentSecondary,
6160
style = ReedTheme.typography.body2Regular,
6261
)
@@ -68,3 +67,10 @@ internal fun LoadStateFooter(
6867
}
6968
}
7069
}
70+
71+
sealed interface FooterState {
72+
data object Idle : FooterState
73+
data object Loading : FooterState
74+
data object End : FooterState
75+
data class Error(val message: String) : FooterState
76+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<string name="no_more_result">더 이상 결과가 없습니다</string>
4+
<string name="retry">다시 시도</string>
5+
</resources>

0 commit comments

Comments
 (0)