Skip to content

Commit 168e58a

Browse files
committed
[BOOK-166] feat: Home Ui 구성 및 이벤트 연결
1 parent 013983d commit 168e58a

File tree

7 files changed

+167
-40
lines changed

7 files changed

+167
-40
lines changed

feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package com.ninecraft.booket.feature.home
22

33
import androidx.compose.runtime.Composable
44
import androidx.compose.runtime.rememberCoroutineScope
5+
import com.ninecraft.booket.feature.screens.BookDetailScreen
56
import com.ninecraft.booket.feature.screens.HomeScreen
67
import com.ninecraft.booket.feature.screens.RecordScreen
78
import com.ninecraft.booket.feature.screens.SearchScreen
9+
import com.ninecraft.booket.feature.screens.SettingsScreen
810
import com.slack.circuit.codegen.annotations.CircuitInject
911
import com.slack.circuit.runtime.Navigator
1012
import com.slack.circuit.runtime.presenter.Presenter
@@ -24,12 +26,21 @@ class HomePresenter @AssistedInject constructor(
2426

2527
fun handleEvent(event: HomeUiEvent) {
2628
when (event) {
27-
is HomeUiEvent.OnButtonClick -> {
29+
is HomeUiEvent.OnSettingsClick -> {
30+
navigator.goTo(SettingsScreen)
31+
}
32+
33+
is HomeUiEvent.OnBookRegisterClick -> {
2834
navigator.goTo(SearchScreen)
2935
}
36+
3037
is HomeUiEvent.OnRecordButtonClick -> {
3138
navigator.goTo(RecordScreen)
3239
}
40+
41+
is HomeUiEvent.OnBookDetailClick -> {
42+
navigator.goTo(BookDetailScreen(""))
43+
}
3344
}
3445
}
3546

feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt

Lines changed: 76 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
11
package com.ninecraft.booket.feature.home
22

3+
import androidx.compose.foundation.background
34
import androidx.compose.foundation.layout.Arrangement
5+
import androidx.compose.foundation.layout.Box
46
import androidx.compose.foundation.layout.Column
7+
import androidx.compose.foundation.layout.PaddingValues
8+
import androidx.compose.foundation.layout.Row
59
import androidx.compose.foundation.layout.Spacer
610
import androidx.compose.foundation.layout.fillMaxSize
11+
import androidx.compose.foundation.layout.fillMaxWidth
712
import androidx.compose.foundation.layout.height
8-
import androidx.compose.material3.Button
13+
import androidx.compose.foundation.layout.padding
14+
import androidx.compose.foundation.layout.size
15+
import androidx.compose.foundation.pager.HorizontalPager
16+
import androidx.compose.foundation.pager.rememberPagerState
17+
import androidx.compose.foundation.shape.CircleShape
918
import androidx.compose.material3.Text
1019
import androidx.compose.runtime.Composable
11-
import androidx.compose.ui.Alignment
1220
import androidx.compose.ui.Modifier
21+
import androidx.compose.ui.draw.clip
22+
import androidx.compose.ui.res.stringResource
1323
import androidx.compose.ui.unit.dp
1424
import com.ninecraft.booket.core.designsystem.DevicePreview
1525
import com.ninecraft.booket.core.designsystem.theme.ReedTheme
26+
import com.ninecraft.booket.feature.home.component.BookCard
27+
import com.ninecraft.booket.feature.home.component.HomeBanner
28+
import com.ninecraft.booket.feature.home.component.HomeHeader
1629
import com.ninecraft.booket.feature.screens.HomeScreen
1730
import com.slack.circuit.codegen.annotations.CircuitInject
1831
import dagger.hilt.android.components.ActivityRetainedComponent
@@ -25,8 +38,6 @@ internal fun HomeUi(
2538
) {
2639
Column(
2740
modifier = modifier.fillMaxSize(),
28-
horizontalAlignment = Alignment.CenterHorizontally,
29-
verticalArrangement = Arrangement.Center,
3041
) {
3142
HomeContent(
3243
state = state,
@@ -35,28 +46,75 @@ internal fun HomeUi(
3546
}
3647
}
3748

38-
@Suppress("unused")
3949
@Composable
4050
internal fun HomeContent(
4151
state: HomeUiState,
4252
modifier: Modifier = Modifier,
4353
) {
44-
Text(text = "")
45-
Spacer(modifier = Modifier.height(16.dp))
46-
Button(
47-
onClick = {
48-
state.eventSink(HomeUiEvent.OnButtonClick)
54+
val dummyBooks = listOf(
55+
Book("여름은 오래 그곳에 남아", "마쓰이에 마사시", "비채", "https://example.com/sample-book-cover.jpg", 3),
56+
Book("여름은 오래 그곳에 남아", "마쓰이에 마사시", "비채", "https://example.com/sample-book-cover.jpg", 3),
57+
Book("여름은 오래 그곳에 남아", "마쓰이에 마사시", "비채", "https://example.com/sample-book-cover.jpg", 3)
58+
)
59+
60+
HomeHeader(
61+
onSettingsClick = {
62+
state.eventSink(HomeUiEvent.OnSettingsClick)
4963
},
50-
) {
51-
Text(text = "도서 검색 이동")
52-
}
53-
Spacer(modifier = Modifier.height(16.dp))
54-
Button(
55-
onClick = {
56-
state.eventSink(HomeUiEvent.OnRecordButtonClick)
64+
modifier = modifier,
65+
)
66+
HomeBanner(
67+
onBookRegisterClick = {
68+
state.eventSink(HomeUiEvent.OnBookRegisterClick)
5769
},
70+
modifier = modifier,
71+
)
72+
Column(
73+
modifier = Modifier
74+
.fillMaxSize()
75+
.background(ReedTheme.colors.baseSecondary),
5876
) {
59-
Text(text = "독서 기록 작성")
77+
Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing6))
78+
Text(
79+
text = stringResource(R.string.home_content_label_reading_now),
80+
modifier = Modifier.padding(start = ReedTheme.spacing.spacing5),
81+
color = ReedTheme.colors.contentSecondary,
82+
style = ReedTheme.typography.headline2Medium,
83+
)
84+
Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing3))
85+
val pagerState = rememberPagerState(pageCount = { dummyBooks.size })
86+
HorizontalPager(
87+
state = pagerState,
88+
modifier = Modifier.fillMaxWidth(),
89+
contentPadding = PaddingValues(horizontal = ReedTheme.spacing.spacing5),
90+
pageSpacing = ReedTheme.spacing.spacing5,
91+
) { page ->
92+
BookCard(
93+
bookInfo = dummyBooks[page],
94+
onBookDetailClick = {
95+
state.eventSink(HomeUiEvent.OnBookDetailClick)
96+
},
97+
onRecordButtonClick = {
98+
state.eventSink(HomeUiEvent.OnRecordButtonClick)
99+
}
100+
)
101+
}
102+
Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing5))
103+
Row(
104+
modifier = Modifier.fillMaxWidth(),
105+
horizontalArrangement = Arrangement.Center,
106+
) {
107+
repeat(pagerState.pageCount) { iteration ->
108+
val color = if (pagerState.currentPage == iteration) ReedTheme.colors.bgPrimary else ReedTheme.colors.bgSecondaryPressed
109+
Box(
110+
modifier = Modifier
111+
.size(12.dp)
112+
.padding(3.dp)
113+
.clip(CircleShape)
114+
.background(color)
115+
)
116+
}
117+
}
60118
}
61119
}
62120

feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUiState.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ data class HomeUiState(
88
) : CircuitUiState
99

1010
sealed interface HomeUiEvent : CircuitUiEvent {
11-
data object OnButtonClick : HomeUiEvent
11+
data object OnSettingsClick : HomeUiEvent
12+
data object OnBookRegisterClick : HomeUiEvent
1213
data object OnRecordButtonClick : HomeUiEvent
14+
data object OnBookDetailClick: HomeUiEvent
1315
}
16+
17+
data class Book(
18+
val title: String = "",
19+
val author: String = "",
20+
val publisher: String = "",
21+
val imageUrl: String = "",
22+
val reviewCount: Int = 0,
23+
)

feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/BookCard.kt

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,32 @@ import androidx.compose.ui.draw.shadow
2424
import androidx.compose.ui.graphics.Color
2525
import androidx.compose.ui.graphics.vector.ImageVector
2626
import androidx.compose.ui.res.painterResource
27+
import androidx.compose.ui.res.stringResource
2728
import androidx.compose.ui.res.vectorResource
29+
import androidx.compose.ui.text.SpanStyle
30+
import androidx.compose.ui.text.buildAnnotatedString
2831
import androidx.compose.ui.text.style.TextOverflow
32+
import androidx.compose.ui.text.withStyle
2933
import androidx.compose.ui.unit.dp
34+
import com.ninecraft.booket.core.common.extensions.clickableSingle
3035
import com.ninecraft.booket.core.designsystem.ComponentPreview
3136
import com.ninecraft.booket.core.designsystem.component.NetworkImage
3237
import com.ninecraft.booket.core.designsystem.component.button.ReedButton
3338
import com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle
3439
import com.ninecraft.booket.core.designsystem.component.button.largeButtonStyle
3540
import com.ninecraft.booket.core.designsystem.theme.ReedTheme
3641
import com.ninecraft.booket.core.designsystem.theme.White
42+
import com.ninecraft.booket.feature.home.Book
43+
import com.ninecraft.booket.feature.home.R
3744
import com.ninecraft.booket.core.designsystem.R as designR
3845

3946
@Composable
40-
fun BookCard(modifier: Modifier = Modifier) {
47+
fun BookCard(
48+
bookInfo: Book,
49+
onBookDetailClick: () -> Unit,
50+
onRecordButtonClick: () -> Unit,
51+
modifier: Modifier = Modifier,
52+
) {
4153
Column(
4254
modifier = modifier
4355
.fillMaxWidth()
@@ -51,6 +63,10 @@ fun BookCard(modifier: Modifier = Modifier) {
5163
color = ReedTheme.colors.basePrimary,
5264
shape = RoundedCornerShape(ReedTheme.radius.sm),
5365
)
66+
.clip(shape = RoundedCornerShape(ReedTheme.radius.sm))
67+
.clickableSingle {
68+
onBookDetailClick()
69+
}
5470
.border(
5571
width = 1.dp,
5672
color = ReedTheme.colors.borderSecondary,
@@ -66,7 +82,7 @@ fun BookCard(modifier: Modifier = Modifier) {
6682
) {
6783
Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing5))
6884
NetworkImage(
69-
imageUrl = "",
85+
imageUrl = bookInfo.imageUrl,
7086
contentDescription = "Book CoverImage",
7187
modifier = Modifier
7288
.width(86.dp)
@@ -81,7 +97,7 @@ fun BookCard(modifier: Modifier = Modifier) {
8197
)
8298
Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing5))
8399
Text(
84-
text = "여름은 오래 그곳에 남아",
100+
text = bookInfo.title,
85101
color = ReedTheme.colors.contentPrimary,
86102
style = ReedTheme.typography.headline1SemiBold,
87103
)
@@ -92,7 +108,7 @@ fun BookCard(modifier: Modifier = Modifier) {
92108
horizontalArrangement = Arrangement.Center,
93109
) {
94110
Text(
95-
text = "마쓰이에 마사시",
111+
text = bookInfo.author,
96112
color = ReedTheme.colors.contentTertiary,
97113
overflow = TextOverflow.Ellipsis,
98114
maxLines = 1,
@@ -107,7 +123,7 @@ fun BookCard(modifier: Modifier = Modifier) {
107123
)
108124
Spacer(Modifier.width(ReedTheme.spacing.spacing1))
109125
Text(
110-
text = "비채",
126+
text = bookInfo.publisher,
111127
color = ReedTheme.colors.contentTertiary,
112128
overflow = TextOverflow.Ellipsis,
113129
maxLines = 1,
@@ -123,6 +139,10 @@ fun BookCard(modifier: Modifier = Modifier) {
123139
color = ReedTheme.colors.baseSecondary,
124140
shape = RoundedCornerShape(ReedTheme.radius.sm),
125141
)
142+
.clip(shape = RoundedCornerShape(ReedTheme.radius.sm))
143+
.clickableSingle {
144+
onBookDetailClick()
145+
}
126146
.padding(
127147
horizontal = ReedTheme.spacing.spacing3,
128148
vertical = ReedTheme.spacing.spacing2,
@@ -136,18 +156,26 @@ fun BookCard(modifier: Modifier = Modifier) {
136156
)
137157
Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing1))
138158
Text(
139-
text = "3개",
159+
text = buildAnnotatedString {
160+
append("${bookInfo.reviewCount}")
161+
withStyle(style = SpanStyle(color = ReedTheme.colors.contentSecondary)) {
162+
append("")
163+
}
164+
},
165+
color = ReedTheme.colors.contentBrand,
140166
style = ReedTheme.typography.label1SemiBold,
141167
)
142168

143169
}
144170
Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing2))
145171
ReedButton(
146-
onClick = { /*TODO*/ },
172+
onClick = {
173+
onRecordButtonClick()
174+
},
147175
sizeStyle = largeButtonStyle,
148176
colorStyle = ReedButtonColorStyle.PRIMARY,
149177
modifier = Modifier.weight(1f),
150-
text = "기록하기",
178+
text = stringResource(R.string.book_card_record),
151179
leadingIcon = {
152180
Icon(
153181
imageVector = ImageVector.vectorResource(designR.drawable.ic_edit_3),
@@ -198,13 +226,13 @@ fun EmptyBookCard(
198226
)
199227
Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing5))
200228
Text(
201-
text = "아직 등록된 책이 없어요",
229+
text = stringResource(R.string.empty_book_card_title),
202230
color = ReedTheme.colors.contentPrimary,
203231
style = ReedTheme.typography.headline1SemiBold,
204232
)
205233
Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing1))
206234
Text(
207-
text = "등록 후 나만의 독서 기록을 남겨 보세요.",
235+
text = stringResource(R.string.empty_book_card_description),
208236
color = ReedTheme.colors.contentTertiary,
209237
style = ReedTheme.typography.label1Medium,
210238
)
@@ -216,7 +244,7 @@ fun EmptyBookCard(
216244
sizeStyle = largeButtonStyle,
217245
colorStyle = ReedButtonColorStyle.PRIMARY,
218246
modifier = Modifier.fillMaxWidth(),
219-
text = "등록하기",
247+
text = stringResource(R.string.empty_book_card_register),
220248
)
221249
}
222250
}
@@ -225,7 +253,11 @@ fun EmptyBookCard(
225253
@Composable
226254
private fun BookCardPreview() {
227255
ReedTheme {
228-
BookCard()
256+
BookCard(
257+
bookInfo = Book(),
258+
onBookDetailClick = {},
259+
onRecordButtonClick = {},
260+
)
229261
}
230262
}
231263

feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/HomeBanner.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,23 @@ import androidx.compose.runtime.Composable
1414
import androidx.compose.ui.Alignment
1515
import androidx.compose.ui.Modifier
1616
import androidx.compose.ui.graphics.vector.ImageVector
17+
import androidx.compose.ui.res.stringResource
1718
import androidx.compose.ui.res.vectorResource
1819
import androidx.compose.ui.unit.dp
1920
import com.ninecraft.booket.core.common.extensions.clickableSingle
2021
import com.ninecraft.booket.core.designsystem.ComponentPreview
21-
import com.ninecraft.booket.core.designsystem.R
22+
import com.ninecraft.booket.core.designsystem.R as designR
2223
import com.ninecraft.booket.core.designsystem.theme.HomeBg
2324
import com.ninecraft.booket.core.designsystem.theme.ReedTheme
25+
import com.ninecraft.booket.feature.home.R
2426

2527
@Composable
2628
fun HomeBanner(
2729
onBookRegisterClick: () -> Unit,
30+
modifier: Modifier = Modifier,
2831
) {
2932
Box(
30-
modifier = Modifier
33+
modifier = modifier
3134
.fillMaxWidth()
3235
.height(160.dp)
3336
.background(HomeBg)
@@ -39,7 +42,7 @@ fun HomeBanner(
3942
) {
4043
Column {
4144
Text(
42-
text = "문장 기록하고\n씨앗을 모아볼까요?",
45+
text = stringResource(R.string.home_banner_title),
4346
color = ReedTheme.colors.contentPrimary,
4447
style = ReedTheme.typography.heading1Bold,
4548
)
@@ -51,12 +54,12 @@ fun HomeBanner(
5154
verticalAlignment = Alignment.CenterVertically,
5255
) {
5356
Text(
54-
text = "책 등록하기",
57+
text = stringResource(R.string.home_banner_book_register),
5558
color = ReedTheme.colors.contentBrand,
5659
style = ReedTheme.typography.body2Medium,
5760
)
5861
Icon(
59-
imageVector = ImageVector.vectorResource(id = R.drawable.ic_chevron_right),
62+
imageVector = ImageVector.vectorResource(id = designR.drawable.ic_chevron_right),
6063
contentDescription = "Chevron Right Icon",
6164
tint = ReedTheme.colors.contentBrand,
6265
)

0 commit comments

Comments
 (0)