Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/tgyuu/#63 #71

Merged
merged 48 commits into from
Dec 28, 2023
Merged

Feature/tgyuu/#63 #71

merged 48 commits into from
Dec 28, 2023

Conversation

tgyuuAn
Copy link
Member

@tgyuuAn tgyuuAn commented Dec 27, 2023

1. ๐Ÿ“„ ๊ด€๋ จ๋œ ์ด์Šˆ ๋ฐ ์†Œ๊ฐœ

#63

File Changed๊ฐ€ ๋„ˆ๋ฌด ์ปค์ง€๋Š” ๊ฒƒ ๊ฐ™์•„์„œ ์ผ์ฐจ์ ์œผ๋กœ PR๋‚ ๋ฆฝ๋‹ˆ๋‹ค.

2. ๐Ÿ”ฅ๋ณ€๊ฒฝ๋œ ์ 

- ๋ฐ”ํ…€ ๋„ค๋น„๊ฒŒ์ด์…˜ ์„ค๋ฌธ ํŽ˜์ด์ง€ ํ™”๋ฉด ์ž‘์•„์กŒ๋‹ค ์ปค์กŒ๋‹ค ํ•˜๋Š” ์ด์Šˆ ์ˆ˜์ •

- ํ”„๋กœํ•„ ํ™”๋ฉด UI ๊ฐœ์„ 

- ํ”„๋กœํ•„ ํ™”๋ฉด UI ์™„์„ฑ

- ํ”„๋กœํ•„ ๋” ๋ณด๊ธฐ ํ™”๋ฉด UI ์™„์„ฑ

- ๊ด€๋ฆฌ ํ™”๋ฉด ์ผ์ •, ์„ค๋ฌธ ๋ฐ์ดํ„ฐ ๋ณ‘๋ ฌ๋กœ ๊ฐ€์ ธ์˜ค๋„๋ก ๋ณ€๊ฒฝ

- ๊ด€๋ฆฌ ํ™”๋ฉด Lottie ์ ์šฉ

- WappTheme.colors ์ƒ‰์ƒ ์ •๋ฆฌ




3. ๐Ÿ“ธ ์Šคํฌ๋ฆฐ์ƒท(์„ ํƒ)

1. ํ”„๋กœํ•„ ํ™”๋ฉด UI ๊ฐœ์„ 

image




2. WappTheme.colors ์ƒ‰์ƒ ์ •๋ฆฌ




3. ๊ด€๋ฆฌ ํ™”๋ฉด ๋ฐ์ดํ„ฐ ๋ณ‘๋ ฌ๋กœ ๊ฐ€์ ธ์˜ค๋„๋ก ๋ณ€๊ฒฝ


3-1. ๊ธฐ์กด (๋ฐ์ดํ„ฐ ์ˆœ์„œ๋Œ€๋กœ ๊ฐ€์ ธ์˜ด)


3-2. ๋ณ€๊ฒฝ (๋ฐ์ดํ„ฐ ๋™์‹œ์— ๊ฐ€์ ธ์˜ด)




4. ์„ค๋ฌธ ํ™”๋ฉด ์ž‘์•„์กŒ๋‹ค๊ฐ€ ๋ณด์—ฌ์ง€๋Š” ์ด์Šˆ ์ˆ˜์ •

์„ค๋ฌธ ํŽ˜์ด์ง€ ์ž‘์•„์กŒ๋‹ค ์ปค์กŒ๋‹ค ์ˆ˜์ •




5. ๊ด€๋ฆฌ ํŽ˜์ด์ง€ Lottie ์ ์šฉ

๊ด€๋ฆฌ ํŽ˜์ด์ง€ Lottie




6. ํ”„๋กœํ•„ ํ™”๋ฉด ๋น„ํšŒ์› ํ™”๋ฉด

image

๋กœ๊ทธ์ธ ํ–ˆ์„ ๋•Œ ํ™”๋ฉด์€ ์œ„ ์›€์งค์—์„œ ๋งŽ์ด ๋ณด์ด๋ฏ€๋กœ ๋”ฐ๋กœ ์˜ฌ๋ฆฌ์ง„ ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค!

์œ„ ํ™”๋ฉด์—์„œ ๋กœ๊ทธ์ธ ํ•˜๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ดˆ๊ธฐ SignIn ํ™”๋ฉด์œผ๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค.

๋’ค๋กœ๊ฐ€๊ธฐ๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋‹ค์‹œ ํ•ด๋‹น ํ™”๋ฉด์œผ๋กœ ๋Œ์•„์˜ต๋‹ˆ๋‹ค.

์›€์งค์ฐ๊ธฐ ๊ท€์ฐฎ์•„์„œ ์•ˆ์˜ฌ๋ ธ์Šต๋‹ˆ๋‹ค. ํ•˜ํ•˜




7. ํ”„๋กœํ•„ ๋” ๋ณด๊ธฐ ํ™”๋ฉด

image

์ขŒ์ธก ์ƒ๋‹จ ํ™”์‚ดํ‘œ ๋ˆ„๋ฅด๋ฉด ๋‹น์—ฐํ•˜๊ฒ ์ง€๋งŒ ํ”„๋กœํ•„ ํ™”๋ฉด์œผ๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค.




