diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_check.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_check.xml new file mode 100644 index 0000000..d2c5b53 --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_check.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_comment.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_comment.xml new file mode 100644 index 0000000..0f22a64 --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_comment.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_dislike.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_dislike.xml new file mode 100644 index 0000000..3d2936b --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_dislike.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_empty_star.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_empty_star.xml new file mode 100644 index 0000000..7d7bf35 --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_empty_star.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_filled_star.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_filled_star.xml new file mode 100644 index 0000000..57064b3 --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_filled_star.xml @@ -0,0 +1,11 @@ + + + diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_half_star.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_half_star.xml new file mode 100644 index 0000000..ed4163e --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_half_star.xml @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_kus_blank.png b/core/designSystem/src/commonMain/composeResources/drawable/ic_kus_blank.png new file mode 100644 index 0000000..1c8e7b4 Binary files /dev/null and b/core/designSystem/src/commonMain/composeResources/drawable/ic_kus_blank.png differ diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_kus_logo.png b/core/designSystem/src/commonMain/composeResources/drawable/ic_kus_logo.png new file mode 100644 index 0000000..66557fe Binary files /dev/null and b/core/designSystem/src/commonMain/composeResources/drawable/ic_kus_logo.png differ diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_launcher_background.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_launcher_foreground.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_like.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_like.xml new file mode 100644 index 0000000..600fb48 --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_like.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_location.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_location.xml new file mode 100644 index 0000000..979b315 --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_location.xml @@ -0,0 +1,13 @@ + + + diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_pencil.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_pencil.xml new file mode 100644 index 0000000..f02a736 --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_pencil.xml @@ -0,0 +1,13 @@ + + + diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_saved.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_saved.xml new file mode 100644 index 0000000..cecd7d2 --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_saved.xml @@ -0,0 +1,13 @@ + + + diff --git a/core/designSystem/src/commonMain/composeResources/drawable/ic_unsaved.xml b/core/designSystem/src/commonMain/composeResources/drawable/ic_unsaved.xml new file mode 100644 index 0000000..fa77084 --- /dev/null +++ b/core/designSystem/src/commonMain/composeResources/drawable/ic_unsaved.xml @@ -0,0 +1,13 @@ + + + diff --git a/core/designSystem/src/commonMain/composeResources/font/pretendard_black.ttf b/core/designSystem/src/commonMain/composeResources/font/pretendard_black.ttf new file mode 100644 index 0000000..d0c1db8 Binary files /dev/null and b/core/designSystem/src/commonMain/composeResources/font/pretendard_black.ttf differ diff --git a/core/designSystem/src/commonMain/composeResources/font/pretendard_bold.ttf b/core/designSystem/src/commonMain/composeResources/font/pretendard_bold.ttf new file mode 100644 index 0000000..fb07fc6 Binary files /dev/null and b/core/designSystem/src/commonMain/composeResources/font/pretendard_bold.ttf differ diff --git a/core/designSystem/src/commonMain/composeResources/font/pretendard_extrabold.ttf b/core/designSystem/src/commonMain/composeResources/font/pretendard_extrabold.ttf new file mode 100644 index 0000000..9d5fe07 Binary files /dev/null and b/core/designSystem/src/commonMain/composeResources/font/pretendard_extrabold.ttf differ diff --git a/core/designSystem/src/commonMain/composeResources/font/pretendard_extralight.ttf b/core/designSystem/src/commonMain/composeResources/font/pretendard_extralight.ttf new file mode 100644 index 0000000..09e6542 Binary files /dev/null and b/core/designSystem/src/commonMain/composeResources/font/pretendard_extralight.ttf differ diff --git a/core/designSystem/src/commonMain/composeResources/font/pretendard_light.ttf b/core/designSystem/src/commonMain/composeResources/font/pretendard_light.ttf new file mode 100644 index 0000000..2e8541d Binary files /dev/null and b/core/designSystem/src/commonMain/composeResources/font/pretendard_light.ttf differ diff --git a/core/designSystem/src/commonMain/composeResources/font/pretendard_medium.ttf b/core/designSystem/src/commonMain/composeResources/font/pretendard_medium.ttf new file mode 100644 index 0000000..1db67c6 Binary files /dev/null and b/core/designSystem/src/commonMain/composeResources/font/pretendard_medium.ttf differ diff --git a/core/designSystem/src/commonMain/composeResources/font/pretendard_regular.ttf b/core/designSystem/src/commonMain/composeResources/font/pretendard_regular.ttf new file mode 100644 index 0000000..01147e9 Binary files /dev/null and b/core/designSystem/src/commonMain/composeResources/font/pretendard_regular.ttf differ diff --git a/core/designSystem/src/commonMain/composeResources/font/pretendard_semibold.ttf b/core/designSystem/src/commonMain/composeResources/font/pretendard_semibold.ttf new file mode 100644 index 0000000..9f2690f Binary files /dev/null and b/core/designSystem/src/commonMain/composeResources/font/pretendard_semibold.ttf differ diff --git a/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Color.kt b/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Color.kt new file mode 100644 index 0000000..b483c21 --- /dev/null +++ b/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Color.kt @@ -0,0 +1,143 @@ +package com.kus.designsystem.theme + +import androidx.compose.runtime.Stable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.compose.ui.graphics.Color + +val C_43AB38 = Color(0xFF43AB38) +val C_046B40 = Color(0xFF046B40) +val C_FFFFFF = Color(0xFFFFFFFF) +val C_F5F5F5 = Color(0xFFF5F5F5) +val C_EAEAEA = Color(0xFFEAEAEA) +val C_E0E0E0 = Color(0xFFE0E0E0) +val C_AAAAAA = Color(0xFFAAAAAA) +val C_666666 = Color(0xFF666666) +val C_323232 = Color(0xFF323232) +val C_353535 = Color(0xFF353535) +val C_000000 = Color(0xFF000000) +val C_0093FF = Color(0xFF0093FF) +val C_01BAA6 = Color(0xFF01BAA6) +val C_FFB900 = Color(0xFFFFB900) +val C_9BA5B0 = Color(0xFF9BA5B0) + +@Stable +class KusColors( + c_43AB38: Color, + c_046B40: Color, + c_FFFFFF: Color, + c_F5F5F5: Color, + c_EAEAEA: Color, + c_E0E0E0: Color, + c_AAAAAA: Color, + c_666666: Color, + c_323232: Color, + c_353535: Color, + c_000000: Color, + c_0093FF: Color, + c_01BAA6: Color, + c_FFB900: Color, + c_9BA5B0: Color, +) { + var c_43AB38 by mutableStateOf(c_43AB38) + private set + var c_046B40 by mutableStateOf(c_046B40) + private set + var c_FFFFFF by mutableStateOf(c_FFFFFF) + private set + var c_F5F5F5 by mutableStateOf(c_F5F5F5) + private set + var c_EAEAEA by mutableStateOf(c_EAEAEA) + private set + var c_E0E0E0 by mutableStateOf(c_E0E0E0) + private set + var c_AAAAAA by mutableStateOf(c_AAAAAA) + private set + var c_666666 by mutableStateOf(c_666666) + private set + var c_323232 by mutableStateOf(c_323232) + private set + var c_353535 by mutableStateOf(c_353535) + private set + var c_000000 by mutableStateOf(c_000000) + private set + var c_0093FF by mutableStateOf(c_0093FF) + private set + var c_01BAA6 by mutableStateOf(c_01BAA6) + private set + var c_FFB900 by mutableStateOf(c_FFB900) + private set + var c_9BA5B0 by mutableStateOf(c_9BA5B0) + private set + + fun copy(): KusColors = KusColors( + c_43AB38, + c_046B40, + c_FFFFFF, + c_F5F5F5, + c_EAEAEA, + c_E0E0E0, + c_AAAAAA, + c_666666, + c_323232, + c_353535, + c_000000, + c_0093FF, + c_01BAA6, + c_FFB900, + c_9BA5B0, + ) + + fun update(other: KusColors) { + c_43AB38 = other.c_43AB38 + c_046B40 = other.c_046B40 + c_FFFFFF = other.c_FFFFFF + c_F5F5F5 = other.c_F5F5F5 + c_EAEAEA = other.c_EAEAEA + c_E0E0E0 = other.c_E0E0E0 + c_AAAAAA = other.c_AAAAAA + c_666666 = other.c_666666 + c_323232 = other.c_323232 + c_353535 = other.c_353535 + c_000000 = other.c_000000 + c_0093FF = other.c_0093FF + c_01BAA6 = other.c_01BAA6 + c_FFB900 = other.c_FFB900 + c_9BA5B0 = other.c_9BA5B0 + } +} + +fun KusLightColors( + c_43AB38: Color = C_43AB38, + c_046B40: Color = C_046B40, + c_FFFFFF: Color = C_FFFFFF, + c_F5F5F5: Color = C_F5F5F5, + c_EAEAEA: Color = C_EAEAEA, + c_E0E0E0: Color = C_E0E0E0, + c_AAAAAA: Color = C_AAAAAA, + c_666666: Color = C_666666, + c_323232: Color = C_323232, + c_353535: Color = C_353535, + c_000000: Color = C_000000, + c_0093FF: Color = C_0093FF, + c_01BAA6: Color = C_01BAA6, + c_FFB900: Color = C_FFB900, + c_9BA5B0: Color = C_9BA5B0, +) = KusColors( + c_43AB38, + c_046B40, + c_FFFFFF, + c_F5F5F5, + c_EAEAEA, + c_E0E0E0, + c_AAAAAA, + c_666666, + c_323232, + c_353535, + c_000000, + c_0093FF, + c_01BAA6, + c_FFB900, + c_9BA5B0, +) diff --git a/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Theme.kt b/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Theme.kt new file mode 100644 index 0000000..3726c69 --- /dev/null +++ b/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Theme.kt @@ -0,0 +1,58 @@ +package com.kus.designsystem.theme + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.remember +import androidx.compose.runtime.staticCompositionLocalOf + +private val LocalKusColors = staticCompositionLocalOf { + error("No KusColors provided") +} + +private val LocalKusTypography = staticCompositionLocalOf { + error("No KusTypography provided") +} + +object KusTheme { + val colors: KusColors + @Composable + @ReadOnlyComposable + get() = LocalKusColors.current + val typography: KusTypography + @Composable + @ReadOnlyComposable + get() = LocalKusTypography.current +} + +@Composable +fun ProvideKusColorsAndTypography( + colors: KusColors, + typography: KusTypography, + content: @Composable () -> Unit +) { + val provideColors = remember { colors.copy() }.apply { update(colors) } + CompositionLocalProvider( + LocalKusColors provides provideColors, + LocalKusTypography provides typography, + content = content + ) +} + +@Composable +fun KusTheme( + content: @Composable () -> Unit +) { + val colors = KusLightColors() + val typography = createKusTypography() + + ProvideKusColorsAndTypography( + colors = colors, + typography = typography + ) { + MaterialTheme( + content = content + ) + } +} diff --git a/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Type.kt b/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Type.kt new file mode 100644 index 0000000..a53c626 --- /dev/null +++ b/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Type.kt @@ -0,0 +1,146 @@ +package com.kus.designsystem.theme + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.LineHeightStyle +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.em +import androidx.compose.ui.unit.sp +import kustaurant.core.designsystem.generated.resources.Res +import kustaurant.core.designsystem.generated.resources.pretendard_bold +import kustaurant.core.designsystem.generated.resources.pretendard_medium +import kustaurant.core.designsystem.generated.resources.pretendard_regular +import kustaurant.core.designsystem.generated.resources.pretendard_semibold +import org.jetbrains.compose.resources.Font + +private val PretendardRegular: FontFamily + @Composable + get() = + FontFamily(Font(Res.font.pretendard_regular, FontWeight.Normal)) + +private val PretendardMedium: FontFamily + @Composable + get() = + FontFamily(Font(Res.font.pretendard_medium, FontWeight.Medium)) + +private val PretendardSemiBold: FontFamily + @Composable + get() = + FontFamily(Font(Res.font.pretendard_semibold, FontWeight.SemiBold)) + +private val PretendardBold: FontFamily + @Composable + get() = + FontFamily(Font(Res.font.pretendard_bold, FontWeight.Bold)) + +private fun KusTextStyle( + fontFamily: FontFamily, + fontSize: TextUnit, + lineHeight: TextUnit = 1.28.em, + letterSpacing: TextUnit = 0.02.em, +): TextStyle = TextStyle( + fontFamily = fontFamily, + fontSize = fontSize, + lineHeight = lineHeight, + letterSpacing = letterSpacing, + lineHeightStyle = LineHeightStyle( + alignment = LineHeightStyle.Alignment.Center, + trim = LineHeightStyle.Trim.None + ), +) + +@Immutable +class KusTypography( + val type20b: TextStyle, + val type16b: TextStyle, + val type13b: TextStyle, + val type18sb: TextStyle, + val type17sb: TextStyle, + val type16sb: TextStyle, + val type15sb: TextStyle, + val type18m: TextStyle, + val type16m: TextStyle, + val type15m: TextStyle, + val type12m: TextStyle, + val type11m: TextStyle, + val type14r: TextStyle, + val type13r: TextStyle, + val type12r: TextStyle, + val type11r: TextStyle, + val type10r: TextStyle, +) + +@Composable +fun createKusTypography() = KusTypography( + type20b = KusTextStyle( + fontFamily = PretendardBold, + fontSize = 20.sp, + ), + type16b = KusTextStyle( + fontFamily = PretendardBold, + fontSize = 16.sp, + ), + type13b = KusTextStyle( + fontFamily = PretendardBold, + fontSize = 13.sp, + ), + type18sb = KusTextStyle( + fontFamily = PretendardSemiBold, + fontSize = 18.sp, + ), + type17sb = KusTextStyle( + fontFamily = PretendardSemiBold, + fontSize = 17.sp, + ), + type16sb = KusTextStyle( + fontFamily = PretendardSemiBold, + fontSize = 16.sp, + ), + type15sb = KusTextStyle( + fontFamily = PretendardSemiBold, + fontSize = 15.sp, + ), + type18m = KusTextStyle( + fontFamily = PretendardMedium, + fontSize = 18.sp, + ), + type16m = KusTextStyle( + fontFamily = PretendardMedium, + fontSize = 16.sp, + ), + type15m = KusTextStyle( + fontFamily = PretendardMedium, + fontSize = 15.sp, + ), + type12m = KusTextStyle( + fontFamily = PretendardMedium, + fontSize = 12.sp, + ), + type11m = KusTextStyle( + fontFamily = PretendardMedium, + fontSize = 11.sp, + ), + type14r = KusTextStyle( + fontFamily = PretendardRegular, + fontSize = 14.sp, + ), + type13r = KusTextStyle( + fontFamily = PretendardRegular, + fontSize = 13.sp, + ), + type12r = KusTextStyle( + fontFamily = PretendardRegular, + fontSize = 12.sp, + ), + type11r = KusTextStyle( + fontFamily = PretendardRegular, + fontSize = 11.sp, + ), + type10r = KusTextStyle( + fontFamily = PretendardRegular, + fontSize = 10.sp, + ), +) \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 6f8e6ea..76a3ace 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,10 +3,14 @@ kotlin.code.style=official kotlin.daemon.jvmargs=-Xmx3072M #Gradle -org.gradle.jvmargs=-Xmx4096M -Dfile.encoding=UTF-8 -org.gradle.configuration-cache=true +org.gradle.jvmargs=-Xmx4096M -Dfile.encoding=UTF-8 -XX:+UseG1GC -XX:MaxMetaspaceSize=512m +org.gradle.configuration-cache=false org.gradle.caching=true #Android android.nonTransitiveRClass=true -android.useAndroidX=true \ No newline at end of file +android.useAndroidX=true + +org.gradle.parallel=true +org.gradle.daemon=true +org.gradle.configureondemand=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ee27a37..4904cd6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -33,6 +33,7 @@ material = "1.12.0" uiautomator = "2.3.0" benchmarkMacroJunit4 = "1.4.1" napier = "2.7.1" +kamel = "0.9.4" [libraries] kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } @@ -85,6 +86,8 @@ androidx-benchmark-macro-junit4 = { group = "androidx.benchmark", name = "benchm napier-log = { group = "io.github.aakira", name = "napier", version.ref = "napier" } +kamel-image = { module = "media.kamel:kamel-image", version.ref = "kamel" } + [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } androidLibrary = { id = "com.android.library", version.ref = "agp" } diff --git a/shared/core/designSystem/build.gradle.kts b/shared/core/designSystem/build.gradle.kts index 21fdde4..ce1bf0b 100644 --- a/shared/core/designSystem/build.gradle.kts +++ b/shared/core/designSystem/build.gradle.kts @@ -47,6 +47,7 @@ kotlin { implementation(compose.components.uiToolingPreview) implementation(libs.koin.core) implementation(libs.koin.compose) + implementation(libs.kamel.image) } } diff --git a/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_black.ttf b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_black.ttf new file mode 100644 index 0000000..d0c1db8 Binary files /dev/null and b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_black.ttf differ diff --git a/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_bold.ttf b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_bold.ttf new file mode 100644 index 0000000..fb07fc6 Binary files /dev/null and b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_bold.ttf differ diff --git a/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_extrabold.ttf b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_extrabold.ttf new file mode 100644 index 0000000..9d5fe07 Binary files /dev/null and b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_extrabold.ttf differ diff --git a/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_extralight.ttf b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_extralight.ttf new file mode 100644 index 0000000..09e6542 Binary files /dev/null and b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_extralight.ttf differ diff --git a/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_light.ttf b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_light.ttf new file mode 100644 index 0000000..2e8541d Binary files /dev/null and b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_light.ttf differ diff --git a/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_medium.ttf b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_medium.ttf new file mode 100644 index 0000000..1db67c6 Binary files /dev/null and b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_medium.ttf differ diff --git a/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_regular.ttf b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_regular.ttf new file mode 100644 index 0000000..01147e9 Binary files /dev/null and b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_regular.ttf differ diff --git a/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_semibold.ttf b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_semibold.ttf new file mode 100644 index 0000000..9f2690f Binary files /dev/null and b/shared/core/designSystem/src/commonMain/composeResources/font/pretendard_semibold.ttf differ diff --git a/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusButton.kt b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusButton.kt new file mode 100644 index 0000000..71dd5b3 --- /dev/null +++ b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusButton.kt @@ -0,0 +1,168 @@ +package com.kus.designsystem.component + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +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.size +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.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.draw.shadow +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.unit.dp +import com.kus.designsystem.theme.KusTheme +import kustaurant.shared.core.designsystem.generated.resources.Res +import org.jetbrains.compose.resources.vectorResource +import org.jetbrains.compose.ui.tooling.preview.Preview + +/** + * 쿠스토랑 버튼 + * + * @param enabled 버튼 활성화 여부 + * @param buttonName 버튼 내용 + * @param roundedCornerShape 버튼 테두리 모양 + * @param modifier 내용에 적용되는 수정자 + * @param textStyle 내용 텍스트 style(default: type18sb) + * @param contentColor 내용 색상(default: White) + * @param containerColor 버튼 배경 색상(default: c_43AB38) + * @param borderColor 버튼 테두리 색상(default: c_43AB38) + * @param contentPadding 내용과 버튼 사이 패딩(default: PaddingValues(vertical = 13.dp)) + * @param icon 버튼에 들어가는 좌측 아이콘(default: null) + * @param isShadowVisible 새도우 포함 여부(default: false) + * @param onClick 버튼 클릭 시 호출 되는 콜백 함수 + */ +@Composable +fun KusButton( + enabled: Boolean, + buttonName: String, + roundedCornerShape: RoundedCornerShape, + modifier: Modifier = Modifier, + textStyle: TextStyle = KusTheme.typography.type18sb, + contentColor: Color = Color.White, + containerColor: Color = KusTheme.colors.c_43AB38, + borderColor: Color = KusTheme.colors.c_43AB38, + contentPadding: PaddingValues = PaddingValues(vertical = 13.dp), + icon: ImageVector? = null, + isShadowVisible: Boolean = false, + onClick: () -> Unit, +) { + Box { + if (isShadowVisible) { + Box( + modifier = Modifier + .matchParentSize() + .shadow( + elevation = 4.dp, + shape = roundedCornerShape, + ambientColor = Color.Transparent, + ) + ) + } + + Button( + onClick = onClick, + enabled = enabled, + modifier = Modifier, + shape = roundedCornerShape, + colors = ButtonDefaults.buttonColors( + containerColor = containerColor, + contentColor = contentColor, + disabledContainerColor = KusTheme.colors.c_E0E0E0, + disabledContentColor = KusTheme.colors.c_AAAAAA, + ), + border = BorderStroke(1.dp, borderColor), + contentPadding = contentPadding, + ) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center, + ) { + if (icon != null) { + Icon( + imageVector = icon, + contentDescription = null, + modifier = Modifier.size(24.dp) + ) + + Spacer(Modifier.width(10.dp)) + } + + Text( + text = buttonName, + style = textStyle, + ) + } + } + } +} + +//@Preview +//@Composable +//private fun KusButtonPreview() { +// KusTheme { +// KusButton( +// buttonName = "랜덤 뽑기", +// enabled = false, +// roundedCornerShape = RoundedCornerShape(50.dp), +// modifier = Modifier.fillMaxWidth(), +// borderColor = KusTheme.colors.c_E0E0E0, +// onClick = {}, +// ) +// } +//} +// +//@Preview +//@Composable +//private fun KusButtonPreview2() { +// KusTheme { +// KusButton( +// buttonName = "다시 뽑기", +// enabled = true, +// roundedCornerShape = RoundedCornerShape(100.dp), +// modifier = Modifier, +// textStyle = KusTheme.typography.type14r, +// contentPadding = PaddingValues(horizontal = 16.dp, vertical = 4.dp), +// icon = vectorResource(Res.drawable.ic_like), +// onClick = {}, +// ) +// } +//} +// +//@Preview(showBackground = true) +//@Composable +//private fun KusButtonPreview3() { +// KusTheme { +// Column( +// modifier = Modifier.fillMaxSize(), +// verticalArrangement = Arrangement.Center, +// ) { +// KusButton( +// buttonName = "카테고리 재설정", +// enabled = true, +// roundedCornerShape = RoundedCornerShape(100.dp), +// modifier = Modifier, +// textStyle = KusTheme.typography.type14r, +// contentPadding = PaddingValues(horizontal = 16.dp, vertical = 4.dp), +// contentColor = KusTheme.colors.c_43AB38, +// containerColor = Color.White, +// isShadowVisible = true, +// onClick = {}, +// ) +// } +// } +//} diff --git a/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusCategoryImageButton.kt b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusCategoryImageButton.kt new file mode 100644 index 0000000..c9f8869 --- /dev/null +++ b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusCategoryImageButton.kt @@ -0,0 +1,108 @@ +package com.kus.designsystem.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.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +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.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp +import com.kus.designsystem.theme.KusTheme + +/** + * 카테고리 버튼 + * + * @param modifier 수정자 + * @param categoryName 카테고리명 + * @param categoryImage 카테고리 이미지 ImageVector + * @param isSelected 버튼 선택 유무 (default : false) + * @param onClick 버튼 클릭 시 호출 되는 콜백 함수 + */ +@Composable +fun KusCategoryImageButton( + modifier: Modifier = Modifier, + categoryName: String, + categoryImage: ImageVector, + isSelected: Boolean = false, + onClick: () -> Unit, +) { + val roundedCornerShape = RoundedCornerShape(15.dp) + val borderColor = + if (isSelected) KusTheme.colors.c_43AB38 + else KusTheme.colors.c_F5F5F5 + + Box { + if (isSelected) { + Box( + modifier = Modifier + .matchParentSize() + .shadow( + elevation = 20.dp, + shape = RoundedCornerShape(15.dp), + ambientColor = borderColor.copy(alpha = 0.6f), + ) + ) + } + + Column( + modifier = modifier + .border(width = 1.dp, color = borderColor, shape = roundedCornerShape) + .clip(roundedCornerShape) + .background(KusTheme.colors.c_F5F5F5) + .clickable(onClick = onClick) + .padding(6.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Image( + imageVector = categoryImage, + contentDescription = null, + modifier = Modifier.size(60.dp), + ) + + Text( + text = categoryName, + style = KusTheme.typography.type11m, + color = KusTheme.colors.c_323232, + ) + } + } +} + +//@Preview +//@Composable +//private fun KusCategoryImageButtonPreview() { +// KusTheme { +// KusCategoryImageButton( +// categoryName = "전체", +// categoryImage = vectorResource(Res.drawable.ic_like), +// modifier = Modifier, +// onClick = {}, +// ) +// } +//} +// +//@Preview(showBackground = true) +//@Composable +//private fun KusCategoryImageButtonSelectablePreview() { +// var isSelected by remember { mutableStateOf(false) } +// +// KusTheme { +// KusCategoryImageButton( +// categoryName = "전체", +// categoryImage = vectorResource(Res.drawable.ic_like), +// isSelected = isSelected, +// modifier = Modifier, +// onClick = { isSelected = !isSelected }, +// ) +// } +//} diff --git a/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusChip.kt b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusChip.kt index 6179fd9..af29e9a 100644 --- a/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusChip.kt +++ b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusChip.kt @@ -1,81 +1,71 @@ package com.kus.designsystem.component - -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.layout.Arrangement + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Surface 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.graphics.Color import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.kus.designsystem.color.KusColor.Signature1 -import com.kus.designsystem.util.noRippleClickable +import com.kus.designsystem.theme.KusTheme import org.jetbrains.compose.ui.tooling.preview.Preview -private val UnselectedStroke = Color(0xFFAAAAAA) - +/** + * 티어표 상단 필터 칩 + * + * @param modifier chip 영역 수정자 + * @param chipName chip 이름 + * @param isSelected chip 선택 유무 + * @param onClick chip 클릭 시 호출 되는 콜백 함수 + */ @Composable fun KusChip( - text: String, + modifier: Modifier = Modifier, + chipName: String, + isSelected: Boolean = false, onClick: () -> Unit, - selected: Boolean, - isSelectable: Boolean, - modifier: Modifier = Modifier ) { - val strokeColor = if (selected) Signature1 else UnselectedStroke - val bgColor = if (selected) Signature1.copy(alpha = 0.2f) else Color.Transparent + val roundedCornerShape = RoundedCornerShape(100.dp) + val mainColor = + if (isSelected) KusTheme.colors.c_43AB38 + else KusTheme.colors.c_AAAAAA + val backgroundColor = + if (isSelected) KusTheme.colors.c_43AB38.copy(alpha = 0.2f) + else Color.White - Surface( - modifier = modifier.then( - if (isSelectable) Modifier.noRippleClickable(onClick) else Modifier - ), - shape = RoundedCornerShape(16.dp), - color = bgColor, - border = BorderStroke(1.dp, strokeColor) + Box( + modifier = modifier + .background(backgroundColor, roundedCornerShape) + .border(1.dp, mainColor, roundedCornerShape) + .padding(horizontal = 16.dp, vertical = 4.dp) + .clickable(onClick = onClick), ) { - Box( - modifier = Modifier.padding(horizontal = 14.dp, vertical = 6.dp), - contentAlignment = Alignment.Center - ) { - Text( - text = text, - color = strokeColor, - fontSize = 14.sp - ) - } + Text( + text = chipName, + style = KusTheme.typography.type14r, + color = mainColor, + ) } } - -@Preview(showBackground = true) +@Preview @Composable -fun PreviewKusChip() { - var isSelected1 by remember { mutableStateOf(true) } - var isSelected2 by remember { mutableStateOf(true) } +private fun KusChipPreview() { + var isSelected by remember { mutableStateOf(false) } - Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + KusTheme { KusChip( - text = "Selectable", - selected = isSelected1, - isSelectable = true, - onClick = { isSelected1 = !isSelected1 } - ) - - KusChip( - text = "Locked (selected but not clickable)", - selected = isSelected2, - isSelectable = false, - onClick = { isSelected2 = !isSelected2 } // 호출 안 됨 + chipName = "전체", + isSelected = isSelected, + onClick = { isSelected = !isSelected }, ) } -} \ No newline at end of file +} diff --git a/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusRatingBar.kt b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusRatingBar.kt new file mode 100644 index 0000000..eb580b2 --- /dev/null +++ b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusRatingBar.kt @@ -0,0 +1,142 @@ +package com.kus.designsystem.component + +import androidx.compose.foundation.gestures.detectDragGestures +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.unit.dp +import kustaurant.shared.core.designsystem.generated.resources.Res +//import kustaurant.core.designsystem.generated.resources.ic_empty_star +//import kustaurant.core.designsystem.generated.resources.ic_filled_star +//import kustaurant.core.designsystem.generated.resources.ic_half_star +import org.jetbrains.compose.resources.vectorResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import kotlin.math.round + +/** + * 쿠스토랑 별점 바 + * @param modifier : 별점 전체 컴포넌트 modifier + * @param rating : 초기 rating 값 + * @param isEnabled : 별점 변경 가능 불가능 + * @param onRatingChange : 별점 변경에 따른 함수 반환 + * @param starModifier : 각 별의 modifier + */ +@Composable +fun KusRatingBar( + modifier: Modifier = Modifier, + rating: Float = 0f, + isEnabled: Boolean = true, + onRatingChange: (Float) -> Unit = {}, + starModifier: Modifier = Modifier.size(24.dp) +) { + var currentRating by remember { mutableFloatStateOf(rating.coerceIn(0f, 5f)) } + var containerWidth by remember { mutableIntStateOf(0) } + + LaunchedEffect(rating, isEnabled) { + if (!isEnabled) { + currentRating = rating.coerceIn(0f, 5f) + } + } + + Row( + modifier = modifier + .onSizeChanged { size -> + containerWidth = size.width + } + .then( + if (isEnabled) { + Modifier.pointerInput(Unit) { + detectDragGestures( + onDrag = { change, _ -> + val x = change.position.x + if (containerWidth > 0) { + val newRating = (x / containerWidth * 5).coerceIn(0f, 5f) + // 0.5 단위 반올림 + val roundedRating = (round(newRating * 2) / 2).coerceIn(0f, 5f) + if (roundedRating != currentRating) { + currentRating = roundedRating + onRatingChange(roundedRating) + } + } + } + ) + } + } else { + Modifier + } + ), + horizontalArrangement = Arrangement.spacedBy(1.dp), + verticalAlignment = Alignment.CenterVertically + ) { + repeat(5) { index -> + val starIndex = index + 1 + val starRating = currentRating - index + + when { + starRating >= 1f -> { + // 완전히 채워진 별 + Icon( + imageVector = vectorResource(Res.drawable.ic_filled_star), + contentDescription = "별점 $starIndex", + modifier = starModifier, + tint = Color.Unspecified + ) + } + starRating >= 0.5f -> { + // 반채워진 별 + Icon( + imageVector = vectorResource(Res.drawable.ic_half_star), + contentDescription = "별점 $starIndex", + modifier = starModifier, + tint = Color.Unspecified + ) + } + else -> { + // 빈 별 + Icon( + imageVector = vectorResource(Res.drawable.ic_empty_star), + contentDescription = "별점 $starIndex", + modifier = starModifier, + tint = Color.Unspecified + ) + } + } + } + } +} + +@Preview(showBackground = true, name = "드래그 가능 별점") +@Composable +fun KusRatingBarInteractivePreview() { + KusRatingBar( + modifier = Modifier.padding(16.dp), + rating = 2.5f, + isEnabled = true, + onRatingChange = { }, + starModifier = Modifier.size(40.dp) + ) +} + +@Preview(showBackground = true, name = "읽기 전용 별점") +@Composable +fun KusRatingBarReadOnlyPreview() { + KusRatingBar( + modifier = Modifier.padding(16.dp), + rating = 3.5f, + isEnabled = false + ) +} diff --git a/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusReactionButton.kt b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusReactionButton.kt new file mode 100644 index 0000000..7215fb9 --- /dev/null +++ b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusReactionButton.kt @@ -0,0 +1,181 @@ +package com.kus.designsystem.component + +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.size +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +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.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp +import com.kus.designsystem.theme.KusTheme +import kustaurant.shared.core.designsystem.generated.resources.Res +//import kustaurant.core.designsystem.generated.resources.ic_dislike +//import kustaurant.core.designsystem.generated.resources.ic_like +import org.jetbrains.compose.resources.vectorResource +import org.jetbrains.compose.ui.tooling.preview.Preview + +/** + * 좋아요/싫어요 반응 타입 + */ +enum class ReactionType { + Like, + DisLike +} + +/** + * 쿠스토랑 반응 버튼 + * @param modifier : 버튼 전체 컴포넌트 modifier + * @param likeText : 좋아요 개수 + * @param dislikeText : 싫어요 개수 + * @param selectedType : 현재 선택된 타입 (null 선택 안됨) + * @param enabled : 클릭 가능 여부 + * @param onLikeClick : 좋아요 클릭 시 호출되는 함수 + * @param onDislikeClick : 싫어요 클릭 시 호출되는 함수 + */ +@Composable +fun KusReactionButton( + modifier: Modifier = Modifier, + likeText: String, + dislikeText: String, + selectedType: ReactionType? = null, + enabled: Boolean = true, + onLikeClick: () -> Unit = {}, + onDislikeClick: () -> Unit = {}, +) { + val isLikeSelected = selectedType == ReactionType.Like + val isDislikeSelected = selectedType == ReactionType.DisLike + + Row( + modifier = modifier, + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + // 좋아요 버튼 + ReactionButtonItem( + iconRes = vectorResource(Res.drawable.ic_like), + text = likeText, + selected = isLikeSelected, + enabled = enabled, + onClick = onLikeClick, + contentDescription = "좋아요" + ) + + // 싫어요 버튼 + ReactionButtonItem( + iconRes = vectorResource(Res.drawable.ic_dislike), + text = dislikeText, + selected = isDislikeSelected, + enabled = enabled, + onClick = onDislikeClick, + contentDescription = "싫어요" + ) + } +} + +@Composable +private fun ReactionButtonItem( + iconRes: ImageVector, + text: String, + selected: Boolean, + enabled: Boolean, + onClick: () -> Unit, + contentDescription: String +) { + val iconColor = if (selected) { + KusTheme.colors.c_43AB38 + } else { + KusTheme.colors.c_AAAAAA + } + + val textColor = if (selected) { + KusTheme.colors.c_43AB38 + } else { + KusTheme.colors.c_AAAAAA + } + + Row( + modifier = Modifier + .then( + if (enabled) { + Modifier.clickable { onClick() } + } else { + Modifier + } + ), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = iconRes, + contentDescription = contentDescription, + modifier = Modifier.size(16.dp), + tint = iconColor + ) + + Spacer(modifier = Modifier.width(4.dp)) + + Text( + text = text, + style = KusTheme.typography.type14r.copy( + color = textColor + ) + ) + } +} + +@Preview(showBackground = true, name = "클릭 인터랙션 테스트") +@Composable +fun KusReactionButtonInteractivePreview() { + KusTheme { + var selectedType by remember { mutableStateOf(null) } + var likeCount by remember { mutableIntStateOf(123) } + var dislikeCount by remember { mutableIntStateOf(45) } + + KusReactionButton( + likeText = likeCount.toString(), + dislikeText = dislikeCount.toString(), + selectedType = selectedType, + enabled = true, + onLikeClick = { + if (selectedType == ReactionType.Like) { + // 이미 선택된 경우 취소 + selectedType = null + likeCount-- + } else { + // 좋아요 선택 + if (selectedType == ReactionType.DisLike) { + // 싫어요가 선택되어 있었다면 취소 + dislikeCount-- + } + selectedType = ReactionType.Like + likeCount++ + } + }, + onDislikeClick = { + if (selectedType == ReactionType.DisLike) { + // 이미 선택된 경우 취소 + selectedType = null + dislikeCount-- + } else { + // 싫어요 선택 + if (selectedType == ReactionType.Like) { + // 좋아요가 선택되어 있었다면 취소 + likeCount-- + } + selectedType = ReactionType.DisLike + dislikeCount++ + } + } + ) + } +} diff --git a/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusRestThumbnail.kt b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusRestThumbnail.kt new file mode 100644 index 0000000..256d541 --- /dev/null +++ b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusRestThumbnail.kt @@ -0,0 +1,254 @@ +package com.kus.designsystem.component + +import androidx.compose.foundation.Image +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.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +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.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import com.kus.designsystem.theme.KusTheme +import kustaurant.shared.core.designsystem.generated.resources.Res +//import kustaurant.core.designsystem.generated.resources.ic_check +//import kustaurant.core.designsystem.generated.resources.ic_kus_blank +//import kustaurant.core.designsystem.generated.resources.ic_location +//import kustaurant.core.designsystem.generated.resources.ic_saved +//import kustaurant.core.designsystem.generated.resources.ic_unsaved +import org.jetbrains.compose.resources.vectorResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import io.kamel.image.KamelImage +import io.kamel.image.asyncPainterResource + +@Composable +fun KusRestThumbnail( + modifier: Modifier = Modifier, + tier: Int? = null, + restName: String, + restThumbnail: String? = null, + restAlliance: String? = null, + categories: ArrayList? = null, + location: String? = null, + isSaved: Boolean, + isEvaluated: Boolean, + onClick: () -> Unit = {}, +) { + val locationText = location ?: "위치정보 없음" + val allianceText = restAlliance ?: "해당사항 없음" + val tierText = tier?.toString() ?: "-" + val tierColor = when (tier) { + 1 -> KusTheme.colors.c_0093FF + 2 -> KusTheme.colors.c_01BAA6 + 3 -> KusTheme.colors.c_FFB900 + 4 -> KusTheme.colors.c_9BA5B0 + else -> KusTheme.colors.c_AAAAAA + } + val savedModel = if (isSaved) Res.drawable.ic_saved else Res.drawable.ic_unsaved + + Row( + modifier = modifier + .background( + color = KusTheme.colors.c_FFFFFF, + shape = RoundedCornerShape(16.dp) + ) + .padding(8.dp) + ) { + Box( + modifier = Modifier + .size(80.dp) + .clip(RoundedCornerShape(11.dp)) + ) { + if (restThumbnail.isNullOrBlank()) { + Image( + imageVector = vectorResource(Res.drawable.ic_kus_blank), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.size(80.dp) + ) + } else { + KamelImage( + resource = asyncPainterResource(restThumbnail), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.size(80.dp), + onFailure = { + Image( + imageVector = vectorResource(Res.drawable.ic_kus_blank), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.size(80.dp) + ) + } + ) + } + + Icon( + imageVector = vectorResource(savedModel), + contentDescription = null, + modifier = Modifier + .size(20.dp) + .padding(top = 2.dp), + tint = Color.Unspecified + ) + } + + Column( + modifier = Modifier + .padding(start = 17.dp, end = 8.dp) + .weight(1f) + ) { + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = restName, + style = KusTheme.typography.type16b.copy( + color = KusTheme.colors.c_000000 + ) + ) + + if (isEvaluated) { + Icon( + imageVector = vectorResource(Res.drawable.ic_check), + contentDescription = null, + modifier = Modifier.padding(start = 6.dp), + tint = Color.Unspecified + ) + } + } + + Row( + modifier = Modifier.padding(top = 5.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = vectorResource(Res.drawable.ic_location), + contentDescription = null, + modifier = Modifier.size(12.dp), + tint = KusTheme.colors.c_AAAAAA + ) + + Text( + text = locationText, + style = KusTheme.typography.type12m.copy( + color = KusTheme.colors.c_AAAAAA + ), + modifier = Modifier.padding(start = 4.dp) + ) + } + + + if (categories != null) { + val categoryItems = categories.filter { it.isNotBlank() } + LazyRow( + modifier = Modifier + .padding(top = 4.dp), + horizontalArrangement = Arrangement.spacedBy(4.dp) + ) { + items(categoryItems) { tag -> + Text( + text = "#$tag", + style = KusTheme.typography.type12r.copy( + color = KusTheme.colors.c_AAAAAA + ) + ) + } + } + } + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(top = 8.dp) + ) { + Text( + text = "제휴", + modifier = Modifier + .border( + width = 1.dp, + color = KusTheme.colors.c_AAAAAA, + shape = RoundedCornerShape(16.dp) + ) + .background( + color = KusTheme.colors.c_FFFFFF + ) + .padding(horizontal = 4.dp, vertical = 1.dp), + style = KusTheme.typography.type10r.copy( + color = KusTheme.colors.c_AAAAAA + ) + ) + + Text( + text = allianceText, + modifier = Modifier.padding(start = 4.dp), + style = KusTheme.typography.type10r.copy( + color = KusTheme.colors.c_AAAAAA + ), + overflow = TextOverflow.Ellipsis, + maxLines = 1 + ) + + } + + } + + Box( + modifier = Modifier + .align(Alignment.Bottom) + .size(20.dp) + .border( + width = 1.dp, + color = tierColor, + shape = RoundedCornerShape(16.dp) + ) + .padding(2.dp) + .background(tierColor, RoundedCornerShape(100.dp)), + contentAlignment = Alignment.Center + ) { + Text( + text = tierText, + style = KusTheme.typography.type16sb.copy( + color = KusTheme.colors.c_FFFFFF, + lineHeight = androidx.compose.ui.unit.TextUnit.Unspecified + ), + textAlign = TextAlign.Center + ) + } + + + } +} + +//@Preview +//@Composable +//fun KusRestThumbnailPreview() { +// KusTheme { +// KusRestThumbnail( +// modifier = Modifier +// .fillMaxWidth() +// .padding(horizontal = 16.dp), +// tier = 3, +// restName = "꾸아 건대점", +// restAlliance = "어디대 학생증 제시하면 10% 할인이 된다네요 대박 개쩔어", +// categories = arrayListOf("한식", "분식", "가성비"), +// location = "서울 성동구", +// isSaved = true, +// isEvaluated = true, +// ) +// } +//} diff --git a/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusTopBar.kt b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusTopBar.kt new file mode 100644 index 0000000..ebc221a --- /dev/null +++ b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/component/KusTopBar.kt @@ -0,0 +1,130 @@ +package com.kus.designsystem.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector + +/** + * 쿠스토랑 top bar + * @param modifier : 전체 modifier + * @param leftIcon : 좌측 아이콘 + * @param rightFirstIcon : 우측 왼쪽 첫번째 아이콘 + * @param rightSecondIcon : 우측 오른쪽 두번째 아이콘 + * @param onLeftClicked : 좌측 아이콘 클릭 로직 + * @param onRightFirstClicked : 우측 왼쪽 첫번째 아이콘 클릭 로직 + * @param onRightSecondClicked : 우측 오른쪽 첫번째 아이콘 클릭 로직 + * @param leftIconModifier : 좌측 아이콘 modifier + * @param rightFirstIconModifier : 우측 왼쪽 첫번째 아이콘 modifier + * @param rightSecondIconModifier : 우측 오른쪽 두번째 아이콘 modifier + * @param content : 가운데 표시되는 content + */ +@Composable +fun KusTopBar( + modifier: Modifier = Modifier, + leftIcon: ImageVector? = null, + rightFirstIcon: ImageVector? = null, + rightSecondIcon: ImageVector? = null, + onLeftClicked: () -> Unit = {}, + onRightFirstClicked: () -> Unit = {}, + onRightSecondClicked: () -> Unit = {}, + leftIconModifier: Modifier = Modifier, + rightFirstIconModifier: Modifier = Modifier, + rightSecondIconModifier: Modifier = Modifier, + content: @Composable () -> Unit = {}, +) { + Box( + modifier = modifier + ) { + // 가운데 컨텐츠 + Row( + modifier = Modifier.align(Alignment.Center), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + content() + } + + // 왼쪽 아이콘 + if (leftIcon != null) { + IconButton( + onClick = onLeftClicked, + modifier = Modifier + .align(Alignment.CenterStart) + .then(leftIconModifier) + ) { + Icon( + imageVector = leftIcon, + contentDescription = null + ) + } + } + + // 오른쪽 아이콘들 + Row( + modifier = Modifier.align(Alignment.CenterEnd), + horizontalArrangement = Arrangement.End + ) { + if (rightFirstIcon != null) { + IconButton( + onClick = onRightFirstClicked, + modifier = rightFirstIconModifier + ) { + Icon( + imageVector = rightFirstIcon, + contentDescription = null + ) + } + } + if (rightSecondIcon != null) { + IconButton( + onClick = onRightSecondClicked, + modifier = rightSecondIconModifier + ) { + Icon( + imageVector = rightSecondIcon, + contentDescription = null + ) + } + } + } + } +} + +//@Preview(showBackground = true, name = "오른쪽 아이콘 1개") +//@Composable +//fun KusTopBarPreviewOneRightIcon(){ +// KusTheme { +// KusTopBar( +// modifier = Modifier +// .fillMaxWidth(), +// leftIcon = Icons.Default.ArrowBack, +// rightFirstIcon = Icons.Default.Search, +// content = { +// Text("제목") +// } +// ) +// } +//} +// +//@Preview(showBackground = true, name = "오른쪽 아이콘 2개") +//@Composable +//fun KusTopBarPreviewTwoRightIcons(){ +// KusTheme { +// KusTopBar( +// modifier = Modifier +// .fillMaxWidth(), +// leftIcon = Icons.Default.ArrowBack, +// rightFirstIcon = Icons.Default.Search, +// rightSecondIcon = Icons.Default.Menu, +// content = { +// Text("제목") +// } +// ) +// } +//} diff --git a/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Color.kt b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Color.kt new file mode 100644 index 0000000..b483c21 --- /dev/null +++ b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Color.kt @@ -0,0 +1,143 @@ +package com.kus.designsystem.theme + +import androidx.compose.runtime.Stable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.compose.ui.graphics.Color + +val C_43AB38 = Color(0xFF43AB38) +val C_046B40 = Color(0xFF046B40) +val C_FFFFFF = Color(0xFFFFFFFF) +val C_F5F5F5 = Color(0xFFF5F5F5) +val C_EAEAEA = Color(0xFFEAEAEA) +val C_E0E0E0 = Color(0xFFE0E0E0) +val C_AAAAAA = Color(0xFFAAAAAA) +val C_666666 = Color(0xFF666666) +val C_323232 = Color(0xFF323232) +val C_353535 = Color(0xFF353535) +val C_000000 = Color(0xFF000000) +val C_0093FF = Color(0xFF0093FF) +val C_01BAA6 = Color(0xFF01BAA6) +val C_FFB900 = Color(0xFFFFB900) +val C_9BA5B0 = Color(0xFF9BA5B0) + +@Stable +class KusColors( + c_43AB38: Color, + c_046B40: Color, + c_FFFFFF: Color, + c_F5F5F5: Color, + c_EAEAEA: Color, + c_E0E0E0: Color, + c_AAAAAA: Color, + c_666666: Color, + c_323232: Color, + c_353535: Color, + c_000000: Color, + c_0093FF: Color, + c_01BAA6: Color, + c_FFB900: Color, + c_9BA5B0: Color, +) { + var c_43AB38 by mutableStateOf(c_43AB38) + private set + var c_046B40 by mutableStateOf(c_046B40) + private set + var c_FFFFFF by mutableStateOf(c_FFFFFF) + private set + var c_F5F5F5 by mutableStateOf(c_F5F5F5) + private set + var c_EAEAEA by mutableStateOf(c_EAEAEA) + private set + var c_E0E0E0 by mutableStateOf(c_E0E0E0) + private set + var c_AAAAAA by mutableStateOf(c_AAAAAA) + private set + var c_666666 by mutableStateOf(c_666666) + private set + var c_323232 by mutableStateOf(c_323232) + private set + var c_353535 by mutableStateOf(c_353535) + private set + var c_000000 by mutableStateOf(c_000000) + private set + var c_0093FF by mutableStateOf(c_0093FF) + private set + var c_01BAA6 by mutableStateOf(c_01BAA6) + private set + var c_FFB900 by mutableStateOf(c_FFB900) + private set + var c_9BA5B0 by mutableStateOf(c_9BA5B0) + private set + + fun copy(): KusColors = KusColors( + c_43AB38, + c_046B40, + c_FFFFFF, + c_F5F5F5, + c_EAEAEA, + c_E0E0E0, + c_AAAAAA, + c_666666, + c_323232, + c_353535, + c_000000, + c_0093FF, + c_01BAA6, + c_FFB900, + c_9BA5B0, + ) + + fun update(other: KusColors) { + c_43AB38 = other.c_43AB38 + c_046B40 = other.c_046B40 + c_FFFFFF = other.c_FFFFFF + c_F5F5F5 = other.c_F5F5F5 + c_EAEAEA = other.c_EAEAEA + c_E0E0E0 = other.c_E0E0E0 + c_AAAAAA = other.c_AAAAAA + c_666666 = other.c_666666 + c_323232 = other.c_323232 + c_353535 = other.c_353535 + c_000000 = other.c_000000 + c_0093FF = other.c_0093FF + c_01BAA6 = other.c_01BAA6 + c_FFB900 = other.c_FFB900 + c_9BA5B0 = other.c_9BA5B0 + } +} + +fun KusLightColors( + c_43AB38: Color = C_43AB38, + c_046B40: Color = C_046B40, + c_FFFFFF: Color = C_FFFFFF, + c_F5F5F5: Color = C_F5F5F5, + c_EAEAEA: Color = C_EAEAEA, + c_E0E0E0: Color = C_E0E0E0, + c_AAAAAA: Color = C_AAAAAA, + c_666666: Color = C_666666, + c_323232: Color = C_323232, + c_353535: Color = C_353535, + c_000000: Color = C_000000, + c_0093FF: Color = C_0093FF, + c_01BAA6: Color = C_01BAA6, + c_FFB900: Color = C_FFB900, + c_9BA5B0: Color = C_9BA5B0, +) = KusColors( + c_43AB38, + c_046B40, + c_FFFFFF, + c_F5F5F5, + c_EAEAEA, + c_E0E0E0, + c_AAAAAA, + c_666666, + c_323232, + c_353535, + c_000000, + c_0093FF, + c_01BAA6, + c_FFB900, + c_9BA5B0, +) diff --git a/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Theme.kt b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Theme.kt new file mode 100644 index 0000000..3726c69 --- /dev/null +++ b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Theme.kt @@ -0,0 +1,58 @@ +package com.kus.designsystem.theme + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.remember +import androidx.compose.runtime.staticCompositionLocalOf + +private val LocalKusColors = staticCompositionLocalOf { + error("No KusColors provided") +} + +private val LocalKusTypography = staticCompositionLocalOf { + error("No KusTypography provided") +} + +object KusTheme { + val colors: KusColors + @Composable + @ReadOnlyComposable + get() = LocalKusColors.current + val typography: KusTypography + @Composable + @ReadOnlyComposable + get() = LocalKusTypography.current +} + +@Composable +fun ProvideKusColorsAndTypography( + colors: KusColors, + typography: KusTypography, + content: @Composable () -> Unit +) { + val provideColors = remember { colors.copy() }.apply { update(colors) } + CompositionLocalProvider( + LocalKusColors provides provideColors, + LocalKusTypography provides typography, + content = content + ) +} + +@Composable +fun KusTheme( + content: @Composable () -> Unit +) { + val colors = KusLightColors() + val typography = createKusTypography() + + ProvideKusColorsAndTypography( + colors = colors, + typography = typography + ) { + MaterialTheme( + content = content + ) + } +} diff --git a/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Type.kt b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Type.kt new file mode 100644 index 0000000..e8ebe9d --- /dev/null +++ b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/theme/Type.kt @@ -0,0 +1,146 @@ +package com.kus.designsystem.theme + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.LineHeightStyle +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.em +import androidx.compose.ui.unit.sp +import kustaurant.shared.core.designsystem.generated.resources.Res +import kustaurant.shared.core.designsystem.generated.resources.pretendard_bold +import kustaurant.shared.core.designsystem.generated.resources.pretendard_medium +import kustaurant.shared.core.designsystem.generated.resources.pretendard_regular +import kustaurant.shared.core.designsystem.generated.resources.pretendard_semibold +import org.jetbrains.compose.resources.Font + +private val PretendardRegular: FontFamily + @Composable + get() = + FontFamily(Font(Res.font.pretendard_regular, FontWeight.Normal)) + +private val PretendardMedium: FontFamily + @Composable + get() = + FontFamily(Font(Res.font.pretendard_medium, FontWeight.Medium)) + +private val PretendardSemiBold: FontFamily + @Composable + get() = + FontFamily(Font(Res.font.pretendard_semibold, FontWeight.SemiBold)) + +private val PretendardBold: FontFamily + @Composable + get() = + FontFamily(Font(Res.font.pretendard_bold, FontWeight.Bold)) + +private fun KusTextStyle( + fontFamily: FontFamily, + fontSize: TextUnit, + lineHeight: TextUnit = 1.28.em, + letterSpacing: TextUnit = 0.02.em, +): TextStyle = TextStyle( + fontFamily = fontFamily, + fontSize = fontSize, + lineHeight = lineHeight, + letterSpacing = letterSpacing, + lineHeightStyle = LineHeightStyle( + alignment = LineHeightStyle.Alignment.Center, + trim = LineHeightStyle.Trim.None + ), +) + +@Immutable +class KusTypography( + val type20b: TextStyle, + val type16b: TextStyle, + val type13b: TextStyle, + val type18sb: TextStyle, + val type17sb: TextStyle, + val type16sb: TextStyle, + val type15sb: TextStyle, + val type18m: TextStyle, + val type16m: TextStyle, + val type15m: TextStyle, + val type12m: TextStyle, + val type11m: TextStyle, + val type14r: TextStyle, + val type13r: TextStyle, + val type12r: TextStyle, + val type11r: TextStyle, + val type10r: TextStyle, +) + +@Composable +fun createKusTypography() = KusTypography( + type20b = KusTextStyle( + fontFamily = PretendardBold, + fontSize = 20.sp, + ), + type16b = KusTextStyle( + fontFamily = PretendardBold, + fontSize = 16.sp, + ), + type13b = KusTextStyle( + fontFamily = PretendardBold, + fontSize = 13.sp, + ), + type18sb = KusTextStyle( + fontFamily = PretendardSemiBold, + fontSize = 18.sp, + ), + type17sb = KusTextStyle( + fontFamily = PretendardSemiBold, + fontSize = 17.sp, + ), + type16sb = KusTextStyle( + fontFamily = PretendardSemiBold, + fontSize = 16.sp, + ), + type15sb = KusTextStyle( + fontFamily = PretendardSemiBold, + fontSize = 15.sp, + ), + type18m = KusTextStyle( + fontFamily = PretendardMedium, + fontSize = 18.sp, + ), + type16m = KusTextStyle( + fontFamily = PretendardMedium, + fontSize = 16.sp, + ), + type15m = KusTextStyle( + fontFamily = PretendardMedium, + fontSize = 15.sp, + ), + type12m = KusTextStyle( + fontFamily = PretendardMedium, + fontSize = 12.sp, + ), + type11m = KusTextStyle( + fontFamily = PretendardMedium, + fontSize = 11.sp, + ), + type14r = KusTextStyle( + fontFamily = PretendardRegular, + fontSize = 14.sp, + ), + type13r = KusTextStyle( + fontFamily = PretendardRegular, + fontSize = 13.sp, + ), + type12r = KusTextStyle( + fontFamily = PretendardRegular, + fontSize = 12.sp, + ), + type11r = KusTextStyle( + fontFamily = PretendardRegular, + fontSize = 11.sp, + ), + type10r = KusTextStyle( + fontFamily = PretendardRegular, + fontSize = 10.sp, + ), +) diff --git a/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/util/ColorUtil.kt b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/util/ColorUtil.kt new file mode 100644 index 0000000..8dd42e4 --- /dev/null +++ b/shared/core/designSystem/src/commonMain/kotlin/com/kus/designsystem/util/ColorUtil.kt @@ -0,0 +1,13 @@ +package com.kus.designsystem.util + +import androidx.compose.ui.graphics.Color + +/** + * 컬러의 투명도를 퍼센트로 설정하는 확장함수 + * @param percent 투명도 퍼센트 (0-100) + * @return 해당 퍼센트의 투명도를 가진 Color + */ +fun Color.withOpacityPercent(percent: Int): Color { + val clampedPercent = percent.coerceIn(0, 100) + return this.copy(alpha = clampedPercent / 100f) +} diff --git a/shared/data/firstLaunch/build.gradle.kts b/shared/data/firstLaunch/build.gradle.kts index 629b91d..df37dd2 100644 --- a/shared/data/firstLaunch/build.gradle.kts +++ b/shared/data/firstLaunch/build.gradle.kts @@ -55,6 +55,7 @@ kotlin { implementation(project(":shared:domain:firstLaunch")) } + resources.srcDirs("src/commonMain/composeResources") } commonTest {