From 8bd1495c7545309dec5ebc34fa991994f0e49ee6 Mon Sep 17 00:00:00 2001 From: Ray Jang Date: Wed, 21 Feb 2024 01:31:39 +0900 Subject: [PATCH] =?UTF-8?q?[Feature]=20=EB=94=94=EC=9E=90=EC=9D=B8=20QA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/common/theme/Typography.kt | 26 +- .../presentation/ui/main/home/HomeScreen.kt | 2 +- .../home/schedule/add/ScheduleAddScreen.kt | 801 ++++++++++-------- .../main/home/statistics/StatisticsScreen.kt | 22 +- .../home/statistics/me/StatisticsMeScreen.kt | 4 +- .../me/event/StatisticsMeEventScreen.kt | 6 +- 6 files changed, 489 insertions(+), 372 deletions(-) diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/common/theme/Typography.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/common/theme/Typography.kt index ca472276..ce2ae4a6 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/common/theme/Typography.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/common/theme/Typography.kt @@ -14,7 +14,7 @@ private val EmptyTextStyle = TextStyle( ) val Typography = Typography( - defaultFontFamily = FontFamily.Default, + defaultFontFamily = FontFamily(Font(R.font.pretendard)), h1 = EmptyTextStyle, h2 = EmptyTextStyle, h3 = EmptyTextStyle, @@ -31,62 +31,62 @@ val Typography = Typography( ) val Headline0 = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily(Font(R.font.pretendard)), fontWeight = FontWeight.SemiBold, fontSize = 24.sp ) val Headline1 = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily(Font(R.font.pretendard)), fontWeight = FontWeight.SemiBold, fontSize = 20.sp ) val Headline2 = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily(Font(R.font.pretendard)), fontWeight = FontWeight.SemiBold, fontSize = 18.sp ) val Headline3 = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily(Font(R.font.pretendard)), fontWeight = FontWeight.SemiBold, fontSize = 16.sp ) val Body0 = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily(Font(R.font.pretendard)), fontWeight = FontWeight.Normal, fontSize = 16.sp ) val Body1 = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily(Font(R.font.pretendard)), fontWeight = FontWeight.Normal, fontSize = 14.sp ) val Body2 = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily(Font(R.font.pretendard)), fontWeight = FontWeight.Normal, fontSize = 12.sp ) val Caption1 = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily(Font(R.font.pretendard)), fontWeight = FontWeight.Normal, fontSize = 12.sp ) val Caption2 = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily(Font(R.font.pretendard)), fontWeight = FontWeight.Medium, fontSize = 12.sp ) val Caption3 = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily(Font(R.font.pretendard)), fontWeight = FontWeight.Normal, fontSize = 10.sp ) val Caption4 = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily(Font(R.font.pretendard)), fontWeight = FontWeight.SemiBold, fontSize = 10.sp ) val Caption5 = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily(Font(R.font.pretendard)), fontWeight = FontWeight.Medium, fontSize = 10.sp ) diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/HomeScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/HomeScreen.kt index fa84e6d1..8fa21dfb 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/HomeScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/HomeScreen.kt @@ -178,7 +178,7 @@ private fun HomeBottomBarScreen( onClick: (Int) -> Unit ) { BottomNavigation( - elevation = 3.dp, + elevation = 15.dp, backgroundColor = Gray000, modifier = Modifier .fillMaxWidth() diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddScreen.kt index 0bacfb39..2f4c516e 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddScreen.kt @@ -4,8 +4,10 @@ import ac.dnd.mour.android.domain.model.feature.relation.RelationSimple import ac.dnd.mour.android.presentation.R import ac.dnd.mour.android.presentation.common.theme.Body0 import ac.dnd.mour.android.presentation.common.theme.Body1 +import ac.dnd.mour.android.presentation.common.theme.Gray000 import ac.dnd.mour.android.presentation.common.theme.Gray200 import ac.dnd.mour.android.presentation.common.theme.Gray600 +import ac.dnd.mour.android.presentation.common.theme.Gray700 import ac.dnd.mour.android.presentation.common.theme.Gray800 import ac.dnd.mour.android.presentation.common.theme.Headline1 import ac.dnd.mour.android.presentation.common.theme.Headline3 @@ -19,6 +21,7 @@ import ac.dnd.mour.android.presentation.common.util.coroutine.event.EventFlow import ac.dnd.mour.android.presentation.common.util.coroutine.event.MutableEventFlow import ac.dnd.mour.android.presentation.common.util.coroutine.event.eventObserve import ac.dnd.mour.android.presentation.common.view.DialogScreen +import ac.dnd.mour.android.presentation.common.view.SnackBarScreen import ac.dnd.mour.android.presentation.common.view.calendar.CalendarPicker import ac.dnd.mour.android.presentation.common.view.calendar.TimePicker import ac.dnd.mour.android.presentation.common.view.chip.ChipItem @@ -36,7 +39,9 @@ import ac.dnd.mour.android.presentation.ui.main.ApplicationState import ac.dnd.mour.android.presentation.ui.main.home.common.relation.get.SearchRelationScreen import ac.dnd.mour.android.presentation.ui.main.home.schedule.add.notification.ScheduleAddNotificationScreen import ac.dnd.mour.android.presentation.ui.main.rememberApplicationState +import androidx.activity.compose.BackHandler import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource @@ -51,6 +56,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardActions @@ -75,9 +81,13 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.datetime.Clock import kotlinx.datetime.DateTimeUnit @@ -119,6 +129,7 @@ fun ScheduleAddScreen( var isAddSuccessShowing: Boolean by remember { mutableStateOf(false) } var isEditSuccessShowing: Boolean by remember { mutableStateOf(false) } var isRemoveSuccessShowing: Boolean by remember { mutableStateOf(false) } + var isOutPageShowing: Boolean by remember { mutableStateOf(false) } val isConfirmEnabled: Boolean = relation != null && eventName.isNotBlank() && model.state != ScheduleAddState.Loading @@ -199,32 +210,102 @@ fun ScheduleAddScreen( ) } - if (isEditSuccessShowing) { + if (isRemoveSuccessShowing) { DialogScreen( title = "일정 수정하기", - message = "일정을 수정하였습니다.", + message = "일정을 제거하였습니다.", isCancelable = false, onConfirm = { appState.navController.navigateUp() }, onDismissRequest = { - isEditSuccessShowing = false + isRemoveSuccessShowing = false } ) } - if (isRemoveSuccessShowing) { - DialogScreen( - title = "일정 수정하기", - message = "일정을 제거하였습니다.", - isCancelable = false, - onConfirm = { - appState.navController.navigateUp() - }, + if (isOutPageShowing) { + Dialog( + properties = DialogProperties( + dismissOnBackPress = true, + dismissOnClickOutside = true + ), onDismissRequest = { - isRemoveSuccessShowing = false + isOutPageShowing = false } - ) + ) { + Card( + backgroundColor = Color.White, + shape = Shapes.large + ) { + Column( + modifier = Modifier + .wrapContentSize() + .padding(horizontal = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer(modifier = Modifier.height(30.dp)) + Image( + painter = painterResource(R.drawable.ic_alert_triangle_gray), + contentDescription = null + ) + Spacer(modifier = Modifier.height(20.dp)) + Text( + text = "페이지를 나가면\n수정중인 내용이 삭제돼요.", + style = Body1.merge( + color = Gray800, + fontWeight = FontWeight.SemiBold + ), + textAlign = TextAlign.Center + ) + Spacer(modifier = Modifier.height(20.dp)) + + Row(modifier = Modifier.wrapContentSize()) { + ConfirmButton( + properties = ConfirmButtonProperties( + size = ConfirmButtonSize.Large, + type = ConfirmButtonType.Secondary + ), + modifier = Modifier.weight(1f), + onClick = { + isOutPageShowing = false + appState.navController.popBackStack() + } + ) { + Text( + text = "나가기", + style = Headline3.merge( + color = Gray700, + fontWeight = FontWeight.SemiBold + ) + ) + } + + Spacer(modifier = Modifier.width(10.dp)) + + ConfirmButton( + properties = ConfirmButtonProperties( + size = ConfirmButtonSize.Large, + type = ConfirmButtonType.Primary + ), + modifier = Modifier.weight(1f), + onClick = { + isOutPageShowing = false + } + ) { + Text( + text = "계속 수정", + style = Headline3.merge( + color = Gray000, + fontWeight = FontWeight.SemiBold + ) + ) + } + } + Spacer(modifier = Modifier.height(20.dp)) + } + } + } } val formattedDate = Unit.let { @@ -259,389 +340,413 @@ fun ScheduleAddScreen( }.getOrDefault("?? ??:??") } ?: "시간 없음" - Column( + BackHandler( + enabled = model.isEdit, + onBack = { + isOutPageShowing = true + } + ) + + + + Box( modifier = Modifier .fillMaxSize() .background(color = Color.White) - .verticalScroll(rememberScrollState()) ) { - Row( + Column( modifier = Modifier - .height(56.dp) - .fillMaxWidth() - .padding(horizontal = 20.dp), - verticalAlignment = Alignment.CenterVertically + .fillMaxSize() + .verticalScroll(rememberScrollState()) ) { - Box( - modifier = Modifier.clickable( - interactionSource = remember { MutableInteractionSource() }, - indication = rememberRipple(bounded = false), - onClick = { - appState.navController.navigateUp() - } - ) + Row( + modifier = Modifier + .height(56.dp) + .fillMaxWidth() + .padding(horizontal = 20.dp), + verticalAlignment = Alignment.CenterVertically ) { - Icon( - modifier = Modifier.size(Icon24), - painter = painterResource(id = R.drawable.ic_chevron_left), - contentDescription = null - ) - } - Text( - text = if (model.isEdit) "일정 수정하기" else "일정 추가하기", - style = Headline1 - ) - } - Spacer(modifier = Modifier.height(16.dp)) - Column( - modifier = Modifier.padding(horizontal = 20.dp, vertical = 16.dp) - ) { - Row { - Text( - text = "이름", - style = Body1.merge( - color = Gray800, - fontWeight = FontWeight.SemiBold + Box( + modifier = Modifier.clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple(bounded = false), + onClick = { + appState.navController.navigateUp() + } ) - ) - Spacer(modifier = Modifier.width(6.dp)) + ) { + Icon( + modifier = Modifier.size(Icon24), + painter = painterResource(id = R.drawable.ic_chevron_left), + contentDescription = null + ) + } Text( - text = "*", - style = Body1.merge(color = Negative) + text = if (model.isEdit) "일정 수정하기" else "일정 추가하기", + style = Headline1 ) } - Spacer(modifier = Modifier.height(6.dp)) - if (relation == null) { + Spacer(modifier = Modifier.height(16.dp)) + Column( + modifier = Modifier.padding(horizontal = 20.dp, vertical = 16.dp) + ) { + Row { + Text( + text = "이름", + style = Body1.merge( + color = Gray800, + fontWeight = FontWeight.SemiBold + ) + ) + Spacer(modifier = Modifier.width(6.dp)) + Text( + text = "*", + style = Body1.merge(color = Negative) + ) + } + Spacer(modifier = Modifier.height(6.dp)) + if (relation == null) { + FieldSelectComponent( + isSelected = isGetRelationShowing, + text = "이름 선택", + onClick = { + isGetRelationShowing = true + } + ) + } else { + Card( + modifier = Modifier + .fillMaxWidth() + .height(48.dp) + .clickable { + if (!model.isEdit) { + isGetRelationShowing = true + } + }, + backgroundColor = Primary1, + shape = Shapes.medium, + border = BorderStroke(1.dp, Primary4), + ) { + Row( + modifier = Modifier + .padding(horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Text( + text = relation?.name.orEmpty(), + style = Headline3.merge(Gray800) + ) + Text( + text = "・", + style = Headline3.merge(Gray800) + ) + Text( + text = relation?.group?.name.orEmpty(), + style = Body0.merge(Gray800) + ) + Spacer(modifier = Modifier.width(6.dp)) + Icon( + modifier = Modifier.size(Icon24), + painter = painterResource(id = R.drawable.ic_chevron_right), + contentDescription = null, + tint = Gray600 + ) + } + } + } + Spacer(modifier = Modifier.height(32.dp)) + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "날짜", + style = Body1.merge( + color = Gray800, + fontWeight = FontWeight.SemiBold + ) + ) + Spacer(modifier = Modifier.width(6.dp)) + Text( + text = "*", + style = Body1.merge(color = Negative) + ) + } + Spacer(modifier = Modifier.height(6.dp)) FieldSelectComponent( - isSelected = isGetRelationShowing, - text = "이름 선택", + isSelected = isDatePickerShowing, + text = formattedDate, onClick = { - isGetRelationShowing = true + isDatePickerShowing = true } ) - } else { - Card( - modifier = Modifier - .fillMaxWidth() - .height(48.dp) - .clickable { - if (!model.isEdit) { - isGetRelationShowing = true - } - }, - backgroundColor = Primary1, - shape = Shapes.medium, - border = BorderStroke(1.dp, Primary4), + Spacer(modifier = Modifier.height(24.dp)) + Row( + verticalAlignment = Alignment.CenterVertically ) { - Row( - modifier = Modifier - .padding(horizontal = 16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center - ) { - Text( - text = relation?.name.orEmpty(), - style = Headline3.merge(Gray800) - ) - Text( - text = "・", - style = Headline3.merge(Gray800) + Text( + text = "경사 종류", + style = Body1.merge( + color = Gray800, + fontWeight = FontWeight.SemiBold ) - Text( - text = relation?.group?.name.orEmpty(), - style = Body0.merge(Gray800) - ) - Spacer(modifier = Modifier.width(6.dp)) - Icon( - modifier = Modifier.size(Icon24), - painter = painterResource(id = R.drawable.ic_chevron_right), - contentDescription = null, - tint = Gray600 + ) + Spacer(modifier = Modifier.width(6.dp)) + Text( + text = "*", + style = Body1.merge(color = Negative) + ) + } + Spacer(modifier = Modifier.height(6.dp)) + TypingTextField( + textType = TypingTextFieldType.Basic, + text = eventName, + onValueChange = { text -> + eventName = text + }, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Next + ), + keyboardActions = KeyboardActions( + onNext = { isAlarmDatePickerShowing = true } + ), + hintText = "직접 입력" + ) + Spacer(modifier = Modifier.height(10.dp)) + LazyRow( + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { + items(eventTypeList.size) { index -> + val item = eventTypeList[index] + ChipItem( + chipType = ChipType.BORDER, + currentSelectedId = currentEvent?.let { setOf(it.id) }.orEmpty(), + chipId = item.id, + chipText = item.eventName, + chipCount = 0, + onSelectChip = { id -> + eventName = eventTypeList.find { it.id == id }?.eventName.orEmpty() + } ) } } } - Spacer(modifier = Modifier.height(32.dp)) - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = "날짜", - style = Body1.merge( - color = Gray800, - fontWeight = FontWeight.SemiBold - ) - ) - Spacer(modifier = Modifier.width(6.dp)) - Text( - text = "*", - style = Body1.merge(color = Negative) - ) - } - Spacer(modifier = Modifier.height(6.dp)) - FieldSelectComponent( - isSelected = isDatePickerShowing, - text = formattedDate, - onClick = { - isDatePickerShowing = true - } + Spacer(modifier = Modifier.height(46.dp)) + Divider( + modifier = Modifier.height(8.dp), + color = Gray200 ) - Spacer(modifier = Modifier.height(24.dp)) - Row( - verticalAlignment = Alignment.CenterVertically + Spacer(modifier = Modifier.height(46.dp)) + Column( + modifier = Modifier.padding(horizontal = 20.dp, vertical = 16.dp) ) { - Text( - text = "경사 종류", - style = Body1.merge( - color = Gray800, - fontWeight = FontWeight.SemiBold + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.size(16.dp), + painter = painterResource(id = R.drawable.ic_notification), + contentDescription = null, + tint = Gray600 ) - ) - Spacer(modifier = Modifier.width(6.dp)) - Text( - text = "*", - style = Body1.merge(color = Negative) - ) - } - Spacer(modifier = Modifier.height(6.dp)) - TypingTextField( - textType = TypingTextFieldType.Basic, - text = eventName, - onValueChange = { text -> - eventName = text - }, - keyboardOptions = KeyboardOptions( - keyboardType = KeyboardType.Text, - imeAction = ImeAction.Next - ), - keyboardActions = KeyboardActions( - onNext = { isAlarmDatePickerShowing = true } - ), - hintText = "직접 입력" - ) - Spacer(modifier = Modifier.height(10.dp)) - LazyRow( - horizontalArrangement = Arrangement.spacedBy(6.dp) - ) { - items(eventTypeList.size) { index -> - val item = eventTypeList[index] - ChipItem( - chipType = ChipType.BORDER, - currentSelectedId = currentEvent?.let { setOf(it.id) }.orEmpty(), - chipId = item.id, - chipText = item.eventName, - chipCount = 0, - onSelectChip = { id -> - eventName = eventTypeList.find { it.id == id }?.eventName.orEmpty() - } + Spacer(modifier = Modifier.width(4.dp)) + Text( + text = "미리 알림", + style = Body1.merge( + color = Gray800, + fontWeight = FontWeight.SemiBold + ) ) } - } - } - Spacer(modifier = Modifier.height(46.dp)) - Divider( - modifier = Modifier.height(8.dp), - color = Gray200 - ) - Spacer(modifier = Modifier.height(46.dp)) - Column( - modifier = Modifier.padding(horizontal = 20.dp, vertical = 16.dp) - ) { - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - modifier = Modifier.size(16.dp), - painter = painterResource(id = R.drawable.ic_notification), - contentDescription = null, - tint = Gray600 + Spacer(modifier = Modifier.height(6.dp)) + FieldSelectComponent( + isSelected = isAlarmDatePickerShowing, + text = formattedAlarm, + onClick = { + isAlarmDatePickerShowing = true + } ) - Spacer(modifier = Modifier.width(4.dp)) - Text( - text = "미리 알림", - style = Body1.merge( - color = Gray800, - fontWeight = FontWeight.SemiBold + Spacer(modifier = Modifier.height(24.dp)) + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.size(16.dp), + painter = painterResource(id = R.drawable.ic_clock), + contentDescription = null, + tint = Gray600 + ) + Spacer(modifier = Modifier.width(4.dp)) + Text( + text = "시간", + style = Body1.merge( + color = Gray800, + fontWeight = FontWeight.SemiBold + ) ) - ) - } - Spacer(modifier = Modifier.height(6.dp)) - FieldSelectComponent( - isSelected = isAlarmDatePickerShowing, - text = formattedAlarm, - onClick = { - isAlarmDatePickerShowing = true } - ) - Spacer(modifier = Modifier.height(24.dp)) - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - modifier = Modifier.size(16.dp), - painter = painterResource(id = R.drawable.ic_clock), - contentDescription = null, - tint = Gray600 + FieldSelectComponent( + isSelected = isTimePickerShowing, + text = formattedTime, + onClick = { + isTimePickerShowing = true + } ) - Spacer(modifier = Modifier.width(4.dp)) - Text( - text = "시간", - style = Body1.merge( - color = Gray800, - fontWeight = FontWeight.SemiBold + Spacer(modifier = Modifier.height(24.dp)) + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.size(16.dp), + painter = painterResource(id = R.drawable.ic_location), + contentDescription = null, + tint = Gray600 + ) + Spacer(modifier = Modifier.width(4.dp)) + Text( + text = "위치", + style = Body1.merge( + color = Gray800, + fontWeight = FontWeight.SemiBold + ) ) - ) - } - FieldSelectComponent( - isSelected = isTimePickerShowing, - text = formattedTime, - onClick = { - isTimePickerShowing = true } - ) - Spacer(modifier = Modifier.height(24.dp)) - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - modifier = Modifier.size(16.dp), - painter = painterResource(id = R.drawable.ic_location), - contentDescription = null, - tint = Gray600 + Spacer(modifier = Modifier.height(6.dp)) + TypingTextField( + textType = TypingTextFieldType.Basic, + text = location, + onValueChange = { text -> + location = text + }, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Next + ), + hintText = "위치를 입력해주세요" ) - Spacer(modifier = Modifier.width(4.dp)) - Text( - text = "위치", - style = Body1.merge( - color = Gray800, - fontWeight = FontWeight.SemiBold + Spacer(modifier = Modifier.height(24.dp)) + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.size(16.dp), + painter = painterResource(id = R.drawable.ic_link), + contentDescription = null, + tint = Gray600 ) + Spacer(modifier = Modifier.width(4.dp)) + Text( + text = "초대장 링크", + style = Body1.merge( + color = Gray800, + fontWeight = FontWeight.SemiBold + ) + ) + } + Spacer(modifier = Modifier.height(6.dp)) + TypingTextField( + textType = TypingTextFieldType.Basic, + text = link, + onValueChange = { text -> + link = text + }, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Next + ), + hintText = "모바일 초대장 링크를 입력해주세요" ) - } - Spacer(modifier = Modifier.height(6.dp)) - TypingTextField( - textType = TypingTextFieldType.Basic, - text = location, - onValueChange = { text -> - location = text - }, - keyboardOptions = KeyboardOptions( - keyboardType = KeyboardType.Text, - imeAction = ImeAction.Next - ), - hintText = "위치를 입력해주세요" - ) - Spacer(modifier = Modifier.height(24.dp)) - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - modifier = Modifier.size(16.dp), - painter = painterResource(id = R.drawable.ic_link), - contentDescription = null, - tint = Gray600 - ) - Spacer(modifier = Modifier.width(4.dp)) - Text( - text = "초대장 링크", - style = Body1.merge( - color = Gray800, - fontWeight = FontWeight.SemiBold + Spacer(modifier = Modifier.height(24.dp)) + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.size(16.dp), + painter = painterResource(id = R.drawable.ic_memo), + contentDescription = null, + tint = Gray600 ) + Spacer(modifier = Modifier.width(4.dp)) + Text( + text = "메모", + style = Body1.merge( + color = Gray800, + fontWeight = FontWeight.SemiBold + ) + ) + } + Spacer(modifier = Modifier.height(6.dp)) + TypingTextField( + textType = TypingTextFieldType.LongSentence, + text = memo, + onValueChange = { text -> + memo = text + }, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Done + ), + keyboardActions = KeyboardActions( + onDone = { + onConfirm() + focusManager.clearFocus() + } + ), + hintText = "경사 관련 메모를 입력해주세요" ) } - Spacer(modifier = Modifier.height(6.dp)) - TypingTextField( - textType = TypingTextFieldType.Basic, - text = link, - onValueChange = { text -> - link = text - }, - keyboardOptions = KeyboardOptions( - keyboardType = KeyboardType.Text, - imeAction = ImeAction.Next - ), - hintText = "모바일 초대장 링크를 입력해주세요" - ) - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(46.dp)) Row( - verticalAlignment = Alignment.CenterVertically + modifier = Modifier + .padding(horizontal = 20.dp, vertical = 12.dp) + .fillMaxWidth() ) { - Icon( - modifier = Modifier.size(16.dp), - painter = painterResource(id = R.drawable.ic_memo), - contentDescription = null, - tint = Gray600 - ) - Spacer(modifier = Modifier.width(4.dp)) - Text( - text = "메모", - style = Body1.merge( - color = Gray800, - fontWeight = FontWeight.SemiBold - ) - ) - } - Spacer(modifier = Modifier.height(6.dp)) - TypingTextField( - textType = TypingTextFieldType.LongSentence, - text = memo, - onValueChange = { text -> - memo = text - }, - keyboardOptions = KeyboardOptions( - keyboardType = KeyboardType.Text, - imeAction = ImeAction.Done - ), - keyboardActions = KeyboardActions( - onDone = { - onConfirm() - focusManager.clearFocus() + if (model.isEdit) { + ConfirmButton( + properties = ConfirmButtonProperties( + size = ConfirmButtonSize.Large, + type = ConfirmButtonType.Secondary + ), + isEnabled = isConfirmEnabled, + onClick = { + onRemove() + } + ) { + Icon( + modifier = Modifier.size(Icon24), + painter = painterResource(id = R.drawable.ic_trash), + contentDescription = null + ) } - ), - hintText = "경사 관련 메모를 입력해주세요" - ) - } - Spacer(modifier = Modifier.height(46.dp)) - Row( - modifier = Modifier - .padding(horizontal = 20.dp, vertical = 12.dp) - .fillMaxWidth() - ) { - if (model.isEdit) { + Spacer(modifier = Modifier.width(12.dp)) + } ConfirmButton( properties = ConfirmButtonProperties( size = ConfirmButtonSize.Large, - type = ConfirmButtonType.Secondary + type = ConfirmButtonType.Primary ), + modifier = Modifier.weight(1f), isEnabled = isConfirmEnabled, onClick = { - onRemove() + onConfirm() } - ) { - Icon( - modifier = Modifier.size(Icon24), - painter = painterResource(id = R.drawable.ic_trash), - contentDescription = null + ) { style -> + Text( + text = "저장하기", + style = style ) } - Spacer(modifier = Modifier.width(12.dp)) } - ConfirmButton( - properties = ConfirmButtonProperties( - size = ConfirmButtonSize.Large, - type = ConfirmButtonType.Primary - ), - modifier = Modifier.weight(1f), - isEnabled = isConfirmEnabled, - onClick = { - onConfirm() - } - ) { style -> - Text( - text = "저장하기", - style = style - ) + } + + if (isEditSuccessShowing) { + Box( + modifier = Modifier + .align(Alignment.BottomCenter) + .padding(bottom = 61.dp) + ) { + SnackBarScreen("수정이 완료되었습니다.") } } } @@ -698,7 +803,11 @@ fun ScheduleAddScreen( fun editSchedule(event: ScheduleAddEvent.EditSchedule) { when (event) { ScheduleAddEvent.EditSchedule.Success -> { - isEditSuccessShowing = true + scope.launch(handler) { + isEditSuccessShowing = true + delay(1000L) + isEditSuccessShowing = false + } } } } diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/StatisticsScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/StatisticsScreen.kt index c71537da..5359fbf7 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/StatisticsScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/StatisticsScreen.kt @@ -2,8 +2,10 @@ package ac.dnd.mour.android.presentation.ui.main.home.statistics import ac.dnd.mour.android.presentation.R import ac.dnd.mour.android.presentation.common.theme.Gray000 +import ac.dnd.mour.android.presentation.common.theme.Gray400 import ac.dnd.mour.android.presentation.common.theme.Gray500 import ac.dnd.mour.android.presentation.common.theme.Gray700 +import ac.dnd.mour.android.presentation.common.theme.Gray800 import ac.dnd.mour.android.presentation.common.theme.Headline1 import ac.dnd.mour.android.presentation.common.theme.Headline3 import ac.dnd.mour.android.presentation.common.util.ErrorObserver @@ -31,6 +33,7 @@ import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material.Divider import androidx.compose.material.Tab import androidx.compose.material.TabRow import androidx.compose.material.Text @@ -129,19 +132,20 @@ private fun StatisticsScreen( Box( modifier = Modifier .fillMaxWidth() - .height(50.dp) ) { + Divider( + modifier = Modifier + .align(Alignment.BottomCenter) + .fillMaxWidth() + .height(1.dp), + color = Gray400 + ) TabRow( selectedTabIndex = pagerState.currentPage, - backgroundColor = Color.White, + backgroundColor = Color.Transparent, + contentColor = Gray800, modifier = Modifier.padding(horizontal = 20.dp), - divider = { - Box( - modifier = Modifier - .fillMaxWidth() - .background(Color.Transparent) - ) - } + divider = { } ) { pages.forEachIndexed { index, pageText -> Tab( diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/me/StatisticsMeScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/me/StatisticsMeScreen.kt index 5729bccb..234f92a0 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/me/StatisticsMeScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/me/StatisticsMeScreen.kt @@ -174,7 +174,7 @@ private fun StatisticsMeScreen( formatted.append(",") } } - "${formatted}원" + "-${formatted}원" } val statisticsData: Map> = when (selectedChipType) { MyStatisticsChipType.Take -> model.myStatistics.take @@ -304,7 +304,7 @@ private fun StatisticsMeScreen( ) } Box( - modifier = Modifier.width(60.dp) + modifier = Modifier.width(80.dp) ) { Box( modifier = Modifier diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/me/event/StatisticsMeEventScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/me/event/StatisticsMeEventScreen.kt index 7f278a2b..7c7056bc 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/me/event/StatisticsMeEventScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/me/event/StatisticsMeEventScreen.kt @@ -250,7 +250,11 @@ private fun StatisticsMeEventItemScreen( formatted.append(",") } } - "${formatted}원" + if (isGive) { + "-${formatted}원" + } else { + "${formatted}원" + } } Card(