diff --git a/.gitignore b/.gitignore index aa724b77..64ef9d56 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ .externalNativeBuild .cxx local.properties +.idea/deploymentTargetSelector.xml \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index b268ef36..00e85ee2 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -2,7 +2,18 @@ - + + + diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b679eeb7..a7b39ef7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -52,6 +52,8 @@ dependencies { implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.foundation) + implementation(libs.androidx.lifecycle.viewmodel.compose) implementation(libs.androidx.navigation.runtime.android) implementation(libs.accompanist.pager) implementation(libs.accompanist.pager.indicators) diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/MenuItemButton.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/MenuItemButton.kt new file mode 100644 index 00000000..34abd394 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/MenuItemButton.kt @@ -0,0 +1,89 @@ +package com.texthip.thip.ui.common.buttons + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +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.graphics.painter.Painter +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun MenuItemButton( + text: String, + icon: Painter? = null, + contentColor: Color, + backgroundColor: Color, + hasRightIcon: Boolean = false, + modifier: Modifier = Modifier, + onClick: () -> Unit = {}, +) { + val hasLeftIcon = icon != null + + Row( + modifier = modifier + .fillMaxWidth() + .height(56.dp) + .background(color = backgroundColor, shape = RoundedCornerShape(12.dp)) + .clickable(onClick = onClick) + .padding(horizontal = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + if (hasLeftIcon) { + Icon( + painter = icon, + contentDescription = null, + tint = contentColor, + ) + Spacer(modifier = Modifier.width(12.dp)) + } + Text( + text = text, + color = contentColor, + style = typography.smalltitle_sb600_s16_h24, + ) + } + if (hasRightIcon) { + Icon( + painter = painterResource(R.drawable.ic_chevron), + contentDescription = null, + tint = contentColor, + ) + } + + } +} + +@Preview +@Composable +private fun MenuItemButtonPreview() { + MenuItemButton( + text = stringResource(R.string.saved), + icon = painterResource(R.drawable.ic_save), + contentColor = colors.White, + backgroundColor = colors.DarkGrey02, + hasRightIcon = true, + modifier = Modifier + .fillMaxWidth(), + onClick = {} + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt index 97e4854b..5e70609c 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt @@ -20,15 +20,15 @@ import com.texthip.thip.R import com.texthip.thip.ui.theme.ThipTheme.colors @Composable -fun ToggleSwitchButton() { - var isChecked by remember { mutableStateOf(true) } - +fun ToggleSwitchButton( + isChecked: Boolean, + onToggleChange: (Boolean) -> Unit +) { + //var isChecked by remember { mutableStateOf(true) } Switch( modifier = Modifier.padding(4.dp), checked = isChecked, - onCheckedChange = { - isChecked = it - }, + onCheckedChange = onToggleChange, colors = SwitchDefaults.colors( checkedThumbColor = colors.White, checkedTrackColor = colors.Purple, @@ -49,11 +49,16 @@ fun ToggleSwitchButton() { @Preview @Composable private fun ToggleSwitchButtonPreview() { + var isChecked by remember { mutableStateOf(true) } + Column( modifier = Modifier .fillMaxSize() .padding(30.dp) ) { - ToggleSwitchButton() + ToggleSwitchButton( + isChecked = isChecked, + onToggleChange = { isChecked = it } + ) } } diff --git a/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt b/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt index cca99e99..e23d86a6 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt @@ -1,6 +1,5 @@ package com.texthip.thip.ui.common.cards -import androidx.compose.ui.graphics.Color import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable @@ -25,6 +24,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview @@ -51,7 +51,7 @@ fun CardAlarm( .fillMaxWidth() .clickable { onClick() }, colors = CardDefaults.cardColors( - containerColor = if (isRead) containerColorUnread else containerColorRead + containerColor = if (isRead) containerColorRead else containerColorUnread ), elevation = CardDefaults.cardElevation(defaultElevation = 2.dp), shape = RoundedCornerShape(12.dp) diff --git a/app/src/main/java/com/texthip/thip/ui/common/forms/FormTextFieldDefault.kt b/app/src/main/java/com/texthip/thip/ui/common/forms/FormTextFieldDefault.kt index a04f60ba..55f2972e 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/forms/FormTextFieldDefault.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/forms/FormTextFieldDefault.kt @@ -4,6 +4,9 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape @@ -33,7 +36,8 @@ fun FormTextFieldDefault( hint: String, showLimit: Boolean = false, limit: Int = 10, - showIcon: Boolean = true + showIcon: Boolean = true, + containerColor: Color = colors.Black ) { var text by rememberSaveable { mutableStateOf("") } val myStyle = typography.menu_r400_s14_h24.copy(lineHeight = 14.sp) @@ -41,7 +45,8 @@ fun FormTextFieldDefault( // 글자수 제한 적용 val displayText = if (showLimit && text.length > limit) text.substring(0, limit) else text - Box(modifier = modifier) { + Box(modifier = modifier + .height(48.dp)) { OutlinedTextField( value = displayText, onValueChange = { @@ -56,15 +61,14 @@ fun FormTextFieldDefault( ) }, textStyle = myStyle, - modifier = Modifier - .size(width = 320.dp, height = 48.dp), + modifier = Modifier.fillMaxSize(), shape = RoundedCornerShape(12.dp), colors = TextFieldDefaults.colors( focusedTextColor = colors.White, focusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent, - focusedContainerColor = colors.Black, - unfocusedContainerColor = colors.Black, + focusedContainerColor = containerColor, + unfocusedContainerColor = containerColor, cursorColor = colors.NeonGreen ), trailingIcon = { diff --git a/app/src/main/java/com/texthip/thip/ui/common/header/AuthorHeader.kt b/app/src/main/java/com/texthip/thip/ui/common/header/AuthorHeader.kt index 8f98f717..38d1ab0d 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/header/AuthorHeader.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/header/AuthorHeader.kt @@ -28,6 +28,7 @@ import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography import com.texthip.thip.R +import com.texthip.thip.ui.common.buttons.OutlinedButton import com.texthip.thip.ui.theme.Grey02 @Composable @@ -36,7 +37,8 @@ fun AuthorHeader( profileImage: Painter?, nickname: String, badgeText: String, - onSubscribeClick: () -> Unit + buttonText: String, + onButtonClick: () -> Unit = {} ) { Row( modifier = modifier @@ -77,21 +79,13 @@ fun AuthorHeader( maxLines = 1 ) } - - Box( + OutlinedButton( modifier = Modifier - .clip(RoundedCornerShape(20.dp)) - .border(1.dp, Grey02, RoundedCornerShape(20.dp)) - .background(Color.Transparent) - .clickable { onSubscribeClick() } - .padding(horizontal = 12.dp, vertical = 8.dp) - ) { - Text( - text = stringResource(R.string.subscribe), - style = typography.menu_m500_s14_h24, - color = colors.White - ) - } + .size(width = 51.dp, height = 35.dp), + text = buttonText, + textStyle = typography.menu_m500_s14_h24, + onClick = onButtonClick + ) } } @@ -103,7 +97,7 @@ fun PreviewAuthorHeader() { profileImage = null, nickname = "열자자제한열열자제한", badgeText = "칭호칭호칭호", - onSubscribeClick = { println("구독") } + buttonText = "구독" ) } } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt b/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt index 20c08449..6c29cdb8 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape @@ -45,6 +46,7 @@ fun ProfileBar( Row( modifier = modifier .fillMaxWidth() + .padding( vertical = 12.dp) .clickable { onClick() }, verticalAlignment = Alignment.CenterVertically ) { diff --git a/app/src/main/java/com/texthip/thip/ui/common/modal/DialogPopup.kt b/app/src/main/java/com/texthip/thip/ui/common/modal/DialogPopup.kt index e920b072..857948fa 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/modal/DialogPopup.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/modal/DialogPopup.kt @@ -12,8 +12,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -47,7 +45,7 @@ fun DialogPopup( verticalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxSize() ) { - Column { + Column (){ Text( text = title, color = colors.White, @@ -61,7 +59,6 @@ fun DialogPopup( ) } - //TODO: 추후 버튼 공통 컴포넌트로 변경 Row( horizontalArrangement = Arrangement.spacedBy(20.dp), modifier = Modifier.fillMaxWidth() @@ -71,14 +68,14 @@ fun DialogPopup( contentColor = colors.White, backgroundColor = colors.Grey02, modifier = Modifier.weight(1f), - onClick = {}, + onClick = onCancel, ) ActionMediumButton( text = stringResource(R.string.yes), contentColor = colors.White, backgroundColor = colors.Purple, modifier = Modifier.weight(1f), - onClick = {}, + onClick = onConfirm, ) } diff --git a/app/src/main/java/com/texthip/thip/ui/common/modal/ToastWithDate.kt b/app/src/main/java/com/texthip/thip/ui/common/modal/ToastWithDate.kt new file mode 100644 index 00000000..d5216ca2 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/common/modal/ToastWithDate.kt @@ -0,0 +1,68 @@ +package com.texthip.thip.ui.common.modal + +import android.widget.Toast +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun ToastWithDate( + modifier: Modifier = Modifier, + message: String, + date: String +) { + Box( + modifier = modifier + .clip(RoundedCornerShape(12.dp)) + .background(color = colors.DarkGrey02) + .border( + width = 2.dp, + color = colors.Grey02, + shape = RoundedCornerShape(12.dp) + ) + .padding(15.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = message, + color = colors.White, + style = typography.view_m500_s12_h20 + ) + Text( + text = date, + color = colors.Grey02, + style = typography.timedate_r400_s11 + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun ToastPrev() { + ToastWithDate( + message = stringResource(R.string.push_off), + date = "2025년 6월 29일 22시 30분", + modifier = Modifier.fillMaxWidth() + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/DeleteAccountCompleteScreen.kt b/app/src/main/java/com/texthip/thip/ui/myPage/DeleteAccountCompleteScreen.kt new file mode 100644 index 00000000..fc79be00 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/DeleteAccountCompleteScreen.kt @@ -0,0 +1,104 @@ +package com.texthip.thip.ui.myPage.screen + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + + +@Composable +fun DeleteAccountCompleteScreen() { + Scaffold( + containerColor = colors.Black, + topBar = { + DefaultTopAppBar( + isRightIconVisible = false, + isTitleVisible = false, + onLeftClick = {}, + ) + } + ) { innerPadding -> + Column( + modifier = Modifier + .padding(innerPadding) + .fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + text = stringResource(R.string.delete_account_complete), + style = typography.title_b700_s20_h24, + color = colors.White, + textAlign = TextAlign.Center, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 12.dp) + ) + Text( + text = stringResource(R.string.see_you_again), + style = typography.menu_m500_s16_h24, + color = colors.White, + textAlign = TextAlign.Center, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 12.dp) + ) + Spacer(modifier = Modifier.height(40.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Image( + painter = painterResource(R.drawable.character_humanities), + contentDescription = null, + modifier = Modifier + .size(80.dp) + ) + Image( + painter = painterResource(R.drawable.character_art), + contentDescription = null, + modifier = Modifier + .size(80.dp) + ) + Image( + painter = painterResource(R.drawable.character_science), + contentDescription = null, + modifier = Modifier + .size(80.dp) + ) + Image( + painter = painterResource(R.drawable.character_literature), + contentDescription = null, + modifier = Modifier + .size(80.dp) + ) + } + } + } +} + +@Preview +@Composable +private fun DeleteAccountCompleteScreenPrev() { + DeleteAccountCompleteScreen() +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/DeleteAccountScreen.kt b/app/src/main/java/com/texthip/thip/ui/myPage/DeleteAccountScreen.kt new file mode 100644 index 00000000..95d5e2d6 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/DeleteAccountScreen.kt @@ -0,0 +1,175 @@ +package com.texthip.thip.ui.myPage.screen + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +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.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import com.texthip.thip.R +import com.texthip.thip.ui.common.buttons.CheckboxButton +import com.texthip.thip.ui.common.modal.DialogPopup +import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar +import com.texthip.thip.ui.theme.DarkGrey02 +import com.texthip.thip.ui.theme.Red +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun DeleteAccountScreen() { + var isChecked by rememberSaveable { mutableStateOf(false) } + val backgroundColor = if (isChecked) colors.Purple else colors.Grey02 + var isDialogVisible by rememberSaveable { mutableStateOf(false) } + + Scaffold( + containerColor = colors.Black, + topBar = { + DefaultTopAppBar( + title = stringResource(R.string.delete_account), + onLeftClick = {}, + ) + }, + bottomBar = { + Row( + modifier = Modifier + .fillMaxWidth() + .height(56.dp) + .background(backgroundColor) + .clickable( + enabled = isChecked, + onClick = { + isDialogVisible = true + }), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + painter = painterResource(R.drawable.ic_bye), + contentDescription = null, + tint = colors.White + ) + Text( + text = stringResource(R.string.leave_thip), + color = colors.White, + style = typography.smalltitle_sb600_s18_h24, + modifier = Modifier.padding(horizontal = 8.dp) + ) + } + } + ) { innerPadding -> + Column( + modifier = Modifier + .padding(20.dp) + .padding(innerPadding) + .fillMaxSize() + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(DarkGrey02, shape = RoundedCornerShape(12.dp)) + .padding(20.dp) + ) { + Column { + Text( + text = stringResource(R.string.leave_thip_notice_title), + style = typography.menu_m500_s16_h24, + color = colors.White + ) + Spacer(modifier = Modifier.height(40.dp)) + Text( + text = buildAnnotatedString { + append(stringResource(R.string.leave_thip_notice_1) + " ") + withStyle(style = SpanStyle(color = Red)) { + append(stringResource(R.string.leave_thip_notice_2)) + } + append(" ") + append(stringResource(R.string.leave_thip_notice_3)) + }, + style = typography.copy_r400_s14, + color = colors.White + ) + Spacer(modifier = Modifier.height(20.dp)) + Text( + text = stringResource(R.string.leave_thip_notice_4), + style = typography.copy_r400_s14, + color = colors.White + ) + Spacer(modifier = Modifier.height(20.dp)) + Text( + text = stringResource(R.string.leave_thip_notice_5), + style = typography.copy_r400_s14, + color = colors.White + ) + } + } + Spacer(modifier = Modifier.height(29.dp)) + Row(verticalAlignment = Alignment.CenterVertically) { + Text( + text = stringResource(R.string.leave_thip_agree), + style = typography.copy_r400_s14, + color = colors.White, + modifier = Modifier.weight(1f) + ) + CheckboxButton( + isChecked = isChecked, + onCheckedChange = { + isChecked = it + + } + ) + } + } + if (isDialogVisible) { + Dialog(onDismissRequest = { isDialogVisible = false }) { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + DialogPopup( + modifier = Modifier + .fillMaxWidth(), + title = stringResource(R.string.ask_account_deletion), + description = stringResource(R.string.delete_account_description), + onCancel = { isDialogVisible = false }, + onConfirm = { + isDialogVisible = false + // TODO: 회원탈퇴 로직 + } + ) + } + } + } + } +} + +@Preview +@Composable +private fun DeleteAccountScreenPrev() { + DeleteAccountScreen() +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/EditProfileScreen.kt b/app/src/main/java/com/texthip/thip/ui/myPage/EditProfileScreen.kt new file mode 100644 index 00000000..dad344f2 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/EditProfileScreen.kt @@ -0,0 +1,156 @@ +package com.texthip.thip.ui.myPage.screen + + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.common.forms.FormTextFieldDefault +import com.texthip.thip.ui.common.topappbar.InputTopAppBar +import com.texthip.thip.ui.myPage.component.RoleCard +import com.texthip.thip.ui.myPage.mock.RoleItem +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun EditProfileScreen() { + var selectedIndex by rememberSaveable { mutableStateOf(-1) } + val roleCards = listOf( + RoleItem( + stringResource(R.string.literature), + stringResource(R.string.literary_person), + R.drawable.character_literature, + colors.NeonGreen + ), + RoleItem( + stringResource(R.string.science_it), + stringResource(R.string.scientist), + R.drawable.character_science, + colors.Lavendar + ), + RoleItem( + stringResource(R.string.social_science), + stringResource(R.string.sociologist), + R.drawable.character_sociology, + colors.Orange + ), + RoleItem( + stringResource(R.string.art), + stringResource(R.string.artist), + R.drawable.character_art, + colors.Pink + ), + RoleItem( + stringResource(R.string.humanities), + stringResource(R.string.philosopher), + R.drawable.character_humanities, + colors.Skyblue + ) + ) + Scaffold( + containerColor = colors.Black, + topBar = { + InputTopAppBar( + title = stringResource(R.string.edit_profile), + isRightButtonEnabled = true, + onLeftClick = {}, + onRightClick = {} + ) + } + ) { innerPadding -> + Column( + modifier = Modifier + .padding(innerPadding) + .padding(horizontal = 20.dp) + .fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer(modifier = Modifier.height(40.dp)) + Text( + text = stringResource(R.string.change_nickname), + style = typography.smalltitle_sb600_s18_h24, + color = colors.White, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 12.dp) + ) + //TODO 컴포넌트 수정 필요 -> text count 추가, boolean 값으로 icon, limit 설정가능하도록 + FormTextFieldDefault( + modifier = Modifier.fillMaxWidth(), + showLimit = true, + limit = 10, + showIcon = false, + containerColor = colors.DarkGrey02, + hint = stringResource(R.string.change_nickname) + ) + Spacer(modifier = Modifier.height(40.dp)) + Text( + text = stringResource(R.string.edit_role), + style = typography.smalltitle_sb600_s18_h24, + color = colors.White, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 8.dp) + ) + Text( + text = stringResource(R.string.role_description), + style = typography.copy_r400_s14, + color = colors.White, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 12.dp) + ) + Text( + text = stringResource(R.string.choice_one), + style = typography.info_r400_s12, + color = colors.NeonGreen, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 12.dp) + ) + + + FlowRow( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(20.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + roleCards.forEachIndexed { index, RoleItem -> + RoleCard( + genre = RoleItem.genre, + role = RoleItem.role, + imageResId = RoleItem.imageResId, + genreColor = colors.White, + roleColor = RoleItem.roleColor, + selected = selectedIndex == index, + onClick = { selectedIndex = index } + ) + } + } + + } + } +} + +@Preview +@Composable +private fun EditProfileScreenPrev() { + EditProfileScreen() +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/MyPageScreen.kt b/app/src/main/java/com/texthip/thip/ui/myPage/MyPageScreen.kt deleted file mode 100644 index 0f35fe9a..00000000 --- a/app/src/main/java/com/texthip/thip/ui/myPage/MyPageScreen.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.texthip.thip.ui.myPage - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.navigation.NavController - -@Composable -fun MyPageScreen(navController: NavController) { - Box( - modifier = Modifier.Companion.fillMaxSize(), - contentAlignment = Alignment.Companion.Center - ) { - Text(text = "MyPage Screen") - } -} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/NotificationScreen.kt b/app/src/main/java/com/texthip/thip/ui/myPage/NotificationScreen.kt new file mode 100644 index 00000000..3f6c49ee --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/NotificationScreen.kt @@ -0,0 +1,117 @@ +package com.texthip.thip.ui.myPage.screen + +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.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex +import com.texthip.thip.R +import com.texthip.thip.ui.common.buttons.ToggleSwitchButton +import com.texthip.thip.ui.common.modal.ToastWithDate +import com.texthip.thip.ui.common.topappbar.InputTopAppBar +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography +import kotlinx.coroutines.delay + +@Composable +fun NotificationScreen() { + var isChecked by rememberSaveable { mutableStateOf(true) } + var toastMessage by rememberSaveable { mutableStateOf(null) } + + LaunchedEffect(toastMessage) { + if (toastMessage != null) { + delay(2000) + toastMessage = null + } + } + Box(modifier = Modifier.fillMaxSize()) { + toastMessage?.let { message -> + Box( + modifier = Modifier + .fillMaxWidth() + .zIndex(1f) + .align(Alignment.TopCenter) + .padding(horizontal = 15.dp, vertical = 15.dp), + contentAlignment = Alignment.TopCenter + ) { + ToastWithDate( + message = stringResource( + if (message == "push_on") R.string.push_on else R.string.push_off + ), + date = "2025년 6월 29일 22시 30분", + modifier = Modifier.fillMaxWidth() + ) + } + } + Scaffold( + containerColor = colors.Black, + topBar = { + InputTopAppBar( + title = stringResource(R.string.notification_settings), + isRightButtonEnabled = true, + onLeftClick = {}, + onRightClick = {} + ) + } + ) { innerPadding -> + Column( + modifier = Modifier + .padding(innerPadding) + .padding(horizontal = 20.dp) + .fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = stringResource(R.string.push_notification), + style = typography.smalltitle_sb600_s18_h24, + color = colors.White, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 12.dp) + ) + Row(verticalAlignment = Alignment.CenterVertically) { + Text( + text = stringResource(R.string.notification_description), + style = typography.menu_r400_s14_h24, + color = colors.White, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 8.dp) + .weight(1f) + ) + ToggleSwitchButton( + isChecked = isChecked, + onToggleChange = { + isChecked = it + toastMessage = if (it) "push_on" else "push_off" + } + ) + } + + } + + + } + } +} + +@Preview +@Composable +private fun NotificationScreenPrev() { + NotificationScreen() +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/ReactionsScreen.kt b/app/src/main/java/com/texthip/thip/ui/myPage/ReactionsScreen.kt new file mode 100644 index 00000000..68948902 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/ReactionsScreen.kt @@ -0,0 +1,111 @@ +package com.texthip.thip.ui.myPage.screen + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.common.buttons.OptionChipButton +import com.texthip.thip.ui.common.cards.CardAlarm +import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar +import com.texthip.thip.ui.myPage.mock.ReactionItem +import com.texthip.thip.ui.theme.Black + +@Composable +fun ReactionsScreen() { + //추후 뷰모델로 수정 예정 + val reactions = listOf( + ReactionItem("@user 1님의 피드 글","어쩌구 저쩌구 콘텐츠 내용입니다.어쩌구 저쩌구 콘텐츠 내용입니다.어쩌구 저쩌구 콘텐츠 내용입니다.","좋아요", "2"), + ReactionItem("@user 1님의 글", "어쩌구 저쩌구 콘텐츠 내용입니다.","댓글","7"), + ReactionItem("@user 3님의 기록", "어쩌구 저쩌구 콘텐츠 내용입니다.","댓글", "17"), + ReactionItem("@user 1님의 글", "어쩌구 저쩌구 콘텐츠 내용입니다.", "좋아요", "25"), + ReactionItem("@user 1님의 글", "어쩌구 저쩌구 콘텐츠 내용입니다.","댓글", "7"), + ReactionItem("@user 1님의 글", "어쩌구 저쩌구 콘텐츠 내용입니다.","댓글", "7"), + ReactionItem("@user 1님의 글", "어쩌구 저쩌구 콘텐츠 내용입니다.", "좋아요", "7"), + ReactionItem("@user 1님의 글", "어쩌구 저쩌구 콘텐츠 내용입니다.","댓글", "7"), + ReactionItem("@user 1님의 글", "어쩌구 저쩌구 콘텐츠 내용입니다.","댓글", "7"), + ReactionItem("@user 1님의 글", "어쩌구 저쩌구 콘텐츠 내용입니다.", "좋아요", "7"), + ReactionItem("@user 1님의 글", "어쩌구 저쩌구 콘텐츠 내용입니다.","댓글", "7"), + ReactionItem("@user 1님의 글", "어쩌구 저쩌구 콘텐츠 내용입니다.", "좋아요", "7") + ) + var isLikesSelected by remember { mutableStateOf(false) } + var isCommentsSelected by remember { mutableStateOf(false) } + val filteredReactions = reactions.filter { item -> + when { + isLikesSelected && isCommentsSelected -> true + isLikesSelected -> item.type == stringResource(R.string.likes) + isCommentsSelected -> item.type == stringResource(R.string.comments) + else -> true + } + } + + Scaffold( + containerColor = Black, + topBar = { + DefaultTopAppBar( + title = stringResource(R.string.reactions), + onLeftClick = {}, + ) + } + ) { innerPadding -> + Column( + modifier = Modifier + .padding(innerPadding) + .fillMaxSize() + ) { + //TODO card 컴포넌트 수정 후 적용 & 필터링 기능 + Row(modifier = Modifier.padding(start = 20.dp, top = 20.dp, bottom = 20.dp)) { + OptionChipButton( + text = stringResource(R.string.likes), + isFilled = isLikesSelected, + onClick = {isLikesSelected = !isLikesSelected} + ) + Spacer(modifier = Modifier.width(12.dp)) + OptionChipButton( + text = stringResource(R.string.comments), + isFilled = isCommentsSelected, + onClick = {isCommentsSelected = !isCommentsSelected} + ) + + } + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 20.dp), + verticalArrangement = Arrangement.spacedBy(20.dp) + ) { + items(filteredReactions) { item -> + CardAlarm( + title = item.title, + message = item.message, + timeAgo = item.timeAgo, + isRead = true, + badgeText = item.type, + onClick = {} + ) + } + } + } + } +} + +@Preview +@Composable +private fun ReactionsScreenPrev() { + ReactionsScreen() +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/SavedScreen.kt b/app/src/main/java/com/texthip/thip/ui/myPage/SavedScreen.kt new file mode 100644 index 00000000..332dffe4 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/SavedScreen.kt @@ -0,0 +1,112 @@ +package com.texthip.thip.ui.myPage.screen + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Tab +import androidx.compose.material3.TabRow +import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar +import com.texthip.thip.ui.myPage.component.BookContent +import com.texthip.thip.ui.myPage.component.FeedContent +import com.texthip.thip.ui.theme.Black +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography +import com.texthip.thip.ui.theme.White + +@Composable +fun SavedScreen() { + val tabs = listOf(stringResource(R.string.feed), stringResource(R.string.book)) + var selectedTabIndex by rememberSaveable { mutableStateOf(0) } + + Scaffold( + containerColor = Black, + topBar = { + DefaultTopAppBar( + title = stringResource(R.string.saved), + onLeftClick = {}, + ) + } + ) { innerPadding -> + Column( + modifier = Modifier + .padding(innerPadding) + .fillMaxSize() + ) { + Box(modifier = Modifier.width(160.dp).padding(start = 20.dp)) { + TabRow( + selectedTabIndex = selectedTabIndex, + containerColor = Color.Transparent, + contentColor = colors.White, + indicator = { tabPositions -> + val tabPosition = tabPositions[selectedTabIndex] + + Box( + modifier = Modifier + .tabIndicatorOffset(tabPosition) + .width(48.dp) + .height(2.dp) + .align(Alignment.BottomCenter) + .clip(RoundedCornerShape(1.5.dp)) + .background(White) + ) + }, + divider = {}) { + + tabs.forEachIndexed { index, title -> + val selected = selectedTabIndex == index + Tab( + modifier = Modifier.width(60.dp), + selected = selected, + onClick = { selectedTabIndex = index }, + selectedContentColor = colors.White, + unselectedContentColor = colors.Grey02, + text = { + Text( + textAlign = TextAlign.Center, + text = title, + style = typography.smalltitle_sb600_s18_h24 + ) + } + ) + } + } + } + Box(modifier = Modifier.fillMaxWidth()) { + when (selectedTabIndex) { + 0 -> FeedContent() + 1 -> BookContent() + } + } + } + } +} + + +@Preview +@Composable +private fun SavedScreenPrev() { + SavedScreen() +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/component/BookContent.kt b/app/src/main/java/com/texthip/thip/ui/myPage/component/BookContent.kt new file mode 100644 index 00000000..9d70930a --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/component/BookContent.kt @@ -0,0 +1,28 @@ +package com.texthip.thip.ui.myPage.component + +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.lifecycle.viewmodel.compose.viewModel +import com.texthip.thip.ui.common.cards.CardBookList +import com.texthip.thip.ui.myPage.viewmodel.SavedBookViewModel + +@Composable +fun BookContent(viewModel: SavedBookViewModel = viewModel()) { + val books by viewModel.bookList.collectAsState() + + LazyColumn { + items(items = books, key = { it.id }) { book -> + CardBookList( + title = book.title, + author = book.author, + imageRes = null, + publisher = book.publisher, + isBookmarked = book.isSaved, + onBookmarkClick = { viewModel.toggleBookmark(book.id) } + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/component/FeedContent.kt b/app/src/main/java/com/texthip/thip/ui/myPage/component/FeedContent.kt new file mode 100644 index 00000000..56216cef --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/component/FeedContent.kt @@ -0,0 +1,30 @@ +package com.texthip.thip.ui.myPage.component + +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.res.painterResource +import androidx.lifecycle.viewmodel.compose.viewModel +import com.texthip.thip.ui.myPage.viewmodel.SavedFeedViewModel + +@Composable +fun FeedContent(viewModel: SavedFeedViewModel = viewModel()) { + val feedList by viewModel.feeds.collectAsState() + + LazyColumn { + items(feedList, key = { it.id }) { feed -> + val bookImagePainter = feed.imageUrl?.let { painterResource(it) } + val profileImagePainter = feed.userProfileImage?.let { painterResource(it) } + + SavedFeedCard( + feedItem = feed, + bookImage = bookImagePainter, + profileImage = profileImagePainter, + onBookmarkClick = { viewModel.toggleBookmark(feed.id) }, + onLikeClick = { viewModel.toggleLike(feed.id) } + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/component/RoleCard.kt b/app/src/main/java/com/texthip/thip/ui/myPage/component/RoleCard.kt new file mode 100644 index 00000000..1743529c --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/component/RoleCard.kt @@ -0,0 +1,138 @@ +package com.texthip.thip.ui.myPage.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +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.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.theme.DarkGrey +import com.texthip.thip.ui.theme.NeonGreen +import com.texthip.thip.ui.theme.Pink +import com.texthip.thip.ui.theme.ThipTheme +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography +import com.texthip.thip.ui.theme.White + +@Composable +fun RoleCard( + modifier: Modifier = Modifier, + genre: String, + role: String, + imageResId: Int, + genreColor: Color, + roleColor: Color, + selected: Boolean, + onClick: () -> Unit +) { + val borderColor = if (selected) White else DarkGrey + val bgAlpha = if (selected) 1f else 0.3f + val backgroundBrush = if (selected) { + Brush.verticalGradient( + colors = listOf( + colors.Black.copy(alpha = 0.7f), //상단은 어둡게 + colors.White.copy(alpha = 0.2f) //하단은 밝게 + ) + ) + } else { + SolidColor(colors.Black.copy(alpha = 0.3f)) + } + Box( + modifier = modifier + .width(162.dp) + .height(100.dp) + .clip(RoundedCornerShape(12.dp)) + .background(brush = backgroundBrush, shape = RoundedCornerShape(12.dp)) + .border( + width = 1.dp, + color = borderColor, + shape = RoundedCornerShape(12.dp) + ) + .clickable { onClick() } + ) { + Image( + painter = painterResource(id = imageResId), + contentDescription = null, + modifier = Modifier + .align(Alignment.BottomStart) + .size(80.dp), + contentScale = ContentScale.Fit, + alpha = bgAlpha + ) + Column( + modifier = Modifier + .align(Alignment.TopEnd) + .padding(20.dp), + horizontalAlignment = Alignment.End + ) { + Text( + text = genre, + style = typography.smalltitle_m500_s18_h24, + color = genreColor + ) + Text( + text = role, + style = typography.info_r400_s12, + color = roleColor + ) + } + } +} + +@Preview +@Composable +fun RoleCardPreview() { + var selected1 by rememberSaveable { mutableStateOf(true) } + var selected2 by rememberSaveable { mutableStateOf(false) } + + ThipTheme { + Row( + modifier = Modifier.padding(20.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + RoleCard( + genre = "문학", + role = "문학가", + imageResId = R.drawable.character_literature, + genreColor = White, + roleColor = NeonGreen, + selected = selected1, + onClick = { selected1 = !selected1 } + ) + + RoleCard( + genre = "예술", + role = "예술가", + imageResId = R.drawable.character_art, + genreColor = White, + roleColor = Pink, + selected = selected2, + onClick = { selected2 = !selected2 } + ) + } + } +} diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/component/SavedFeedCard.kt b/app/src/main/java/com/texthip/thip/ui/myPage/component/SavedFeedCard.kt new file mode 100644 index 00000000..cad18ede --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/component/SavedFeedCard.kt @@ -0,0 +1,172 @@ +package com.texthip.thip.ui.myPage.component + +import android.R.attr.contentDescription +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Icon +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.graphics.painter.Painter +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.common.buttons.ActionBookButton +import com.texthip.thip.ui.common.header.ProfileBar +import com.texthip.thip.ui.myPage.mock.FeedItem +import com.texthip.thip.ui.theme.Red +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography +import com.texthip.thip.ui.theme.White + +@Composable +fun SavedFeedCard( + modifier: Modifier = Modifier, + feedItem: FeedItem, + bookImage: Painter? = null, + profileImage: Painter? = null, + onBookmarkClick: () -> Unit = {}, + onLikeClick: () -> Unit = {} +) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(20.dp) + ) { + ProfileBar( + profileImage = profileImage, + topText = feedItem.userName, + bottomText = feedItem.userRole, + showSubscriberInfo = false, + hoursAgo = feedItem.timeAgo + ) + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp, bottom = 16.dp) + ) { + ActionBookButton( + bookTitle = feedItem.bookTitle, + bookAuthor = feedItem.authName, + onClick = {} + ) + } + if (bookImage != null) { + Image( + painter = bookImage , + contentDescription = null, + modifier = Modifier + .fillMaxWidth() + .height(480.dp), + contentScale = ContentScale.Crop + ) + } + + Text( + text = feedItem.content, + style = typography.feedcopy_r400_s14_h20, + color = colors.White, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 16.dp) + ) + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.clickable { onLikeClick() }, + painter = painterResource(if (feedItem.isLiked) R.drawable.ic_heart_filled else R.drawable.ic_heart), + contentDescription = null, + tint = Color.Unspecified + ) + Text( + text = feedItem.likeCount.toString(), + style = typography.feedcopy_r400_s14_h20, + color = colors.White, + modifier = Modifier.padding(start = 5.dp, end = 12.dp) + ) + Icon( + painter = painterResource(R.drawable.ic_comment), + contentDescription = null, + tint = colors.White + ) + Text( + text = feedItem.commentCount.toString(), + style = typography.feedcopy_r400_s14_h20, + color = colors.White, + modifier = Modifier.padding(start = 5.dp, end = 12.dp) + ) + Spacer(modifier = Modifier.weight(1f)) + Icon( + modifier = Modifier.clickable { onBookmarkClick() }, + painter = painterResource(if (feedItem.isSaved) R.drawable.ic_save_filled else R.drawable.ic_save), + contentDescription = null, + tint = Color.Unspecified + ) + } + + } +} + +@Preview +@Composable +private fun SavedFeedCardPrev() { + val feed1 = FeedItem( + id = 1, + userProfileImage = R.drawable.character_literature, + userName = "user.01", + userRole = stringResource(R.string.influencer), + bookTitle = "책 제목", + authName = "한강", + timeAgo = 3, + content = "무한대로입력가능합니닷무한대로입력가능합니닷무한대로입력가능합니닷무한대로입력가능합니닷무한대로입력가능합니닷무한대로입력가능합니닷무한대로입력가능합니닷무한대로입력가능합니닷", + likeCount = 10, + commentCount = 5, + isLiked = false, + isSaved = true, + imageUrl = null + ) + + val feed2 = FeedItem( + id = 2, + userProfileImage = R.drawable.character_art, + userName = "user.01", + userRole = stringResource(R.string.influencer), + bookTitle = "책 제목", + authName = "한강", + timeAgo = 3, + content = "한줄만 입력 가능", + likeCount = 10, + commentCount = 5, + isLiked = false, + isSaved = true, + imageUrl = R.drawable.bookcover_sample + ) + + Column { + SavedFeedCard( + feedItem = feed1, + profileImage = painterResource(feed1.userProfileImage!!), + bookImage = null + ) + SavedFeedCard( + feedItem = feed2, + profileImage = painterResource(feed2.userProfileImage!!), + bookImage = painterResource(feed2.imageUrl!!) + ) + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/mock/BookItem.kt b/app/src/main/java/com/texthip/thip/ui/myPage/mock/BookItem.kt new file mode 100644 index 00000000..bb5c4688 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/mock/BookItem.kt @@ -0,0 +1,10 @@ +package com.texthip.thip.ui.myPage.mock + +data class BookItem( + val id: Int, + val title: String, + val author: String, + val publisher: String, + val imageUrl: String? = null, + val isSaved: Boolean +) diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/mock/FeedItem.kt b/app/src/main/java/com/texthip/thip/ui/myPage/mock/FeedItem.kt new file mode 100644 index 00000000..fab38a1b --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/mock/FeedItem.kt @@ -0,0 +1,18 @@ +package com.texthip.thip.ui.myPage.mock + +data class FeedItem( + val id: Int, + val userProfileImage: Int? = null, + val userName: String, + val userRole: String, + val bookTitle: String, + val authName: String, + val timeAgo: Int, + val content: String, + val likeCount: Int, + val commentCount: Int, + val isLiked: Boolean, + val isSaved: Boolean, + val imageUrl: Int? = null +) + diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/mock/ReactionItem.kt b/app/src/main/java/com/texthip/thip/ui/myPage/mock/ReactionItem.kt new file mode 100644 index 00000000..8ec2098e --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/mock/ReactionItem.kt @@ -0,0 +1,8 @@ +package com.texthip.thip.ui.myPage.mock + +data class ReactionItem( + val title: String, + val message: String, + val type: String, + val timeAgo: String +) \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/mock/RoleItem.kt b/app/src/main/java/com/texthip/thip/ui/myPage/mock/RoleItem.kt new file mode 100644 index 00000000..584cdbb7 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/mock/RoleItem.kt @@ -0,0 +1,10 @@ +package com.texthip.thip.ui.myPage.mock + +import androidx.compose.ui.graphics.Color + +data class RoleItem( + val genre: String, + val role: String, + val imageResId: Int, + val roleColor: Color +) diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/screen/MyPageScreen.kt b/app/src/main/java/com/texthip/thip/ui/myPage/screen/MyPageScreen.kt new file mode 100644 index 00000000..e746dfca --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/screen/MyPageScreen.kt @@ -0,0 +1,188 @@ +package com.texthip.thip.ui.myPage.screen + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.navigation.NavController +import com.texthip.thip.R +import com.texthip.thip.ui.common.buttons.MenuItemButton +import com.texthip.thip.ui.common.header.AuthorHeader +import com.texthip.thip.ui.common.modal.DialogPopup +import com.texthip.thip.ui.common.topappbar.LeftNameTopAppBar +import com.texthip.thip.ui.theme.Black +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun MyPageScreen( + navController: NavController? = null, + nickname: String, + badgeText: String +) { + var showLogoutDialog by remember { mutableStateOf(false) } + Scaffold( + containerColor = Black, + topBar = { + LeftNameTopAppBar( + title = stringResource(R.string.my_page), + leftIcon = painterResource(R.drawable.ic_search), + rightIcon = painterResource(R.drawable.ic_plus) + ) + } + ) { innerPadding -> + Column( + modifier = Modifier + .padding(innerPadding) + .fillMaxSize() + ) { + Spacer(modifier = Modifier.height(40.dp)) + AuthorHeader( + profileImage = null, + nickname = nickname, + badgeText = badgeText, + buttonText = stringResource(R.string.edit) + ) + Spacer(modifier = Modifier.height(40.dp)) + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + ) { + Text( + text = stringResource(R.string.my_activity), + style = typography.smalltitle_sb600_s18_h24, + color = colors.White, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 12.dp) + ) + MenuItemButton( + text = stringResource(R.string.saved), + icon = painterResource(R.drawable.ic_save), + contentColor = colors.White, + backgroundColor = colors.DarkGrey02, + hasRightIcon = true, + modifier = Modifier.fillMaxWidth(), + onClick = {} + ) + Spacer(modifier = Modifier.height(16.dp)) + MenuItemButton( + text = stringResource(R.string.reactions), + icon = painterResource(R.drawable.ic_heart), + contentColor = colors.White, + backgroundColor = colors.DarkGrey02, + hasRightIcon = true, + modifier = Modifier.fillMaxWidth(), + onClick = {} + ) + } + Spacer(modifier = Modifier.height(40.dp)) + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + ) { + Text( + text = stringResource(R.string.menu), + style = typography.smalltitle_sb600_s18_h24, + color = colors.White, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 12.dp) + ) + MenuItemButton( + text = stringResource(R.string.notification_settings), + icon = painterResource(R.drawable.ic_notice), + contentColor = colors.White, + backgroundColor = colors.DarkGrey02, + hasRightIcon = true, + modifier = Modifier.fillMaxWidth(), + onClick = {} + ) + Spacer(modifier = Modifier.height(16.dp)) + MenuItemButton( + text = stringResource(R.string.guide), + icon = painterResource(R.drawable.ic_guide), + contentColor = colors.White, + backgroundColor = colors.DarkGrey02, + hasRightIcon = true, + modifier = Modifier.fillMaxWidth(), + onClick = {} + ) + Spacer(modifier = Modifier.height(16.dp)) + MenuItemButton( + text = stringResource(R.string.customer_service), + icon = painterResource(R.drawable.ic_center), + contentColor = colors.White, + backgroundColor = colors.DarkGrey02, + hasRightIcon = true, + modifier = Modifier.fillMaxWidth(), + onClick = {} + ) + Spacer(modifier = Modifier.height(16.dp)) + MenuItemButton( + text = stringResource(R.string.delete_account), + icon = painterResource(R.drawable.ic_bye), + contentColor = colors.White, + backgroundColor = colors.DarkGrey02, + hasRightIcon = true, + modifier = Modifier.fillMaxWidth(), + onClick = {} + ) + Spacer(modifier = Modifier.height(16.dp)) + MenuItemButton( + text = stringResource(R.string.log_out), + icon = painterResource(R.drawable.ic_logout), + contentColor = colors.Red, + backgroundColor = colors.DarkGrey02, + hasRightIcon = false, + modifier = Modifier.fillMaxWidth(), + onClick = { + showLogoutDialog = true + } + ) + } + if (showLogoutDialog) { + Dialog(onDismissRequest = { showLogoutDialog = false }) { + DialogPopup( + modifier = Modifier + .fillMaxWidth(), + title = stringResource(R.string.log_out), + description = stringResource(R.string.logout_description), + onCancel = { showLogoutDialog = false }, + onConfirm = { + showLogoutDialog = false + // TODO: 로그아웃 로직 + } + ) + } + } + } + } +} + +@Preview +@Composable +private fun MyPagePrev() { + MyPageScreen( + nickname = "ThipUser01", + badgeText = "문학가" + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/viewmodel/SavedBookViewModel.kt b/app/src/main/java/com/texthip/thip/ui/myPage/viewmodel/SavedBookViewModel.kt new file mode 100644 index 00000000..b271d533 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/viewmodel/SavedBookViewModel.kt @@ -0,0 +1,95 @@ +package com.texthip.thip.ui.myPage.viewmodel + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.ViewModel +import com.texthip.thip.ui.myPage.mock.BookItem +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map + +class SavedBookViewModel : ViewModel() { + + private val _bookList = MutableStateFlow>(emptyList()) + val bookList: StateFlow> = _bookList + + init { + loadMockBooks() + } + + private fun loadMockBooks() { + _bookList.value = listOf( + BookItem( + id = 1, + title = "이기적 유전자", + author = "리처드 도킨스", + publisher = "을유문화사", + imageUrl = null, + isSaved = true + ), + BookItem( + id = 2, + title = "이기적 유전자", + author = "리처드 도킨스", + publisher = "을유문화사", + imageUrl = null, + isSaved = true + ), + BookItem( + id = 3, + title = "이기적 유전자", + author = "리처드 도킨스", + publisher = "을유문화사", + imageUrl = null, + isSaved = true + ), + BookItem( + id = 4, + title = "이기적 유전자", + author = "리처드 도킨스", + publisher = "을유문화사", + imageUrl = null, + isSaved = true + ), + BookItem( + id = 5, + title = "이기적 유전자", + author = "리처드 도킨스", + publisher = "을유문화사", + imageUrl = null, + isSaved = true + ), + BookItem( + id = 6, + title = "이기적 유전자", + author = "리처드 도킨스", + publisher = "을유문화사", + imageUrl = null, + isSaved = true + ), + BookItem( + id = 7, + title = "이기적 유전자", + author = "리처드 도킨스", + publisher = "을유문화사", + imageUrl = null, + isSaved = true + ), + BookItem( + id = 8, + title = "이기적 유전자", + author = "리처드 도킨스", + publisher = "을유문화사", + imageUrl = null, + isSaved = true + ) + ) + } + + fun toggleBookmark(id: Int) { + _bookList.value = _bookList.value.map { + if (it.id == id) it.copy(isSaved = !it.isSaved) else it + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/myPage/viewmodel/SavedFeedViewModel.kt b/app/src/main/java/com/texthip/thip/ui/myPage/viewmodel/SavedFeedViewModel.kt new file mode 100644 index 00000000..f0fcbeb5 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/myPage/viewmodel/SavedFeedViewModel.kt @@ -0,0 +1,102 @@ +package com.texthip.thip.ui.myPage.viewmodel + +import androidx.lifecycle.ViewModel +import com.texthip.thip.R +import com.texthip.thip.ui.myPage.mock.FeedItem +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow + +class SavedFeedViewModel: ViewModel() { + private val _feeds = MutableStateFlow( + listOf( + FeedItem( + id = 1, + userProfileImage = R.drawable.character_art, + userName = "user", + userRole = "학생", + bookTitle = "라랄ㄹ라라", + authName = "야야야", + timeAgo = 15, + content = "진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공", + likeCount = 25, + commentCount = 4, + isLiked = false, + isSaved = true + ), + FeedItem( + id = 2, + userProfileImage = R.drawable.character_art, + userName = "user", + userRole = "학생", + bookTitle = "라랄ㄹ라라", + authName = "야야야", + timeAgo = 15, + content = "너무 재밌네요..", + likeCount = 25, + commentCount = 4, + isLiked = false, + isSaved = true, + imageUrl = R.drawable.bookcover_sample + ), + FeedItem( + id = 3, + userProfileImage = R.drawable.character_art, + userName = "user", + userRole = "학생", + bookTitle = "라랄ㄹ라라", + authName = "야야야", + timeAgo = 15, + content = "너무 재밌네요..", + likeCount = 25, + commentCount = 4, + isLiked = false, + isSaved = true, + imageUrl = R.drawable.bookcover_sample + ), + FeedItem( + id = 4, + userProfileImage = R.drawable.character_art, + userName = "user", + userRole = "학생", + bookTitle = "책이름책이름", + authName = "저자이름저자이름", + timeAgo = 25, + content = "진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공", + likeCount = 25, + commentCount = 4, + isLiked = false, + isSaved = true, + imageUrl = R.drawable.bookcover_sample + ), + FeedItem( + id = 5, + userProfileImage = R.drawable.character_art, + userName = "user", + userRole = "학생", + bookTitle = "책이름책이름", + authName = "저자이름저자이름", + timeAgo = 25, + content = "진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공진짜최공진짜최공진차최공", + likeCount = 25, + commentCount = 4, + isLiked = true, + isSaved = true + ), + + + ) + ) + val feeds: StateFlow> = _feeds + + fun toggleBookmark(id: Int) { + _feeds.value = _feeds.value.map { + if (it.id == id) it.copy(isSaved = !it.isSaved) else it + } + } + + fun toggleLike(id: Int) { + _feeds.value = _feeds.value.map { + if (it.id == id) it.copy(isLiked = !it.isLiked) else it + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt b/app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt index 19102a72..cb59a72a 100644 --- a/app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt +++ b/app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt @@ -7,7 +7,7 @@ import androidx.navigation.NavHostController import com.texthip.thip.ui.bookSearch.screen.BookSearchScreen import com.texthip.thip.ui.feed.screen.FeedScreen import com.texthip.thip.ui.group.screen.GroupScreen -import com.texthip.thip.ui.myPage.MyPageScreen +import com.texthip.thip.ui.myPage.screen.MyPageScreen @Composable fun MainNavHost(navController: NavHostController) { @@ -15,6 +15,12 @@ fun MainNavHost(navController: NavHostController) { composable(Routes.Feed.route) { FeedScreen(navController) } composable(Routes.Group.route) { GroupScreen(navController) } composable(Routes.BookSearch.route) { BookSearchScreen(navController) } - composable(Routes.MyPage.route) { MyPageScreen(navController) } + composable(Routes.MyPage.route) { + MyPageScreen( + navController, + nickname = "ThipUser01", + badgeText = "문학가" + ) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/theme/Color.kt b/app/src/main/java/com/texthip/thip/ui/theme/Color.kt index 945fd384..18710484 100644 --- a/app/src/main/java/com/texthip/thip/ui/theme/Color.kt +++ b/app/src/main/java/com/texthip/thip/ui/theme/Color.kt @@ -20,6 +20,7 @@ val OrangeSub = Color(0xFFFF8B17) val genreColor = Color(0xFFB5B35D) val Skyblue = Color(0xFFA1D5FF) val SkyblueSub = Color(0xFF6DB5EE) +val Pink = Color(0xFFFF8BAC) val Lavendar = Color(0xFFC8A5FF) val LavendaSub = Color(0xFFA76FFF) val Yellow = Color(0xFFFFECA7) @@ -36,7 +37,6 @@ val DarkGrey = Color(0xFF3D3D3D) val DarkGrey50 = Color(0x803D3D3D) val DarkGrey02 = Color(0xFF282828) val DarkGrey01 = Color(0x4B4B4B4B) - val Black = Color(0xFF121212) val Black50 = Color(0x80121212) val Black10 = Color(0x1A121212) @@ -57,6 +57,7 @@ data class ThipColors( val genreColor: Color, val Skyblue: Color, val SkyblueSub: Color, + val Pink: Color, val Lavendar: Color, val LavendaSub: Color, val Yellow: Color, @@ -91,6 +92,7 @@ val defaultThipColors = ThipColors( genreColor = genreColor, Skyblue = Skyblue, SkyblueSub = SkyblueSub, + Pink = Pink, Lavendar = Lavendar, LavendaSub = LavendaSub, Yellow = Yellow, diff --git a/app/src/main/res/drawable/character_art.png b/app/src/main/res/drawable/character_art.png new file mode 100644 index 00000000..eacd810e Binary files /dev/null and b/app/src/main/res/drawable/character_art.png differ diff --git a/app/src/main/res/drawable/character_humanities.png b/app/src/main/res/drawable/character_humanities.png new file mode 100644 index 00000000..e3a9d221 Binary files /dev/null and b/app/src/main/res/drawable/character_humanities.png differ diff --git a/app/src/main/res/drawable/character_literature.png b/app/src/main/res/drawable/character_literature.png new file mode 100644 index 00000000..57037f33 Binary files /dev/null and b/app/src/main/res/drawable/character_literature.png differ diff --git a/app/src/main/res/drawable/character_science.png b/app/src/main/res/drawable/character_science.png new file mode 100644 index 00000000..03a25583 Binary files /dev/null and b/app/src/main/res/drawable/character_science.png differ diff --git a/app/src/main/res/drawable/character_sociology.png b/app/src/main/res/drawable/character_sociology.png new file mode 100644 index 00000000..8913147a Binary files /dev/null and b/app/src/main/res/drawable/character_sociology.png differ diff --git a/app/src/main/res/drawable/ic_heart_filled.xml b/app/src/main/res/drawable/ic_heart_filled.xml new file mode 100644 index 00000000..cfb9ba1e --- /dev/null +++ b/app/src/main/res/drawable/ic_heart_filled.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 18e266ad..1ddabbcc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -60,6 +60,64 @@ 다음 페이지명 + + 마이페이지 + 편집 + 내 활동 + 저장 + 반응 + 알림설정 + 가이드 + 고객센터 + 회원탈퇴 + 로그아웃 + 메뉴 + 좋아요 + 댓글 + 피드 + + 프로필 편집 + 닉네임 변경 + 칭호 편집 + 장르는 칭호와 연결돼요. + 아래에서 하나를 선택해주세요. + + 정말로 탈퇴하시겠어요? + \'예\'를 누르면 모든 기록이 사라져요. + + 문학 + 문학가 + 과학·IT + 과학자 + 사회과학 + 사회학자 + 예술 + 예술가 + 인문학 + 철학자 + + 또 THIP 해주실거죠? + + THIP 떠나기 + 탈퇴 주의사항 + 회원탈퇴 시 계정정보는 + 복구 불가능 + 하며 90일 이후 재가입이 가능합니다. + -을 사유로 개인정보를 -개월 간 보존합니다. + 등록된 기록 및 게시물은 자동으로 삭제되지 않습니다.(or 삭제됩니다.) + 주의사항을 확인하였으며 이에 동의합니다. + 탈퇴 완료 + 다음에 또 만나요! + + + 푸시 알림 + 알림센터의 모든 알림을 포함해요 + 푸시 알림이 해제되었어요. + 푸시 알림이 설정되었어요. + + texthip2025@gmail.com + 이메일로 닉네임과 문의사항을 보내주시면\n빠른 시일 내로 해결해 드릴게요! + 진행중 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e91013f9..f596e68f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,6 +9,8 @@ lifecycleRuntimeKtx = "2.8.7" activityCompose = "1.10.1" composeBom = "2024.09.00" navigationCompose = "2.9.0" +foundation = "1.9.0-beta01" +lifecycleViewmodelCompose = "2.9.1" navigationRuntimeAndroid = "2.9.0" accompanistPager = "0.36.0" accompanistPagerIndicators = "0.36.0" @@ -29,6 +31,8 @@ androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-man androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-material3 = { group = "androidx.compose.material3", name = "material3" } androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } +androidx-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "foundation" } +androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelCompose" } androidx-navigation-runtime-android = { group = "androidx.navigation", name = "navigation-runtime-android", version.ref = "navigationRuntimeAndroid" } accompanist-pager = { group = "com.google.accompanist", name = "accompanist-pager", version.ref = "accompanistPager" } accompanist-pager-indicators = { group = "com.google.accompanist", name = "accompanist-pager-indicators", version.ref = "accompanistPagerIndicators" }