Skip to content

Commit 393a0ea

Browse files
authored
Merge pull request #442 from BCSDLab/feature/timetable_duplication_dialog
[Feature] 시간표 중복 다이얼로그
2 parents 978ee56 + ab15a8d commit 393a0ea

File tree

5 files changed

+294
-7
lines changed

5 files changed

+294
-7
lines changed

core/designsystem/src/main/java/in/koreatech/koin/core/designsystem/theme/Type.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,36 +126,36 @@ internal val MediumStyle6 = DefaultTextStyle.copy(
126126

127127
internal val BoldStyle1 = DefaultTextStyle.copy(
128128
fontSize = 12.sp,
129-
fontWeight = FontWeight.Medium,
129+
fontWeight = FontWeight.Bold,
130130
lineHeight = 19.2.sp
131131
)
132132
internal val BoldStyle2 = DefaultTextStyle.copy(
133133
fontSize = 13.sp,
134-
fontWeight = FontWeight.Medium,
134+
fontWeight = FontWeight.Bold,
135135
lineHeight = 20.8.sp
136136
)
137137
internal val BoldStyle3 = DefaultTextStyle.copy(
138138
fontSize = 14.sp,
139-
fontWeight = FontWeight.Medium,
139+
fontWeight = FontWeight.Bold,
140140
lineHeight = 22.4.sp
141141
)
142142
internal val BoldStyle4 = DefaultTextStyle.copy(
143143
fontSize = 15.sp,
144-
fontWeight = FontWeight.Medium,
144+
fontWeight = FontWeight.Bold,
145145
lineHeight = 24.sp
146146
)
147147
internal val BoldStyle5 = DefaultTextStyle.copy(
148148
fontSize = 16.sp,
149-
fontWeight = FontWeight.Medium,
149+
fontWeight = FontWeight.Bold,
150150
lineHeight = 25.6.sp
151151
)
152152
internal val BoldStyle6 = DefaultTextStyle.copy(
153153
fontSize = 18.sp,
154-
fontWeight = FontWeight.Medium,
154+
fontWeight = FontWeight.Bold,
155155
lineHeight = 28.8.sp
156156
)
157157
internal val BoldStyle7 = DefaultTextStyle.copy(
158158
fontSize = 20.sp,
159-
fontWeight = FontWeight.Medium,
159+
fontWeight = FontWeight.Bold,
160160
lineHeight = 30.sp
161161
)
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package `in`.koreatech.koin.feature.timetable.component
2+
3+
import androidx.compose.foundation.interaction.MutableInteractionSource
4+
import androidx.compose.foundation.layout.PaddingValues
5+
import androidx.compose.foundation.layout.height
6+
import androidx.compose.foundation.layout.padding
7+
import androidx.compose.foundation.layout.width
8+
import androidx.compose.material3.Button
9+
import androidx.compose.material3.ButtonColors
10+
import androidx.compose.material3.Surface
11+
import androidx.compose.material3.Text
12+
import androidx.compose.runtime.Composable
13+
import androidx.compose.runtime.remember
14+
import androidx.compose.ui.Modifier
15+
import androidx.compose.ui.graphics.Color
16+
import androidx.compose.ui.graphics.Shape
17+
import androidx.compose.ui.text.TextStyle
18+
import androidx.compose.ui.unit.dp
19+
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme
20+
import `in`.koreatech.koin.core.designsystem.theme.ThemePreviews
21+
22+
@Composable
23+
fun FilledTextButton(
24+
text: String,
25+
onClick: () -> Unit,
26+
modifier: Modifier = Modifier,
27+
enabled: Boolean = true,
28+
textStyle: TextStyle = FilledTextButtonDefaults.textStyle,
29+
textColor: Color = FilledTextButtonDefaults.textColor,
30+
colors: ButtonColors = FilledTextButtonDefaults.colors,
31+
shape: Shape = FilledTextButtonDefaults.shape,
32+
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
33+
) {
34+
Button(
35+
onClick = onClick,
36+
modifier = modifier,
37+
enabled = enabled,
38+
shape = shape,
39+
colors = colors,
40+
elevation = null,
41+
border = null,
42+
contentPadding = FilledTextButtonDefaults.contentPadding,
43+
interactionSource = interactionSource
44+
) {
45+
Text(text = text, style = textStyle, color = textColor)
46+
}
47+
}
48+
49+
object FilledTextButtonDefaults {
50+
val contentPadding = PaddingValues(0.dp)
51+
52+
val colors
53+
@Composable get() = ButtonColors(
54+
containerColor = KoinTheme.colors.primary500,
55+
contentColor = KoinTheme.colors.neutral0,
56+
disabledContainerColor = KoinTheme.colors.neutral300,
57+
disabledContentColor = KoinTheme.colors.neutral600
58+
)
59+
val shape @Composable get() = KoinTheme.shapes.extraSmall
60+
val textColor @Composable get() = KoinTheme.colors.neutral0
61+
val textStyle @Composable get() = KoinTheme.typography.medium15
62+
63+
}
64+
65+
@ThemePreviews
66+
@Composable
67+
private fun FilledTextButtonPreview() {
68+
KoinTheme {
69+
Surface(modifier = Modifier.padding(24.dp)) {
70+
FilledTextButton(
71+
modifier = Modifier
72+
.width(96.dp)
73+
.height(48.dp),
74+
text = "Preview",
75+
onClick = {}
76+
)
77+
78+
}
79+
}
80+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package `in`.koreatech.koin.feature.timetable.component
2+
3+
import androidx.compose.material3.Text
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.ui.Modifier
6+
import androidx.compose.ui.text.ParagraphStyle
7+
import androidx.compose.ui.text.TextStyle
8+
import androidx.compose.ui.text.buildAnnotatedString
9+
import androidx.compose.ui.text.style.LineBreak
10+
import androidx.compose.ui.text.style.TextAlign
11+
import androidx.compose.ui.text.withStyle
12+
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme
13+
import `in`.koreatech.koin.core.designsystem.theme.ThemePreviews
14+
15+
@Composable
16+
fun HighlightedText(
17+
texts: Array<String>,
18+
highlightIndices: List<Int>,
19+
defaultStyle: TextStyle,
20+
highlightStyle: TextStyle,
21+
modifier: Modifier = Modifier
22+
) {
23+
val annotatedString = buildAnnotatedString {
24+
pushStyle(
25+
ParagraphStyle(
26+
lineBreak = LineBreak(
27+
strategy = LineBreak.Strategy.Balanced,
28+
wordBreak = LineBreak.WordBreak.Phrase,
29+
strictness = LineBreak.Strictness.Normal
30+
)
31+
)
32+
)
33+
texts.forEachIndexed { idx, text ->
34+
withStyle(
35+
style = highlightIndices.find { it == idx }
36+
?.let { highlightStyle.toSpanStyle() }
37+
?: defaultStyle.toSpanStyle()
38+
) {
39+
append(text)
40+
}
41+
}
42+
}
43+
44+
Text(
45+
text = annotatedString,
46+
style = defaultStyle,
47+
textAlign = TextAlign.Center,
48+
modifier = modifier
49+
)
50+
}
51+
52+
@ThemePreviews
53+
@Composable
54+
private fun HighlightedTextPreview() {
55+
KoinTheme {
56+
HighlightedText(
57+
texts = arrayOf("안녕하세요 ", "강조", "입니다"),
58+
highlightIndices = listOf(1),
59+
defaultStyle = KoinTheme.typography.regular15,
60+
highlightStyle = KoinTheme.typography.bold15,
61+
)
62+
}
63+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package `in`.koreatech.koin.feature.timetable.view
2+
3+
import androidx.compose.foundation.BorderStroke
4+
import androidx.compose.foundation.layout.Arrangement
5+
import androidx.compose.foundation.layout.Column
6+
import androidx.compose.foundation.layout.PaddingValues
7+
import androidx.compose.foundation.layout.Row
8+
import androidx.compose.foundation.layout.Spacer
9+
import androidx.compose.foundation.layout.fillMaxWidth
10+
import androidx.compose.foundation.layout.height
11+
import androidx.compose.foundation.layout.padding
12+
import androidx.compose.foundation.layout.wrapContentHeight
13+
import androidx.compose.foundation.layout.wrapContentWidth
14+
import androidx.compose.material3.BasicAlertDialog
15+
import androidx.compose.material3.ButtonColors
16+
import androidx.compose.material3.ExperimentalMaterial3Api
17+
import androidx.compose.material3.MaterialTheme
18+
import androidx.compose.material3.OutlinedButton
19+
import androidx.compose.material3.Surface
20+
import androidx.compose.material3.Text
21+
import androidx.compose.runtime.Composable
22+
import androidx.compose.runtime.getValue
23+
import androidx.compose.runtime.mutableStateOf
24+
import androidx.compose.runtime.remember
25+
import androidx.compose.runtime.setValue
26+
import androidx.compose.ui.Alignment
27+
import androidx.compose.ui.Modifier
28+
import androidx.compose.ui.res.stringArrayResource
29+
import androidx.compose.ui.res.stringResource
30+
import androidx.compose.ui.text.style.TextAlign
31+
import androidx.compose.ui.unit.dp
32+
import `in`.koreatech.koin.core.designsystem.theme.FontScalePreviews
33+
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme
34+
import `in`.koreatech.koin.feature.timetable.R
35+
import `in`.koreatech.koin.feature.timetable.component.FilledTextButton
36+
import `in`.koreatech.koin.feature.timetable.component.HighlightedText
37+
38+
@OptIn(ExperimentalMaterial3Api::class)
39+
@Composable
40+
fun LectureDuplicationDialog(
41+
onConfirm: () -> Unit,
42+
onDismiss: () -> Unit,
43+
modifier: Modifier = Modifier
44+
) {
45+
BasicAlertDialog(
46+
onDismissRequest = { onDismiss() },
47+
modifier = modifier,
48+
) {
49+
Surface(
50+
modifier = Modifier
51+
.wrapContentWidth()
52+
.wrapContentHeight(),
53+
shape = KoinTheme.shapes.extraSmall
54+
) {
55+
Column(
56+
modifier = Modifier
57+
.fillMaxWidth()
58+
.padding(
59+
horizontal = 32.dp,
60+
vertical = 24.dp
61+
),
62+
horizontalAlignment = Alignment.CenterHorizontally
63+
) {
64+
Text(
65+
text = stringResource(id = R.string.lecture_duplication_title),
66+
color = KoinTheme.colors.neutral800,
67+
textAlign = TextAlign.Center,
68+
style = KoinTheme.typography.bold16,
69+
)
70+
Spacer(modifier = Modifier.height(8.dp))
71+
HighlightedText(
72+
texts = stringArrayResource(id = R.array.lecture_duplication_description),
73+
highlightIndices = listOf(1),
74+
defaultStyle = KoinTheme.typography.regular14.copy(
75+
color = KoinTheme.colors.neutral600,
76+
),
77+
highlightStyle = KoinTheme.typography.regular14.copy(
78+
color = KoinTheme.colors.warning600,
79+
)
80+
)
81+
Spacer(modifier = Modifier.height(24.dp))
82+
Row(
83+
modifier = Modifier.wrapContentHeight(),
84+
horizontalArrangement = Arrangement.spacedBy(8.dp)
85+
) {
86+
OutlinedButton(
87+
modifier = Modifier
88+
.height(48.dp)
89+
.weight(1.0F),
90+
colors = ButtonColors(
91+
containerColor = KoinTheme.colors.neutral0,
92+
contentColor = KoinTheme.colors.neutral500,
93+
disabledContainerColor = KoinTheme.colors.neutral400,
94+
disabledContentColor = KoinTheme.colors.neutral500
95+
),
96+
shape = MaterialTheme.shapes.extraSmall,
97+
contentPadding = PaddingValues(0.dp),
98+
border = BorderStroke(1.dp, KoinTheme.colors.neutral500),
99+
onClick = { onDismiss() }
100+
) {
101+
Text(text = stringResource(id = R.string.lecture_duplication_cancellation), style = KoinTheme.typography.medium15, color = KoinTheme.colors.neutral600)
102+
}
103+
FilledTextButton(
104+
modifier = Modifier
105+
.height(48.dp)
106+
.weight(1.0F),
107+
text = stringResource(id = R.string.lecture_duplication_confirmation),
108+
onClick = { onConfirm() }
109+
)
110+
}
111+
}
112+
}
113+
}
114+
115+
}
116+
117+
@FontScalePreviews
118+
@Composable
119+
private fun LectureDuplicationDialogPreview(modifier: Modifier = Modifier) {
120+
KoinTheme {
121+
var isShowing by remember { mutableStateOf(true) }
122+
123+
if (isShowing) {
124+
LectureDuplicationDialog(
125+
onConfirm = {},
126+
onDismiss = { isShowing = false }
127+
)
128+
}
129+
}
130+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<string name="lecture_duplication_title">시간표가 중복돼요.</string>
4+
<string name="lecture_duplication_cancellation">취소</string>
5+
<string name="lecture_duplication_confirmation">대체하기</string>
6+
7+
<string-array name="lecture_duplication_description">
8+
<item>추가하시려는 시간에 이미 다른 강의가 있어요.</item>
9+
<item>" 새로운 강의로 대체"</item>
10+
<item>하시겠어요?</item>
11+
</string-array>
12+
13+
14+
</resources>

0 commit comments

Comments
 (0)