4. ๐Ÿ’ก์•Œ๊ฒŒ๋œ ํ˜น์€ ๊ถ๊ธˆํ•œ ์‚ฌํ•ญ๋“ค

1. compose์—์„œ Span ์ ์šฉ

buildAnnotatedString {
    append("๋กœ๊ทธ์ธํ•˜์—ฌ\n")
    withStyle(
        style = SpanStyle(
            color = WappTheme.colors.yellow34,
            textDecoration = TextDecoration.Underline,
        ),
    ) {
        append("WAPP")
    }
    append(" ์™€ ")
    withStyle(
        style = SpanStyle(
            color = WappTheme.colors.yellow34,
            textDecoration = TextDecoration.Underline,
        ),
    ) {
        append("์ถ”์–ต")
    }
    append("์„ ์Œ“์•„๋ณด์„ธ์š”!")
}

์™€ ๊ฐ™์ด buildAnnotatedString์„ ์‚ฌ์šฉํ•˜์—ฌ Span์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

์ถœ์ฒ˜ : Compose ๋กœ Span ์ฃผ๋Š” ๋ฐฉ๋ฒ•




2. ์ฝ”๋ฃจํ‹ด์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ ๊ฐ€์ ธ์˜ฌ ๋•Œ ๋ณ‘๋ ฌ์ ์œผ๋กœ ๋™์‹œ์— ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•

    fun getEventSurveyList() = viewModelScope.launch {
        getMonthEventList()
        getSurveyList()
    }

๋ฅผ

    fun getEventSurveyList() = viewModelScope.launch {
        launch { getMonthEventList() }
        getSurveyList()
    }

์œผ๋กœ ์ˆ˜์ •ํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋™์‹œ์— ๋ณ‘๋ ฌ์ ์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Œ.

์ถœ์ฒ˜ : ์ฝ”ํ‹€๋ฆฐ ์ฝ”๋ฃจํ‹ด ์„œ์ 

๋ธ”๋กœ๊ทธ์— ์ •๋ฆฌํ•ด๋ดค์”๋‹ˆ๋‹ค.




3. ์ง„ํ˜ธ๋‹˜์ด ์ž‘์—…ํ•˜์…จ๋˜ ์„ค๋ฌธ ํŽ˜์ด์ง€ ๋„ค๋น„๊ฒŒ์ด์…˜์—์„œ ์ด๋™ ์‹œ ํ™”๋ฉด์ด ์ž‘์•„์กŒ๋‹ค ์ปค์กŒ๋‹ค ํ•˜๋Š” ์ด์Šˆ

internal fun SurveyScreen(
    viewModel: SurveyViewModel,
    navigateToSurveyAnswer: (Int) -> Unit,
) {
    val context = LocalContext.current
    val surveyFormListUiState = viewModel.surveyFormListUiState.collectAsState().value
    val snackBarHostState = remember { SnackbarHostState() }

    LaunchedEffect(true) {
        viewModel.surveyEvent.collectLatest {
            when (it) {
                is SurveyViewModel.SurveyUiEvent.Failure -> {
                    snackBarHostState.showSnackbar(it.throwable.toSupportingText())
                }

                is SurveyViewModel.SurveyUiEvent.AlreadySubmitted -> {
                    snackBarHostState.showSnackbar(
                        context.getString(R.string.alreay_submitted_description),
                    )
                }

                is SurveyViewModel.SurveyUiEvent.NotSubmitted -> {
                    navigateToSurveyAnswer(it.eventId)
                }
            }
        }
    }

    when (surveyFormListUiState) {
        is SurveyViewModel.SurveyFormListUiState.Init -> { }
        is SurveyViewModel.SurveyFormListUiState.Success -> {
            SurveyContent(
                surveyFormList = surveyFormListUiState.surveyFormList,
                snackBarHostState = snackBarHostState,
                selectedSurveyForm = viewModel::isSubmittedSurvey,
            )
        }
    }
}

์›๋ž˜ ์œ„์— ์ฒ˜๋Ÿผ ์ž‘์—…์ด ๋˜์–ด์žˆ์—ˆ๋Š”๋ฐ,

SurveyFormListUiState๋ฅผ ViewModel์—์„œ Success๋กœ ๊ฐ€์ ธ์˜ฌ ๋•Œ ๊นŒ์ง€ ํ™”๋ฉด์— ์•„๋ฌด๊ฒƒ๋„ ๋›ฐ์›Œ์ฃผ์ง€ ์•Š์•„์š”.

๊ทธ๋ž˜์„œ Compose์—์„œ ๋„์›Œ์ค„ ํ™”๋ฉด์ด ์—†๋‹ค๊ณ  ํŒ๋‹จํ•˜๊ณ  ํ™”๋ฉด์„ ๋ณด์—ฌ์ฃผ์ง€ ์•Š์•„์š”.

