Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[TNT-115] 연결코드 화면 UI 구현 및 연결 #34

Merged
merged 40 commits into from
Jan 26, 2025
Merged
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
b2ab69c
[TNT-115] design: Color 시스템 추가 및 mainColors redColors로 수정
SeonJeongk Jan 22, 2025
fdeb95c
[TNT-115] design: Typo 시스템 추가
SeonJeongk Jan 22, 2025
8f6bf66
[TNT-115] design: Toast 컴포넌트 구현
SeonJeongk Jan 22, 2025
38a32fc
[TNT-115] feat: connect 모듈 최초 생성
SeonJeongk Jan 22, 2025
95f0379
[TNT-115] design: TopBar back 버튼 없는 컴포넌트 분리
SeonJeongk Jan 22, 2025
f3d527e
[TNT-115] feat: 트레이너 연결 코드 생성 화면 UI 구현
SeonJeongk Jan 23, 2025
041b405
[TNT-115] feat: 트레이니 연결 코드 입력 화면 UI 구현
SeonJeongk Jan 23, 2025
bb8e503
[TNT-115] feat: 트레이니 연결 코드 입력 안내 Dialog 구현
SeonJeongk Jan 23, 2025
1caa1a8
[TNT-115] fix: TnTProfileImage padding 수정
SeonJeongk Jan 23, 2025
3dbb3a8
[TNT-115] feat: 트레이너, 트레이니 연결 완료 화면 UI 구현
SeonJeongk Jan 23, 2025
3f32da5
[TNT-115] fix: 트레이니 연결코드 입력 화면 이름 수정
SeonJeongk Jan 23, 2025
641b992
[TNT-115] feat: 트레이니 연결 코드 입력 화면 UI 구현
SeonJeongk Jan 23, 2025
bf39646
[TNT-115] feat: 트레이니 프로필 화면 UI 구현
SeonJeongk Jan 23, 2025
74f3d08
[TNT-115] feat: 연결 화면 Navigation 구현
SeonJeongk Jan 23, 2025
12989ce
[TNT-115] fix: 스트링 리소스 추가 및 적용
SeonJeongk Jan 23, 2025
6c5c3c8
[TNT-115] fix: ProfileInfo 트레이너, 트레이니로 분리
SeonJeongk Jan 24, 2025
c7ea088
[TNT-115] move: 연결 화면 trainer trainee 분리
SeonJeongk Jan 24, 2025
6d7ea06
[TNT-115] fix: 연결 화면 NavGraph 트레이너, 트레이니로 분리
SeonJeongk Jan 24, 2025
8d83671
[TNT-115] feat: TrainerConnectUiState 프로필 정보 업데이트 및 연결 완료 화면 분리
SeonJeongk Jan 24, 2025
f19248b
[TNT-115] feat: 트레이니 프로필 확인 화면 연결
SeonJeongk Jan 24, 2025
00de8e1
[TNT-115] feat: 트레이니 수업정보 저장 및 프로필 데이터 초기화
SeonJeongk Jan 24, 2025
88a0a6d
[TNT-115] feat: 트레이니 연결 코드 인증 viewModel로 분리
SeonJeongk Jan 24, 2025
369b566
[TNT-115] fix: detekt 오류 해결
SeonJeongk Jan 24, 2025
89b38f3
[TNT-115] feat: 트레이너 초대코드 state 연결
SeonJeongk Jan 24, 2025
c434f26
[TNT-115] fix: 트레이니 프로필 width 수정 및 뒤로가기 추가
SeonJeongk Jan 24, 2025
0336474
[TNT-115] fix: 키 정수로 수정
SeonJeongk Jan 25, 2025
dc7ffc4
[TNT-115] move: connect 모듈 트레이너, 트레이니로 나누기 및 파일 이동
SeonJeongk Jan 25, 2025
93db7b6
[TNT-115] fix: Navigation 및 리소스 분리
SeonJeongk Jan 25, 2025
fed8d51
[TNT-115] fix: domain UserType 기본 정보 가지도록 수정
SeonJeongk Jan 26, 2025
9ca80db
[TNT-115] fix: 공통 스트링 리소스 core:ui로 이동
SeonJeongk Jan 26, 2025
0b6ba0a
[TNT-115] fix: 수업 정보 입력 화면 리뷰 반영
SeonJeongk Jan 26, 2025
76e783f
[TNT-115] fix: UserType 기본값 설정 및 반영, 파일들 package 경로 수정
SeonJeongk Jan 26, 2025
955824b
[TNT-115] fix: 트레이니 프로필 화면 레이아웃 수정
SeonJeongk Jan 26, 2025
e4b4dd7
[TNT-115] fix: 트레이니 연결 코드 입력 화면 리뷰 반영
SeonJeongk Jan 26, 2025
d16f688
[TNT-115] fix: core:ui에 UserDefaultImage 구현
SeonJeongk Jan 26, 2025
29b7b4a
[TNT-115] fix: 트레이니 프로필 확인 화면 UI 수정
SeonJeongk Jan 26, 2025
ab2b43e
[TNT-115] chore: conflicts 해결
SeonJeongk Jan 26, 2025
f1b6e1f
[TNT-115] delete: 기존 connect 모듈 삭제
SeonJeongk Jan 26, 2025
324d534
[TNT-115] fix: non-null assertion 삭제
SeonJeongk Jan 26, 2025
05ffd0f
[TNT-115] move: InputState model로 옮기기
SeonJeongk Jan 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[TNT-115] feat: 트레이니 연결 코드 입력 화면 UI 구현
SeonJeongk committed Jan 23, 2025
commit 041b4057e9cdec7548cf2a53358be76a71c8d2e7
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
package co.kr.tnt.connect

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
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.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.HorizontalDivider
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.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import co.kr.tnt.designsystem.component.TnTTopBar
import co.kr.tnt.designsystem.component.button.TnTBottomButton
import co.kr.tnt.designsystem.component.button.TnTTextButton
import co.kr.tnt.designsystem.component.button.model.ButtonSize
import co.kr.tnt.designsystem.theme.TnTTheme
import co.kr.tnt.feature.connect.R

