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

๐Ÿš€ 3๋‹จ๊ณ„ - ํŽ˜์ด๋จผ์ธ (์นด๋“œ์‚ฌ) #64

Open
wants to merge 7 commits into
base: thxallgrace
Choose a base branch
from
Open
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,16 @@
- [x] ์นด๋“œ ๋ชฉ๋ก์ด ๋น„์–ด์žˆ์„ ๋•Œ์—๋Š” "์ƒˆ๋กœ์šด ์นด๋“œ๋ฅผ ๋“ฑ๋กํ•ด์ฃผ์„ธ์š”" ์•ˆ๋‚ด๊ฐ€ ๋…ธ์ถœ๋˜์–ด์•ผ ํ•œ๋‹ค.
- [x] ์นด๋“œ ๋ชฉ๋ก์— ์นด๋“œ๊ฐ€ ํ•œ ๊ฐœ ์žˆ์„ ๋•Œ์˜ ์นด๋“œ ์ถ”๊ฐ€ UI๋Š” ๋ชฉ๋ก ํ•˜๋‹จ์— ๋…ธ์ถœ๋œ๋‹ค.
- [x] ์นด๋“œ ๋ชฉ๋ก์— ์นด๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ์„ ๋•Œ์˜ ์นด๋“œ ์ถ”๊ฐ€ UI๋Š” ์ƒ๋‹จ๋ฐ”์— ๋…ธ์ถœ๋œ๋‹ค.

## ๐Ÿš€ 3๋‹จ๊ณ„ - ํŽ˜์ด๋จผ์ธ (์นด๋“œ์‚ฌ)

### ๊ตฌํ˜„ ๊ธฐ๋Šฅ ๋ชฉ๋ก
- [x] ๋ฆฌ๋ทฐ ๋ฐ˜์˜
- [x] ์นด๋“œ ๋ฆฌ์ŠคํŠธ ํ”„๋ฆฌ๋ทฐ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์‹ค ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€
- [x] PaymentCardLayout ์ถ”๊ฐ€
- [x] TextField์˜ VisualTransformation ์‚ฌ์šฉํ•ด์„œ ์นด๋“œ๋ฒˆํ˜ธ, ๋งŒ๋ฃŒ๋‚ ์งœ ํฌ๋งท ๊ฐœ์„ 
- [x] cardNumber์˜ ๋’ท์ž๋ฆฌ 8์ž๋ฆฌ * ์ฒ˜๋ฆฌ
- [x] ์นด๋“œ ๋ชฉ๋ก ํ™”๋ฉด ๊ตฌํ˜„
- [x] ์นด๋“œ ์ถ”๊ฐ€ ํ™”๋ฉด์— ์ ‘์†ํ–ˆ์„ ๋•Œ ์นด๋“œ์‚ฌ๋ฅผ ํ•„์ˆ˜๋กœ ์„ ํƒํ•ด์•ผ ํ•œ๋‹ค.
- [x] ์„ ํƒํ•œ ์นด๋“œ์‚ฌ์— ๋”ฐ๋ผ ์นด๋“œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ€ ๋ฐ”๋€Œ์–ด์•ผ ํ•œ๋‹ค.
- [x] (์„ ํƒ์‚ฌํ•ญ) ์นด๋“œ์‚ฌ๋ฅผ ์„ ํƒํ•  ๋•Œ ์ ์ ˆํ•œ ์นด๋“œ์‚ฌ ์•„์ด์ฝ˜์„ ๋…ธ์ถœํ•œ๋‹ค.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ dependencies {
implementation(libs.androidx.material3)
implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.material)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/java/nextstep/payments/data/model/CreditCard.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package nextstep.payments.data.model

import nextstep.payments.ui.model.BankType

data class CreditCard (
val cardNumber: String = "",
val ownerName: String? = "",
val expiredDate: String = ""
val expiredDate: String = "",
var bank: BankType = BankType.NOT_SELECTED
)


88 changes: 47 additions & 41 deletions app/src/main/java/nextstep/payments/ui/component/PaymentCard.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,29 @@ import androidx.compose.foundation.layout.size
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.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import nextstep.payments.data.model.CreditCard
import nextstep.payments.ui.theme.Black
import nextstep.payments.ui.ext.toFormattedCardNumber
import nextstep.payments.ui.ext.toFormattedDate
import nextstep.payments.ui.model.BankType
import nextstep.payments.ui.theme.Yellow