์ดํ›„, Success๋ฅผ ๊ฐ€์ ธ์˜ค๋ฉด ๋‹ค์‹œ ํ™”๋ฉด์„ ๋„์›Œ์ฃผ๋ฏ€๋กœ ์ž‘์•„์กŒ๋‹ค ์ปค์ง€๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์˜€์Šต๋‹ˆ๋‹ค.




๊ทธ๋ƒฅ ๋‹จ์ˆœํžˆ ์œ„์˜ ์ฝ”๋“œ๋ฅผ Column(modifier.fillMaxSize())๋กœ ๋ฌถ์–ด์ฃผ๋ฉด ๋์ด์—์š”.

๊ทธ๋Ÿฌ๋ฉด ViewModel์—์„œ Success๋ฅผ ๊ฐ€์ ธ์˜ค์ง€ ์•Š๋”๋ผ๋„, ๋นˆ ํ™”๋ฉด์„ ๋„์›Œ์ฃผ๋‹ˆ๊นŒ ํ™”๋ฉด์ด ์ž‘์•„์ง€๋Š” ์ด์Šˆ๊ฐ€ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค!

(๋นˆ ํ™”๋ฉด์ด๋ผ๋„ ๊ฝ‰ ์ฐจ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž‘์•„์ง€๋Š” ํ˜„์ƒ์ด ์‚ฌ๋ผ์ ธ์š”)

๊ทธ๋ฆฌ๊ณ , ์ด ๋นˆ ํ™”๋ฉด์˜ ์‹œ๊ฐ„์„ ๋–ผ์›Œ์ฃผ๊ธฐ ์œ„ํ•ด์„œ CircleLoader Lottie๋ฅผ ๋„ฃ์–ด๋†จ์Šต๋‹ˆ๋‹ค.




4. LazyColumn ์“ธ ๋•Œ, items ์•ˆ์— key

์ด๊ฑด ๋ญ ๋ณ„ ๊ฑฐ ์—†์Šต๋‹ˆ๋‹ค. xml์“ธ ๋•Œ RecyclerView๋ž‘ ListAdapter์ฐจ์ด๋ž‘ ๋˜‘๊ฐ™์•„์š”.

๋ ˆํผ๋Ÿฐ์Šค





์•„์ง ํ”„๋กœํ•„ ํ™”๋ฉด์—์„œ ์œ ์ € ์ •๋ณด, ์œ ์ €๊ฐ€ ๋น„ํšŒ์›, ํšŒ์›, ์šด์˜์ง„์ธ์ง€ ํŒ๋‹จ, ๋‚˜์˜ ์ถœ๊ฒฐ ํ˜„ํ™ฉ, ๋‚˜์˜ ์ถœ์„ ์„ ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ–ˆ์–ด์š”.

์œ ์ € ์ •๋ณด๋ฅผ ์–ด๋–ป๊ฒŒ ๊ฐ€์ ธ์˜ค๋Š” ์ง€ ๋ชฐ๋ผ์„œ ๊ตฌํ˜„๋˜์–ด์žˆ๋Š” ์ง€ ๋ชฐ๋ผ์„œ ๋ณด๋ฅ˜ํ–ˆ์Šต๋‹ˆ๋‹ค์ž‡.

@tgyuuAn tgyuuAn added ๐ŸŒฑ๊ธฐ๋Šฅ๐ŸŒฑ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ๋‘๋‘๋‘ฅ์žฅ! ๐ŸŽจ์œ ์•„์ด๐ŸŽจ ํ”ผ๊ทธ๋งˆ, ์—‘์„ธ๋ฉœ, ์ปดํฌ์ฆˆ ์œ ์•„์ด/์œ ์—‘์Šค ์ž‘์—… ๐Ÿ”ง๋ฆฌํŒฉํ„ฐ๋ง๐Ÿ”ง ๋ฆฌํŒฉํ„ฐ๋ง์ผ๊นŒ์š” ๋ฆฌํŒฉํ† ๋ง์ผ๊นŒ์š”? ๐Ÿ”ฅ๋ฆฌ๋ทฐ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ค‘๐Ÿ”ฅ PR์„ ์˜ฌ๋ฆฌ๊ณ  ์ฝ”๋“œ๋ฆฌ๋ทฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค. labels Dec 27, 2023
@tgyuuAn tgyuuAn self-assigned this Dec 27, 2023
@tgyuuAn tgyuuAn requested a review from jeongjaino December 27, 2023 15:15
Comment on lines +52 to +56
@Composable
private fun WappAttendanceBadge(isAttendance: Boolean = true) {
val drawableId = if (isAttendance) R.drawable.ic_attendance else R.drawable.ic_absent
Image(painter = painterResource(id = drawableId), contentDescription = "")
}
Copy link
Member Author

Choose a reason for hiding this comment

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

์ง€๊ธˆ ์ถœ์„, ๊ฒฐ์„ ์ด ๊ทธ๋ƒฅ ๋ฒกํ„ฐ๋กœ ๋“ค์–ด๊ฐ€์„œ ๊ทธ๋Ÿฐ์ง€ ๊ธ€์ž๊ฐ€ ์ž˜ ์•ˆ๋ณด์—ฌ์š”,