@Composable
fun TraineeConnectScreen(
onSkipClick: () -> Unit,
onNextClick: () -> Unit,
) {
var code by remember { mutableStateOf("") }
var verificationState by remember { mutableStateOf<Boolean?>(null) }

Scaffold(
topBar = {
TnTTopBar(
title = stringResource(R.string.connect),
trailingComponent = {
Text(
text = stringResource(R.string.skip),
color = TnTTheme.colors.neutralColors.Neutral400,
style = TnTTheme.typography.body2Medium,
modifier = Modifier.clickable {
onSkipClick()
},
)
},
)
},
containerColor = TnTTheme.colors.commonColors.Common0,
) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
Column(modifier = Modifier.fillMaxSize()) {
Spacer(Modifier.padding(top = 24.dp))
Text(
text = stringResource(R.string.enter_invite_code_from_trainer),
color = TnTTheme.colors.neutralColors.Neutral950,
style = TnTTheme.typography.h2,
modifier = Modifier.padding(horizontal = 24.dp),
)
Spacer(Modifier.padding(top = 48.dp))
CodeTextField(
value = code,
onValueChange = {
code = it
verificationState = null
},
modifier = Modifier.padding(horizontal = 20.dp),
verificationState = verificationState,
trailingComponent = {
TnTTextButton(
text = "인증하기",
size = ButtonSize.Small,
onClick = { verificationState = checkValid(code) },
)
},
)
}
TnTBottomButton(
text = stringResource(R.string.complete),
enabled = code.isNotBlank() && verificationState == true,
onClick = onNextClick,
modifier = Modifier.align(Alignment.BottomCenter),
)
}
}
}

// TODO 인증 코드 유효성 검사 API 구현 후 삭제
private fun checkValid(code: String): Boolean {
return code == "12345678"
}

@Composable
private fun CodeTextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
verificationState: Boolean? = null,
trailingComponent: @Composable BoxScope.() -> Unit = {},
) {
var isFocused by remember { mutableStateOf(false) }

val lineColor = when {
verificationState == true -> TnTTheme.colors.blueColors.Blue500
verificationState == false -> TnTTheme.colors.redColors.Red500
isFocused -> TnTTheme.colors.neutralColors.Neutral600
else -> TnTTheme.colors.neutralColors.Neutral200
}

Column(modifier = modifier.fillMaxWidth()) {
Row {
Text(
text = stringResource(R.string.my_invite_code),
style = TnTTheme.typography.body1Bold,
color = TnTTheme.colors.neutralColors.Neutral900,
)
Text(
text = "*",
style = TnTTheme.typography.body1Bold,
color = TnTTheme.colors.redColors.Red500,
)
}
Spacer(Modifier.padding(top = 8.dp))
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
BasicTextField(
value = value,
onValueChange = onValueChange,
singleLine = true,
cursorBrush = SolidColor(TnTTheme.colors.neutralColors.Neutral900),
textStyle = TnTTheme.typography.body1Medium.copy(
color = TnTTheme.colors.neutralColors.Neutral600,
),
modifier = Modifier
.weight(1f)
.onFocusChanged { focusState ->
isFocused = focusState.isFocused
}
.padding(8.dp),
decorationBox = { innerTextField ->
if (value.isEmpty()) {
Text(
text = stringResource(R.string.enter_the_code),
style = TnTTheme.typography.body1Medium,
color = TnTTheme.colors.neutralColors.Neutral400,
)
}
innerTextField()
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
),
)
Box(
modifier = Modifier
.wrapContentSize(Alignment.Center)
.align(Alignment.CenterVertically)
.padding(vertical = 4.dp),
content = trailingComponent,
)
}
HorizontalDivider(
thickness = 1.dp,
color = lineColor,
)
if (verificationState == true) {
Text(
text = stringResource(R.string.verification_success),
style = TnTTheme.typography.body2Medium,
color = TnTTheme.colors.blueColors.Blue500,
modifier = Modifier.padding(top = 6.dp),
)
}
if (verificationState == false) {
Text(
text = stringResource(R.string.verification_fail),
style = TnTTheme.typography.body2Medium,
color = TnTTheme.colors.redColors.Red500,
modifier = Modifier.padding(top = 6.dp),
)
}
}
}

@Preview(showBackground = true)
@Composable
private fun TraineeConnectScreenPreview() {
TnTTheme {
TraineeConnectScreen(
onSkipClick = {},
onNextClick = {},
)
}
}
5 changes: 5 additions & 0 deletions feature/connect/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -9,4 +9,9 @@
<string name="code_reissue">코드 재발급</string>
<string name="code_is_copied">코드가 복사되었어요!</string>

<string name="enter_invite_code_from_trainer">트레이너에게 받은\n초대 코드를 입력해 주세요</string>
<string name="enter_the_code">코드를 입력해주세요</string>
<string name="verification_fail">인증에 실패했어요</string>
<string name="verification_success">인증되었어요</string>

</resources>