Skip to content

Commit

Permalink
Merge pull request #289 from 6QuizOnTheBlock/and/feat#280-student_rel…
Browse files Browse the repository at this point in the history
…ay_detail_ui

And/feat#280 학생 이어 달리기 상세 화면 ui
  • Loading branch information
ghddbwns9808 authored May 12, 2024
2 parents 68c4130 + 44b810e commit ea40aef
Show file tree
Hide file tree
Showing 15 changed files with 373 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package com.sixkids.designsystem.component.item

import androidx.compose.foundation.Image
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
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import com.sixkids.designsystem.R
import com.sixkids.designsystem.theme.Cream
import com.sixkids.designsystem.theme.Gray
import com.sixkids.designsystem.theme.UlbanTypography
import com.sixkids.ui.util.formatToMonthDayTime
import java.time.LocalDateTime

@Composable
fun UlbanRunnerItem(
modifier: Modifier = Modifier,
padding: PaddingValues = PaddingValues(
horizontal = 16.dp,
vertical = 20.dp
),
time: LocalDateTime,
memberName: String,
memberPhoto: String,
question: String,
isLastTurn: Boolean = false,
color: Color = Cream
) {
Column(modifier = modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
Box(modifier = Modifier.wrapContentSize()) {
Card(
colors = CardDefaults.cardColors(
containerColor = color
),
elevation = CardDefaults.cardElevation(
defaultElevation = 8.dp
),
shape = CardDefaults.outlinedShape,
) {
Row(
modifier = modifier
.fillMaxWidth()
.padding(padding),
verticalAlignment = Alignment.CenterVertically
) {
AsyncImage(
model = memberPhoto,
placeholder = painterResource(id = R.drawable.student_boy),
contentDescription = null,
modifier = Modifier.size(80.dp)
)
Column(
modifier = Modifier.padding(start = 16.dp),
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
Text(
text = memberName,
style = UlbanTypography.titleSmall
)
Text(
text = time.formatToMonthDayTime(),
style = UlbanTypography.bodySmall
)
Text(
// text = stringResource(R.string.runner_question),
text = "받은 질문",
style = UlbanTypography.bodySmall.copy(color = Gray)
)
Text(
text = question,
style = UlbanTypography.bodyMedium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
}
if (isLastTurn) {
AsyncImage(
model = R.drawable.bomb,
placeholder = painterResource(id = R.drawable.bomb),
contentDescription = "bomb",
modifier = Modifier
.size(72.dp)
.align(Alignment.TopEnd)
.padding(12.dp)
)
}
}
if (!isLastTurn) {
Image(
painter = painterResource(id = R.drawable.ic_down_arrow),
contentDescription = "next",
modifier = Modifier
.padding(10.dp)
.size(32.dp)
)
}
}

}

@Composable
@Preview(showBackground = true)
fun UlbanRunnerItemPreview() {
UlbanRunnerItem(
time = LocalDateTime.now(),
memberName = "홍유준",
memberPhoto = "https://ulvanbucket.s3.ap-northeast-2.amazonaws.com/c5cef8d2-f085-45ca-b359-f76e39f2bca3_profile.jpg",
question = "이번 턴은 어떤"
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#965406" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">

<path android:fillColor="@android:color/white" android:pathData="M18,6.41l-1.41,-1.41l-4.59,4.58l-4.59,-4.58l-1.41,1.41l6,6z"/>

<path android:fillColor="@android:color/white" android:pathData="M18,13l-1.41,-1.41l-4.59,4.58l-4.59,-4.58l-1.41,1.41l6,6z"/>

</vector>
1 change: 1 addition & 0 deletions android/core/designsystem/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@
<string name="relay">이어 달리기</string>
<string name="relay_item_last_member">%s 학생이 폭탄을 터트렸어요</string>
<string name="relay_item_count">%d번</string>
<string name="runner_question">받은 질문</string>
</resources>
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
package com.sixkids.model

import java.time.LocalDateTime

data class RelayDetail(
val id: Long = 0,
val startTime: LocalDateTime = LocalDateTime.now(),
val endTime: LocalDateTime = LocalDateTime.now(),
val lastTurn: Int = 0,
val lastMemberName: String = "",
val runnerList: List<RelayQuestion> = emptyList(),

)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.sixkids.model

import java.time.LocalDateTime

data class RelayQuestion(
val id: Long = 0,
val memberId: Long = 0,
val memberName: String = "",
val memberPhoto: String = "",
val time: LocalDateTime = LocalDateTime.now(),
val question: String = "",
val turn: Int = 0,
val endStatus: Boolean = false,
)
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,8 @@ class MainNavigator(
}
}

fun navigateStudentRelayDetail(relayId: Long, groupId: Long?) {
navController.navigateStudentRelayDetail(relayId, groupId)
fun navigateStudentRelayDetail(relayId: Long) {
navController.navigateStudentRelayDetail(relayId)
}

fun navigateStudentRelayCreate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,7 @@ fun MainScreen(
navigateRelayDetail = navigator::navigateStudentRelayDetail,
navigateCreateRelay = navigator::navigateStudentRelayCreate,
navigateJoinRelay = navigator::navigateStudentRelayJoin,
handleException = viewModel::handleException,
onBackClick = navigator::popBackStack,
handleException = viewModel::handleException
)

studentBoardNavGraph(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class LoginViewModel @Inject constructor(
}.onFailure {
when(it){
is NotFoundException -> {
postSideEffect(LoginEffect.OnShowSnackBar(SnackbarToken(it.message)))
postSideEffect(LoginEffect.OnShowSnackBar(SnackbarToken("회원가입을 진행 해주세요")))
postSideEffect(LoginEffect.NavigateToSignUp)
}
else -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.sixkids.student.relay.detail

import com.sixkids.model.RelayDetail
import com.sixkids.ui.base.SideEffect
import com.sixkids.ui.base.UiState

data class RelayDetailState(
val isLoading: Boolean = false,
val relayDetail: RelayDetail = RelayDetail(),
) : UiState

sealed interface RelayDetailSideEffect : SideEffect{
data class HandleException(val throwable: Throwable, val retry: () -> Unit) :
RelayDetailSideEffect
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package com.sixkids.student.relay.detail

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.sixkids.designsystem.component.appbar.UlbanDetailAppBar
import com.sixkids.designsystem.component.item.UlbanRunnerItem
import com.sixkids.designsystem.theme.Orange
import com.sixkids.designsystem.theme.UlbanTheme
import com.sixkids.designsystem.theme.UlbanTypography
import com.sixkids.student.relay.R
import com.sixkids.ui.extension.collectWithLifecycle
import com.sixkids.ui.util.formatToMonthDayTime
import com.sixkids.designsystem.R as DesignSystemR


@Composable
fun RelayDetailRoute(
viewModel: RelayDetailViewModel = hiltViewModel(),
handleException: (Throwable, () -> Unit) -> Unit
){
val uiState by viewModel.uiState.collectAsStateWithLifecycle()

viewModel.sideEffect.collectWithLifecycle {
when (it) {
is RelayDetailSideEffect.HandleException -> handleException(it.throwable, it.retry)
}
}
LaunchedEffect(key1 = Unit) {
viewModel.getRelayDetail()
}

RelayDetailScreen(
uiState = uiState
)

}

@Composable
fun RelayDetailScreen(
uiState: RelayDetailState = RelayDetailState()
) {
val listState = rememberLazyListState()
val isScrolled by remember {
derivedStateOf {
listState.firstVisibleItemIndex > 0 || listState.firstVisibleItemScrollOffset > 100
}
}

Box(modifier = Modifier.fillMaxSize())
{
Column(
modifier = Modifier
.fillMaxSize()
) {
UlbanDetailAppBar(
leftIcon = DesignSystemR.drawable.hifive,
title = stringResource(id = R.string.relay_challenge),
content = stringResource(id = R.string.relay_challenge),
topDescription = "${uiState.relayDetail.startTime.formatToMonthDayTime()} ~ ${uiState.relayDetail.endTime.formatToMonthDayTime()}",
bottomDescription = stringResource(
id = R.string.relay_detail_last_member,
uiState.relayDetail.lastMemberName
),
color = Orange,
expanded = !isScrolled,
)
Column(
modifier = Modifier
.fillMaxSize()
.padding(top = 8.dp, start = 16.dp, end = 16.dp, bottom = 16.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
modifier = Modifier
.padding(start = 4.dp)
.size(32.dp),
painter = painterResource(id = DesignSystemR.drawable.member),
tint = Color.Unspecified,
contentDescription = null
)
Text(
text = stringResource(
id = R.string.relay_detail_total_count,
uiState.relayDetail.lastTurn
),
style = UlbanTypography.bodyMedium.copy(fontWeight = FontWeight.Bold)
)
}
HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp))

if (uiState.relayDetail.runnerList.isEmpty()) {
Text(
text = stringResource(id = R.string.relay_no_history),
style = UlbanTypography.bodyMedium.copy(fontWeight = FontWeight.Bold)
)
} else {
LazyColumn(
state = listState,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
items(uiState.relayDetail.runnerList) { runner ->
UlbanRunnerItem(
memberPhoto = runner.memberPhoto,
memberName = runner.memberName,
time = runner.time,
question = runner.question,
isLastTurn = runner.endStatus
)
}
}
}
}
}
}
}

@Composable
@Preview(showBackground = true)
fun RelayDetailScreenPreview() {
UlbanTheme {
RelayDetailScreen()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.sixkids.student.relay.detail

import androidx.lifecycle.SavedStateHandle
import com.sixkids.student.relay.navigation.RelayRoute.RELAY_ID_NAME
import com.sixkids.ui.base.BaseViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject


@HiltViewModel
class RelayDetailViewModel @Inject constructor(
savedStateHandle: SavedStateHandle
) : BaseViewModel<RelayDetailState, RelayDetailSideEffect>(RelayDetailState())
{
private val relayId = savedStateHandle.get<Long>(RELAY_ID_NAME)

fun getRelayDetail() {

}
}
Loading

0 comments on commit ea40aef

Please sign in to comment.