์ถ”ํ›„์— ๊ทธ๋ƒฅ String + Box๋กœ ๋ฐ”๊พธ๊ฒ ์Šต๋‹ˆ๋‹ค.

Copy link
Member

@jeongjaino jeongjaino left a comment

Choose a reason for hiding this comment

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

ํƒœ๊ทœ์ƒ ๋งŽ์€ ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•œ๋‹ค๊ณ  ๊ณ ์ƒ ๋งŽ์œผ์…จ์–ด์š” ~.

์˜ค๋Š˜ ํ•˜๋ฃจ๋„ ํ™”์ดํŒ…์ž…๋‹ˆ๋‹ท!

@@ -4,5 +4,6 @@ import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

internal fun String.toISOLocalDateTime(): LocalDateTime = LocalDateTime.parse(
this, DateTimeFormatter.ISO_LOCAL_DATE_TIME
this,
DateTimeFormatter.ISO_LOCAL_DATE_TIME,
Copy link
Member

Choose a reason for hiding this comment

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

๐Ÿคฉ๐Ÿ˜Ž๐Ÿคฉ๐Ÿ˜Ž

@@ -74,23 +69,15 @@ internal fun ManagementScreen(
navigateToSurveyCheck: (String) -> Unit,
) {
val snackBarHostState = remember { SnackbarHostState() }
val surveyList = viewModel.surveyList.collectAsState().value
val eventList = viewModel.eventList.collectAsState().value
val surveysState by viewModel.surveyList.collectAsState()
Copy link
Member

Choose a reason for hiding this comment

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

๐Ÿคฉ๐Ÿ˜Ž๐Ÿคฉ๐Ÿ˜Ž

fun previewManagementScreen() {
WappTheme {
// ManageScreen()
}
Copy link
Member

Choose a reason for hiding this comment

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

๐Ÿคฉ๐Ÿ˜Ž๐Ÿคฉ๐Ÿ˜Ž

sealed class SurveysState {
data object Loading : SurveysState()
data class Success(val surveys: List<Survey>) : SurveysState()
data class Failure(val throwable: Throwable) : SurveysState()
Copy link
Member

Choose a reason for hiding this comment

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

์œ„ Events๋ž‘ SurveysState ๋ชจ๋‘ Failure๋ฅผ ๋นผ๋Š”๊ฒŒ ๋‚ซ์ง€์•Š์„๊นŒ์š” ?

errorflow์—์„œ Failure๋ฅผ ๋‹ค ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๊ณ ,
์‚ฌ์šฉํ•˜์‹  when ์ ˆ์—์„œ๋„ Failure๋ฅผ ๋”ฐ๋กœ ์ฒ˜๋ฆฌ ์•ˆํ•˜๊ณ  ๊ณ„์‹œ๋‹ˆ ๋”ฐ๋กœ ํ•„์š” ์—†๋Š” ๊ฒƒ ๊ฐ™์•„์š”.

Copy link
Member Author

@tgyuuAn tgyuuAn Dec 28, 2023

Choose a reason for hiding this comment

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

์ €๋„ ์ด ๋ถ€๋ถ„์ด ์กฐ๊ธˆ ๋งˆ์Œ์— ๊ฑธ๋ ธ๋Š”๋ฐ,

            when (eventsState) {
                is ManagementViewModel.EventsState.Loading -> CircleLoader(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(200.dp),
                )

                is ManagementViewModel.EventsState.Success -> {
                    LazyColumn(
                        verticalArrangement = Arrangement.spacedBy(16.dp),
                    ) {
                        itemsIndexed(
                            items = eventsState.events.takeLast(2),
                            key = { index, event -> event.eventId },
                        ) { currentIndex, event ->
                            ManagementEventItem(
                                item = event,
                                cardColor = ManagementCardColor(currentIndex = currentIndex),
                                onCardClicked = { eventId -> onCardClicked(eventId) },
                            )
                        }
                    }

                    WappButton(
                        textRes = R.string.event_registration,
                        onClick = { onAddEventButtonClicked() },
                    )
                }

                is ManagementViewModel.EventsState.Failure -> {}
            }

์ด๋ ‡๊ฒŒ UiState๋ฅผ ๋ถ„๊ธฐ๋กœ Lottie๋›ฐ์›Œ์ฃผ๋Š” ๋ถ€๋ถ„์—์„œ Failure๋กœ ๋“ค์–ด์˜ค๋ฉด ErrorFlow๋กœ SnackBar๋‚˜ Toast๋งŒ ๋„์›Œ์ฃผ๊ณ  ํ™”๋ฉด์—์„œ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ๋„์›Œ์ค˜์š”


.

๊ทธ๋ž˜์„œ ๋งŒ์•ฝ ๋ฐ์ดํ„ฐ๊ฐ€ ์•ˆ ๋“ค์–ด์™”์„ ๊ฒฝ์šฐ ํŠน๋ณ„ํ•œ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ๋ ค๊ณ  ์—ฌ์ง€๋ฅผ ๋‚จ๊ฒจ๋‘” ๊ฑฐ์˜€์–ด์š”.

์ง€๊ธˆ์€ ์ €ํฌ๋ผ๋ฆฌ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฑฐ๋ผ์„œ Failure๋กœ ๋“ค์–ด์˜ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ž˜ ์—†๊ฒ ์ง€๋งŒ์š”.

Copy link
Member

Choose a reason for hiding this comment

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

ํ˜„์žฌ ๋กœ์ง์—์„œ Failure๋กœ ๋ฐฉ์ถœํ•˜๋Š” ๊ฐ’์˜ ์กฐ๊ฑด์€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ๋กœ ์•Œ๊ณ  ์žˆ์–ด์š” !

์กฐํšŒ๋ฅผ ํ–ˆ๋Š”๋ฐ ๋นˆ ๊ฐ’์ธ ๊ฒฝ์šฐ๋Š” Success -> data -> isEmpty๋กœ ๊ฒ€์ฆํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์•„์š”

ํƒœ๊ทœ๋‹˜์ด ๋ง์”€ํ•˜์‹ ๊ฒŒ ๋„คํŠธ์›Œํฌ ๋ถˆ์•ˆ์ •์ด๋‚˜, ์„œ๋ฒ„ ๋ถˆ์•ˆ์ • ๋“ฑ์œผ๋กœ ๋ฐœ์ƒํ•œ ์‹คํŒจ์— ๋Œ€ํ•ด
์•ฝ๊ฐ„ ๋ฐฐ๋‹ฌ์˜ ๋ฏผ์กฑ์ฒ˜๋Ÿผ ์ „์ฒด ํ™”๋ฉด์„ "ํ™”๋ฉด์„ ๋ถˆ๋Ÿฌ์˜ค์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. "๋กœ ์ฑ„์šธ๊บผ๋ผ๋ฉด ์œ„์˜ ๊ฒฝ์šฐ์ฒ˜๋Ÿผ ์ฒ˜๋ฆฌํ•˜๋Š”๊ฒŒ ๋งž์„ ๊ฒƒ ๊ฐ™๋„ค์š”.

๊ทธ๋ž˜๋„ ์ง€๊ธˆ์€ ๋”ฐ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ์•ˆํ•˜๊ณ  ์žˆ์œผ๋‹ˆ, ๋นผ๋Š”๊ฒŒ ์–ด๋–ป๊ฒ ๋ƒ๋Š”๊ฒŒ ์ฝ”๋ฉ˜ํŠธ ๋‚ด์šฉ์ด์˜€์Šต๋‹ˆ๋‹ค. ํ•˜ํ•˜
๋”ฐ๋กœ ์—ฌ์ง€๋ฅผ ๋‚จ๊ฒจ๋‘๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์˜๋„๋•Œ๋ฌธ์ด๋ผ๋ฉด ๋‚˜๋‘์…”๋„ ๋ฌด๋ฐฉํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Copy link
Member Author

Choose a reason for hiding this comment

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

@jeongjaino

๋„คํŠธ์›Œํฌ ๋ถˆ์•ˆ์ • ์ด๋‚˜ ์„œ๋ฒ„ ๋ถˆ์•ˆ์ •์— ๋Œ€ํ•œ ์‹คํŒจ์˜ ๊ฒฝ์šฐ ๋งž์Šต๋‹ˆ๋‹ค!

์ถ”ํ›„์— ๋ฐ˜๋“œ์‹œ ํ•ด๋‹น ๋ถ„๊ธฐ๋ฅผ ์ฑ„์›Œ๋†“๊ฒ ์”๋‹ˆ๋‹ค!

item = survey,
cardColor = ManagementCardColor(currentIndex = currentIndex),
onCardClicked = { surveyId -> onCardClicked(surveyId) },
when (surveysState) {
Copy link
Member

Choose a reason for hiding this comment

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

์–ด๋–ค ํ•ญ๋ชฉ์ด ๋ถˆ๋Ÿฌ์˜ค๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ

์ผ๋ถ€๋กœ ์ปฌ๋Ÿผ ์•ˆ, Title(์„ค๋ฌธ, ํ–‰์‚ฌ) ๋ฐ‘์— when์ ˆ ์ฒ˜๋ฆฌํ•˜์‹ ๊ฑฐ์ฃ  ??

Copy link
Member Author

Choose a reason for hiding this comment

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

๋„ค ์ง€๊ธˆ ์„ค๋ฌธ, ํ–‰์‚ฌ ๊ฐ๊ฐ ๋กœ๋ ๊ฐ€ ๋Œ์•„๊ฐ€๋Š”๋ฐ,

๊ทธ๋ƒฅ ๋‘๊ฐœ๋ฅผ ํ•˜๋‚˜์˜ ๋กœ๋ ๋กœ ํ•ฉ์น  ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด๋Ÿด ๊ฒฝ์šฐ ๋‘˜ ์ค‘์— ํ•˜๋‚˜๋งŒ ์ž˜๋ชป ๋“ค์–ด์™€๋„ ๋กœ๋ ๊ฐ€ ๊ณ„์™ ๋Œ์•„๊ฐ€์„œ ์ด๋ ‡๊ฒŒ ํ–ˆ์”๋‹ˆ๋‹ค.....!

Copy link
Member

Choose a reason for hiding this comment

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

๊ทผ๋ฐ ํ˜น์‹œ ๊ด€๋ฆฌ ํ™”๋ฉด์—์„œ ์Šคํฌ๋กค ์•ˆ๋˜๋Š” ์ด์Šˆ ํ•ด๊ฒฐ ํ–ˆ๋‚˜์š” ,,, ??

๊ฐ ์„ค๋ฌธ, ์ด๋ฒคํŠธ ์•„์ดํ…œ์ด 2๊ฐœ ์ด์ƒ์ด๋ฉด ํ™”๋ฉด์„ ์ดˆ๊ณผํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ๋”ฐ๋กœ ์Šคํฌ๋กค์ด ์•ˆ๋˜๋”๋ผ๊ณ ์š” ใ… 

Copy link
Member Author

@tgyuuAn tgyuuAn Dec 28, 2023

Choose a reason for hiding this comment

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

@jeongjaino

์˜คํ˜ธ ๊ทธ๊ฑฐ ์•„๋งˆ๋„ LazyColumn์ด Scrollable์ด๋ผ, ๊ฐ€์žฅ ๋ฐ”๊นฅ Composable์„ Scrollable๋กœ ํ•˜๊ฒŒ ๋˜๋ฉด

Scrollable ์•ˆ์— LazyColumn์ด๋ผ๋Š” Scrollable์ด ๋˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํฌ๋ž˜์‹œ๊ฐ€ ๋‚ ๊บผ์—์š”.

xml์—์„œ Scrollview์•ˆ์— RecyclerView๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ, NestedScrollView๋ฅผ ์‚ฌ์šฉํ–ˆ๋˜ ๊ฒƒ ์ฒ˜๋Ÿผ์š”.

์ด๊ฑฐ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์—ˆ๋Š”๋ฐ ์ข€ ๊นŒ๋‹ค๋กœ์› ๋˜ ๊ฑธ๋กœ ๊ธฐ์–ตํ•ด์š”. (์ €๋„ ์ฐพ์•„๋ณด๋‹ค๊ฐ€ ๊ท€์ฐฎ๊ณ  ์–ด๋ ค์›Œ์„œ ์ž ์‹œ ํฌ๊ธฐํ–ˆ์Œ)




์ง€๊ธˆ์€ ์•„๋‹ˆ๊ณ  ๋‚˜์ค‘์— ์ด์Šˆ ํ•˜๋‚˜ ํŒŒ์„œ ํ•ด๊ฒฐํ•ด๋ณด๊ฒ ์”๋‹ˆ๋‹ค!

sealed class EventsState {
data object Loading : EventsState()
data class Success(val events: List<Event>) : EventsState()
data class Failure(val throwable: Throwable) : EventsState()
Copy link
Member

Choose a reason for hiding this comment

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

ํ•ด๋‹น EventsState์—์„œ๋„ Failure๋ฅผ ๋”ฐ๋กœ ์ฒ˜๋ฆฌ ์•ˆํ•˜์‹œ๊ณ  ๊ณ„์…”์„œ
๊ตณ์ด Failure๋ฅผ ๋งŒ๋“œ์‹ค ํ•„์š”๋Š” ์—†๋Š” ๊ฒƒ ๊ฐ™์•„์š” !

Copy link
Member Author

Choose a reason for hiding this comment

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

DB์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๋Œ€๋กœ ๊ฐ€์ ธ์˜ค์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ์—†์„๊นŒ์š” ?!

Copy link
Member

Choose a reason for hiding this comment

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

์œ„์˜ ๋ฆฌ๋ทฐ์™€ ๋‹ต์ด ๊ฐ™์Šต๋‹ˆ๋‹ค !

}

@Composable
private fun SpannableGuestText() = buildAnnotatedString {
Copy link
Member

Choose a reason for hiding this comment

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

๐Ÿ˜‹๐Ÿ˜‹

}

@Composable
private fun WapAttendance(
Copy link
Member

Choose a reason for hiding this comment

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

ํ•ด๋‹น WapAttendance ๋ณด๋‹ค๋Š” AttendanceItem์™€ ๊ฐ™์€

์–ด๋–ค ์ปดํฌ๋„ŒํŠธ์ธ์ง€ ํ™• ์™€๋‹ฟ๋Š” ๋‹ค๋ฅธ ๋„ค์ด๋ฐ ์—†์„๊นŒ์š” ,, ?

Copy link
Member Author

Choose a reason for hiding this comment

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

image

WapAttendance๊ฐ€ ์œ„ ๊ทธ๋ฆผ ๋ถ€๋ถ„์ธ๋ฐ ๋” ์ข‹์€ ๋„ค์ด๋ฐ ์–ด๋–ค๊ฒŒ ์žˆ์„๊นŒ์š” ใ… ใ… ใ…  ๋„ค์ด๋ฐ ์ง€์˜ฅ ๋ด‰์ฐฉ

Copy link
Member

Choose a reason for hiding this comment

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

์ €๋Š” ProfileAttendanceCard ํ•œํ‘œ ๋“œ๋ฆฝ๋‹ˆ๋‹ค โ˜บโ˜บ

Copy link
Member Author

Choose a reason for hiding this comment

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

์ €๋Š” ๋งˆ๋•…ํ•œ ์•„์ด๋””์–ด๋„ ์—†์œผ๋‹ˆ ๊ทธ๊ฑธ๋กœ ๋ฐ”๋กœ ๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค!

}

@Composable
private fun MyAttendanceStatus(modifier: Modifier = Modifier) {
Copy link
Member

Choose a reason for hiding this comment

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

My ๋ณด๋‹ค๋Š” Profile์€ ์–ด๋–ค ๊ฒƒ ๊ฐ™์•„์š” ??

ProfileAttendanceCard ?

Copy link
Member Author

@tgyuuAn tgyuuAn Dec 28, 2023

Choose a reason for hiding this comment

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

๋” ์ข‹์€ ๊ฒƒ ๊ฐ™์•„์š”! ์ˆ˜์ •ํ•ด๋†จ์Šต๋‹ˆ๋‹ค!

Copy link
Member

@jeongjaino jeongjaino Dec 28, 2023

Choose a reason for hiding this comment

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

ํ—‰ ์ง“๋‹ค๋ณด๋‹ˆ ์œ„์—๋ž‘ ๊ฒน์น˜๋„ค์š”

๊ทผ๋ฐ ์œ„์—๊ฐ€ ๋” ์–ด์šธ๋ฆฌ๋Š” ๊ฒƒ ๊ฐ™์•„์š”,,,,,,,,

MyAttendanceStatus AttendanceStatusColumn ํ•œํ‘œ ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค ...

Copy link
Member Author

Choose a reason for hiding this comment

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

MyAttendanceStatus ๋กœ ๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค!

context.getString(R.string.alreay_submitted_description),
)
}
LaunchedEffect(true) {
Copy link
Member

@jeongjaino jeongjaino Dec 28, 2023

Choose a reason for hiding this comment

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

ํƒœ๊ทœ์ƒ ์ € ๋Œ€์‹  ๋ฌธ์ œ ํŒŒ์•…ํ•ด์ฃผ์‹œ๊ณ , ํ•ด๊ฒฐ๊นŒ์ง€ ํ•ด์ฃผ์…”์„œ ๋„ˆ๋ฌด๋„ˆ๋ฌด๋„ˆ๋ฌด (์ž๊พธ์ž๊พธ์ž๊พธ ~~) ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค !!

ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋”ฐ๋กœ Column์„ ์•ˆ๋„ฃ์–ด์ฃผ์…”๋„ ๋˜๊ตฌ, ์‚ฌ์‹ค Scaffold๋งŒ ์˜ฌ๋ฆฌ๋‹ˆ๊นŒ ๋˜๋„ค์šฉ !!

๋”ฐ๋กœ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ ๋ถ™์—ฌ ๋„ฃ์–ด์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค !

package com.wap.wapp.feature.survey

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.wap.designsystem.WappTheme
import com.wap.designsystem.component.WappTitle
import com.wap.wapp.core.commmon.extensions.toSupportingText
import com.wap.wapp.core.commmon.util.DateUtil.yyyyMMddFormatter
import com.wap.wapp.core.model.survey.SurveyForm
import kotlinx.coroutines.flow.collectLatest
import java.time.Duration
import java.time.LocalDateTime

@Composable
internal fun SurveyScreen(
    viewModel: SurveyViewModel,
    navigateToSurveyAnswer: (Int) -> Unit,
) {
    val context = LocalContext.current
    val surveyFormListUiState = viewModel.surveyFormListUiState.collectAsState().value
    val snackBarHostState = remember { SnackbarHostState() }

    LaunchedEffect(true) {
        viewModel.surveyEvent.collectLatest {
            when (it) {
                is SurveyViewModel.SurveyUiEvent.Failure -> {
                    snackBarHostState.showSnackbar(it.throwable.toSupportingText())
                }

                is SurveyViewModel.SurveyUiEvent.AlreadySubmitted -> {
                    snackBarHostState.showSnackbar(
                        context.getString(R.string.alreay_submitted_description),
                    )
                }

                is SurveyViewModel.SurveyUiEvent.NotSubmitted -> {
                    navigateToSurveyAnswer(it.eventId)
                }
            }
        }
    }

    Scaffold(
        modifier = Modifier.fillMaxSize(),
        containerColor = WappTheme.colors.backgroundBlack,
        snackbarHost = { SnackbarHost(snackBarHostState) },
    ) { paddingValues ->
        when (surveyFormListUiState) {
            is SurveyViewModel.SurveyFormListUiState.Init -> { }
            is SurveyViewModel.SurveyFormListUiState.Success -> {
                SurveyContent(
                    surveyFormList = surveyFormListUiState.surveyFormList,
                    paddingValues = paddingValues,
                    selectedSurveyForm = viewModel::isSubmittedSurvey,
                )
            }
        }
    }
}

@Composable
private fun SurveyContent(
    surveyFormList: List<SurveyForm>,
    paddingValues: PaddingValues,
    selectedSurveyForm: (Int) -> Unit,
) {
    Column(
        verticalArrangement = Arrangement.spacedBy(16.dp),
        modifier = Modifier
            .padding(paddingValues)
            .padding(vertical = 16.dp, horizontal = 8.dp),
    ) {
        WappTitle(
            title = stringResource(R.string.survey_title),
            content = stringResource(R.string.survey_content),
        )

        LazyColumn(
            verticalArrangement = Arrangement.spacedBy(8.dp),
        ) {
            items(surveyFormList) { surveyForm ->
                SurveyFormItemCard(
                    surveyForm = surveyForm,
                    selectedSurveyForm = selectedSurveyForm,
                )
            }
        }
    }
}

@Composable
private fun SurveyFormItemCard(
    surveyForm: SurveyForm,
    selectedSurveyForm: (Int) -> Unit,
) {
    Card(
        colors = CardDefaults.cardColors(
            containerColor = WappTheme.colors.black25,
        ),
        modifier = Modifier
            .fillMaxWidth()
            .clickable { selectedSurveyForm(surveyForm.eventId) },
    ) {
        Column(
            verticalArrangement = Arrangement.spacedBy(16.dp),
            modifier = Modifier
                .padding(16.dp),
        ) {
            Row(
                modifier = Modifier.fillMaxWidth(),
            ) {
                Text(
                    text = surveyForm.title,
                    color = WappTheme.colors.white,
                    style = WappTheme.typography.titleBold,
                )
                Text(
                    text = calculateDeadline(surveyForm.deadline),
                    color = WappTheme.colors.yellow34,
                    style = WappTheme.typography.captionMedium,
                    modifier = Modifier.fillMaxWidth(),
                    textAlign = TextAlign.End,
                )
            }

            Text(
                text = surveyForm.content,
                color = WappTheme.colors.grayBD,
                style = WappTheme.typography.contentMedium,
            )
        }
    }
}

private fun calculateDeadline(deadline: LocalDateTime): String {
    val currentDateTime = LocalDateTime.now()
    val duration = Duration.between(currentDateTime, deadline)

    if (duration.toMinutes() < 60) {
        val leftMinutes = duration.toMinutes().toString()
        return leftMinutes + "๋ถ„ ํ›„ ๋งˆ๊ฐ"
    }

    if (duration.toHours() < 24) {
        val leftHours = duration.toHours().toString()
        return leftHours + "์‹œ๊ฐ„ ํ›„ ๋งˆ๊ฐ"
    }

    if (duration.toDays() < 31) {
        val leftDays = duration.toDays().toString()
        return leftDays + "์ผ ํ›„ ๋งˆ๊ฐ"
    }

    return deadline.format(yyyyMMddFormatter) + " ๋งˆ๊ฐ"
}

Copy link
Member Author

Choose a reason for hiding this comment

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

์ˆ˜์ •ํ•ด๋†จ์Šต๋‹ˆ๋‹ค!

@jeongjaino jeongjaino added ๐ŸŒŸ๋จธ์ง€ ํ•ด์ฃผ์„ธ์š”๐ŸŒŸ ์ฝ”๋“œ ๋ฆฌ๋ทฐ๊ฐ€ ์™„๋ฃŒ๋œ ๋’ค PR์„ ์˜ฌ๋ฆฐ์‚ฌ๋žŒ์ด Merge๋ฅผ ํ•˜๋ฉด ๋˜๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค. and removed ๐Ÿ”ฅ๋ฆฌ๋ทฐ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ค‘๐Ÿ”ฅ PR์„ ์˜ฌ๋ฆฌ๊ณ  ์ฝ”๋“œ๋ฆฌ๋ทฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค. labels Dec 28, 2023
@tgyuuAn tgyuuAn merged commit 97848fa into develop Dec 28, 2023
@tgyuuAn tgyuuAn deleted the feature/tgyuu/#63 branch February 6, 2024 08:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
๐ŸŒŸ๋จธ์ง€ ํ•ด์ฃผ์„ธ์š”๐ŸŒŸ ์ฝ”๋“œ ๋ฆฌ๋ทฐ๊ฐ€ ์™„๋ฃŒ๋œ ๋’ค PR์„ ์˜ฌ๋ฆฐ์‚ฌ๋žŒ์ด Merge๋ฅผ ํ•˜๋ฉด ๋˜๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค. ๐ŸŒฑ๊ธฐ๋Šฅ๐ŸŒฑ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ๋‘๋‘๋‘ฅ์žฅ! ๐ŸŽจ์œ ์•„์ด๐ŸŽจ ํ”ผ๊ทธ๋งˆ, ์—‘์„ธ๋ฉœ, ์ปดํฌ์ฆˆ ์œ ์•„์ด/์œ ์—‘์Šค ์ž‘์—… ๐Ÿ”ง๋ฆฌํŒฉํ„ฐ๋ง๐Ÿ”ง ๋ฆฌํŒฉํ„ฐ๋ง์ผ๊นŒ์š” ๋ฆฌํŒฉํ† ๋ง์ผ๊นŒ์š”?
Projects
None yet
2 participants