@Composable
fun PaymentCard(
modifier: Modifier = Modifier,
card: CreditCard = CreditCard(),
) {
Box(
contentAlignment = Alignment.CenterStart,
modifier = modifier
.shadow(8.dp)
.size(width = 208.dp, height = 124.dp)
.background(
color = Black,
shape = RoundedCornerShape(5.dp),
)
PaymentCardLayout(
modifier = modifier,
backgroundColor = card.bank.getCardColorRes()
) {
Box(
modifier = Modifier
Expand All @@ -50,35 +45,40 @@ fun PaymentCard(
shape = RoundedCornerShape(4.dp),
)
)
if(card.cardNumber.isNotEmpty()) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(start = 14.dp, end = 14.dp, bottom = 16.dp),
verticalArrangement = Arrangement.Bottom,
) {
val cardTextStyle = TextStyle(
fontSize = 12.sp,
lineHeight = 14.06.sp,
color = Color.White,
letterSpacing = 1.sp
)
Text(
text = card.cardNumber,
style = cardTextStyle
)
Row(
modifier = Modifier.fillMaxWidth().padding(top = 2.dp),
horizontalArrangement = Arrangement.Absolute.SpaceBetween
) {
Text(
text = card.ownerName ?: "CREW",
style = cardTextStyle
)

Column(
modifier = Modifier
.fillMaxSize()
.padding(start = 14.dp, end = 14.dp, top = 15.dp, bottom = 16.dp),
verticalArrangement = Arrangement.SpaceBetween,
) {
val cardTextStyle = TextStyle(
fontSize = 12.sp,
lineHeight = 14.06.sp,
color = Color.White,
letterSpacing = 1.sp
)

Text(
text = card.bank.getNameRes()?.let { stringResource(id = it) } ?: "",
style = cardTextStyle
)

if (card.cardNumber.isNotEmpty()) {
Column {
Text(
text = card.expiredDate,
text = card.cardNumber.toFormattedCardNumber(),
style = cardTextStyle
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(top = 2.dp),
horizontalArrangement = Arrangement.Absolute.SpaceBetween
) {
Text(text = card.ownerName ?: "CREW", style = cardTextStyle)
Text(text = card.expiredDate.toFormattedDate(), style = cardTextStyle)
}
}
}
}
Expand All @@ -89,15 +89,21 @@ private class PaymentCardPreviewParameters : PreviewParameterProvider<CreditCard
override val values: Sequence<CreditCard> = sequenceOf(
CreditCard(),
CreditCard(
cardNumber = "1234-5678-9011",
cardNumber = "123456789011",
ownerName = "kim",
expiredDate = "11/30"
expiredDate = "1130",
bank = BankType.NOT_SELECTED
),
CreditCard(
cardNumber = "123456789011",
ownerName = "kim",
expiredDate = "1130",
bank = BankType.LOTTE
)
)
}



@Preview
@Composable
fun PaymentCardPreview(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package nextstep.payments.ui.component

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

@Composable
fun PaymentCardLayout(
backgroundColor : Color,
modifier: Modifier = Modifier,
onClick : (() -> Unit)? = null,
content: @Composable BoxScope.() -> Unit
) {
Box(
contentAlignment = Alignment.CenterStart,
modifier = modifier
.shadow(8.dp)
.size(width = 208.dp, height = 124.dp)
.background(
color = backgroundColor,
shape = RoundedCornerShape(5.dp),
)
.then(
if(onClick == null) Modifier else Modifier.clickable { onClick() }
)
) {
content()
}
}
12 changes: 12 additions & 0 deletions app/src/main/java/nextstep/payments/ui/ext/StringExt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package nextstep.payments.ui.ext

fun String.toFormattedCardNumber(): String {
return this.chunked(4).joinToString("-")
}

fun String.toFormattedDate(): String {
if (this.length != 4) return this
val month = this.substring(0, 2)
val year = this.substring(2, 4)
return "$month / $year"
}
46 changes: 31 additions & 15 deletions app/src/main/java/nextstep/payments/ui/list/CardListScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import nextstep.payments.R
import nextstep.payments.data.model.CreditCard
import nextstep.payments.ui.component.PaymentCard
import nextstep.payments.ui.component.PaymentCardLayout
import nextstep.payments.ui.model.BankType
import nextstep.payments.ui.theme.DarkGrey
import nextstep.payments.ui.theme.Grey

Expand Down Expand Up @@ -163,15 +165,10 @@ fun AddCard(
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
Box(
modifier = modifier
.size(
width = 208.dp,
height = 124.dp,
)
.clip(shape = RoundedCornerShape(5.dp))
.background(color = Grey)
.clickable(onClick = onClick)
PaymentCardLayout(
backgroundColor = Grey,
modifier = modifier,
onClick = onClick
) {
Icon(
modifier = Modifier
Expand All @@ -184,18 +181,37 @@ fun AddCard(
}
}

private val dummyCard = CreditCard(

)

private class CardListScreenPreviewParameters : PreviewParameterProvider<CreditCardUiState> {
override val values: Sequence<CreditCardUiState> = sequenceOf(
CreditCardUiState.Empty,
CreditCardUiState.One(
card = dummyCard
card = CreditCard(
cardNumber = "0000-1111-2222-3333",
ownerName = "Kim",
expiredDate = "4/25",
bank = BankType.SHINHAN
)
),
CreditCardUiState.Many(
cards = listOf(dummyCard, dummyCard, dummyCard)
cards = listOf(
CreditCard(
cardNumber = "0000-1111-2222-3333",
ownerName = "Kim",
expiredDate = "04/25",
bank = BankType.SHINHAN
),
CreditCard(
cardNumber = "0000-1111-2222-3333",
ownerName = "Park",
expiredDate = "04/25",
bank = BankType.KB
),
CreditCard(
cardNumber = "0000-1111-2222-3333",
ownerName = "Song",
expiredDate = "04/25",
bank = BankType.LOTTE
))
)
)
}
Expand Down
59 changes: 59 additions & 0 deletions app/src/main/java/nextstep/payments/ui/model/BankType.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package nextstep.payments.ui.model

import androidx.compose.ui.graphics.Color
import nextstep.payments.R
import nextstep.payments.ui.theme.BCBrandColor
import nextstep.payments.ui.theme.Black
import nextstep.payments.ui.theme.HANABrandColor
import nextstep.payments.ui.theme.HYUNDAIBrandColor
import nextstep.payments.ui.theme.KAKAOBANKBrandColor
import nextstep.payments.ui.theme.KBBrandColor
import nextstep.payments.ui.theme.LOTTEBrandColor
import nextstep.payments.ui.theme.SHINHANBrandColor
import nextstep.payments.ui.theme.WOORIBrandColor

enum class BankType {
NOT_SELECTED, BC, SHINHAN, KAKAOBANK, HYUNDAI, WOORI, LOTTE, HANA, KB;

fun getIconRes(): Int? {
return when (this) {
BC -> R.drawable.ic_bc
SHINHAN -> R.drawable.ic_shinhan
KAKAOBANK -> R.drawable.ic_kakaobank
HYUNDAI -> R.drawable.ic_hyundai
WOORI -> R.drawable.ic_woori
LOTTE -> R.drawable.ic_lotte
HANA -> R.drawable.ic_hana
KB -> R.drawable.ic_kb
else -> null
}
}

fun getNameRes(): Int? {
return when (this) {
BC -> R.string.bc_card
SHINHAN -> R.string.shinhan_card
KAKAOBANK -> R.string.kakao_bank
HYUNDAI -> R.string.hyundai_card
WOORI -> R.string.woori_card
LOTTE -> R.string.lotte_card
HANA -> R.string.hana_card
KB -> R.string.kb_card
else -> null
}
}

fun getCardColorRes(): Color {
return when(this) {
BC -> BCBrandColor
SHINHAN -> SHINHANBrandColor
KAKAOBANK -> KAKAOBANKBrandColor
HYUNDAI -> HYUNDAIBrandColor
WOORI -> WOORIBrandColor
LOTTE -> LOTTEBrandColor
HANA -> HANABrandColor
KB -> KBBrandColor
else -> Black
}
}
}
Loading