diff --git a/README.md b/README.md index 2a95ce0a..ec5b4391 100644 --- a/README.md +++ b/README.md @@ -1 +1,83 @@ -# 35-APPJAM-ANDROID-SPOONY \ No newline at end of file +# SPOONY + + + +**장소의 찐 리스트를 공유하며 신뢰할 수 있는 추천으로 나만의 지도를 완성하는 앱 서비스** + +
+ +**‘Spoony’** 는 리뷰 작성자의 신뢰도와 영향력에 기반해, 유저가 믿을 수 있는 장소 정보를 탐색하고 공유하며 나만의 찐 리스트 지도를 만들어가는 앱 서비스입니다. + +🌟Spoony와 함께 새로운 장소를 발견하고 나만의 지도를 완성해보세요!🌟 + +
+ + +> 🥄 **Spoony 만의 특별한 사용법**

+1️⃣ **장소 등록하고 수저 획득하기**
+나만 알고 싶은 맛집, 아늑한 카페, 분위기 좋은 펍 등 찐 **장소를 등록하고 수저를 획득**하세요!

+2️⃣**신뢰도 높은 찐 리스트 떠먹기**
+획득한 수저로 다른 사람의 찐 리스트를 떠먹어 보세요! 원하는 유저를 팔로우하고 로컬 사용자와 지역별 랭킹을 통해 **신뢰도 높은 리뷰**를 확인해보세요.

+3️⃣ **나만의 지도 완성하기**
+떠먹은 리스트 중 **마음에 드는 장소를** 추가해 나만의 **찐 리스트 지도**를 만들어보세요!
+ +
+ +## CONTRIBUTORS +| 👑박효빈
([@Hyobeen-Park](https://github.com/Hyobeen-Park)) | 한민재
([@angryPodo](https://github.com/angryPodo)) | 안세홍
([@Roel4990](https://github.com/Roel4990)) | 박동민
([@chattymin](https://github.com/chattymin)) | +|:---------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------:| +| | | | | +| `메인 지도`
`탐색하기`
| `장소 등록하기`
| `장소 상세 페이지`
`신고하기`
| `멘토`
+ + +
+ +## PACKAGE CONVENTION + +``` + +📁 core + ┣ 📁 designsystem + ┣ 📁 util + ┣ 📁 state + ┗ 📁navigation + +📁 data + ┣ 📁 dto + ┃ ┣ 📁 response + ┃ ┣ 📁 request + ┣ 📁 datasource + ┣ 📁 datasourceImpl + ┣ 📁 di + ┣ 📁 local + ┣ 📁 mapper + ┣ 📁 repositoryImpl + ┗ 📁 service + +📁 domain + ┣ 📁 entity + ┗ 📁 repository + +📁 presentation + ┗ 📁 기능 별 패키징 + +``` + +
+ +## TECH STACK +| Title | Content | +| ------------ |---------------------------------------| +| Architecture | Clean Architecture, MVVM | +| UI Framework | Jetpack Compose | +| Dependency Injection | Hilt | +| Network | Retrofit2, OkHttp | +| Asynchronous Processing | Coroutine, Flow | +| Third Party Library | Coil, Timber, Lottie, Naver Map | +| Other Tools | Discode, Notion, Figma, Slack |\ +
+ +## Convention +[안드푼스들의 깃 컨벤션](https://creative-suede-cad.notion.site/Git-Convention-4038dc7126e34df6aa042b400284b188?pvs=4) +
+[안드푼스들의 코딩 컨벤션](https://creative-suede-cad.notion.site/Android-Coding-Convention-71015e22d6a44f28b07aa756c81b2cf3?pvs=4) diff --git a/app/src/main/java/com/spoony/spoony/core/designsystem/component/button/SpoonyButton.kt b/app/src/main/java/com/spoony/spoony/core/designsystem/component/button/SpoonyButton.kt new file mode 100644 index 00000000..61474325 --- /dev/null +++ b/app/src/main/java/com/spoony/spoony/core/designsystem/component/button/SpoonyButton.kt @@ -0,0 +1,266 @@ +package com.spoony.spoony.core.designsystem.component.button + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsPressedAsState +import androidx.compose.foundation.layout.Arrangement +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.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +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 com.spoony.spoony.R +import com.spoony.spoony.core.designsystem.theme.SpoonyAndroidTheme +import com.spoony.spoony.core.designsystem.type.ButtonSize +import com.spoony.spoony.core.designsystem.type.ButtonStyle + +@Composable +fun SpoonyButton( + text: String, + size: ButtonSize, + style: ButtonStyle, + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + icon: (@Composable () -> Unit)? = null, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } +) { + val isPressed by interactionSource.collectIsPressedAsState() + val spoonyColors = SpoonyAndroidTheme.colors + val spoonyTypography = SpoonyAndroidTheme.typography + val backgroundColor = remember(enabled, isPressed, style) { + when { + !enabled -> when (style) { + ButtonStyle.Primary -> spoonyColors.main100 + ButtonStyle.Secondary -> spoonyColors.gray300 + ButtonStyle.Tertiary -> spoonyColors.gray100 + } + isPressed -> when (style) { + ButtonStyle.Primary -> spoonyColors.main500 + ButtonStyle.Secondary -> spoonyColors.gray800 + ButtonStyle.Tertiary -> spoonyColors.gray100 + } + else -> when (style) { + ButtonStyle.Primary -> spoonyColors.main400 + ButtonStyle.Secondary -> spoonyColors.black + ButtonStyle.Tertiary -> spoonyColors.gray0 + } + } + } + val paddingValues = remember(size) { + when (size) { + ButtonSize.Xlarge, ButtonSize.Large, ButtonSize.Medium, ButtonSize.Small -> PaddingValues(horizontal = 16.dp, vertical = 18.dp) + ButtonSize.Xsmall -> PaddingValues(horizontal = 16.dp, vertical = 12.dp) + } + } + + val textColor = remember(style) { + when (style) { + ButtonStyle.Tertiary -> when { + !enabled -> spoonyColors.gray400 + else -> spoonyColors.gray600 + } + else -> spoonyColors.white + } + } + + val cornerRadius = remember(size) { + when (size) { + ButtonSize.Xlarge -> 8.dp + ButtonSize.Large, ButtonSize.Medium, ButtonSize.Small, ButtonSize.Xsmall -> 10.dp + } + } + Row( + modifier = modifier + .clip(RoundedCornerShape(cornerRadius)) + .background(color = backgroundColor) + .clickable( + enabled = enabled, + indication = null, + interactionSource = interactionSource, + onClick = onClick + ) + .padding(paddingValues), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + if (icon != null) { + icon() + Spacer(modifier = Modifier.width(8.dp)) + } + Text( + text = text, + color = textColor, + style = SpoonyAndroidTheme.typography.body2b + ) + } +} + +private class ButtonStyleProvider : PreviewParameterProvider { + override val values: Sequence = sequenceOf( + ButtonStyle.Primary, + ButtonStyle.Secondary, + ButtonStyle.Tertiary + ) +} + +@Preview +@Composable +fun SpoonyButtonEnabledPreview( + @PreviewParameter(ButtonStyleProvider::class) style: ButtonStyle +) { + SpoonyAndroidTheme { + Column( + modifier = Modifier, + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + ButtonSize.entries.forEach { size -> + SpoonyButton( + text = "버튼", + style = style, + size = size, + onClick = { } + ) + } + } + } +} + +@Preview +@Composable +fun SpoonyButtonEnabledIconPreview( + @PreviewParameter(ButtonStyleProvider::class) style: ButtonStyle +) { + SpoonyAndroidTheme { + Column( + modifier = Modifier, + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + ButtonSize.entries.forEach { size -> + SpoonyButton( + text = "버튼", + style = style, + size = size, + onClick = { }, + icon = { + Icon( + painter = painterResource(R.drawable.ic_launcher_foreground), + modifier = Modifier.size(32.dp), + contentDescription = "ic_spoon_button", + tint = Color.Unspecified + ) + } + ) + } + } + } +} + +@Preview +@Composable +fun SpoonyButtonDisabledPreview( + @PreviewParameter(ButtonStyleProvider::class) style: ButtonStyle +) { + SpoonyAndroidTheme { + Column( + modifier = Modifier, + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + ButtonSize.entries.forEach { size -> + SpoonyButton( + text = "버튼", + style = style, + size = size, + enabled = false, + onClick = { } + ) + } + } + } +} + +@Preview +@Composable +private fun SpoonyButtonWidthModifierPreview() { + SpoonyAndroidTheme { + SpoonyButton( + text = "떠먹으러 가기", + onClick = {}, + style = ButtonStyle.Secondary, + size = ButtonSize.Xsmall, + modifier = Modifier.width(134.dp) + ) + } +} + +@Preview +@Composable +private fun SpoonyButtonTwoButtonPreview() { + SpoonyAndroidTheme { + Column( + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + SpoonyButton( + text = "버튼", + onClick = {}, + style = ButtonStyle.Tertiary, + size = ButtonSize.Xsmall, + modifier = Modifier.weight(1f) + ) + Spacer(modifier = Modifier.width(13.dp)) + SpoonyButton( + text = "버튼", + onClick = {}, + style = ButtonStyle.Secondary, + size = ButtonSize.Xsmall, + modifier = Modifier.weight(1f) + ) + } + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + SpoonyButton( + text = "버튼", + onClick = {}, + style = ButtonStyle.Tertiary, + size = ButtonSize.Xsmall, + enabled = false, + modifier = Modifier.weight(1f) + ) + Spacer(modifier = Modifier.width(13.dp)) + SpoonyButton( + text = "버튼", + onClick = {}, + style = ButtonStyle.Secondary, + size = ButtonSize.Xsmall, + enabled = false, + modifier = Modifier.weight(1f) + ) + } + } + } +} diff --git a/app/src/main/java/com/spoony/spoony/core/designsystem/type/ButtonStyles.kt b/app/src/main/java/com/spoony/spoony/core/designsystem/type/ButtonStyles.kt new file mode 100644 index 00000000..48eb3b98 --- /dev/null +++ b/app/src/main/java/com/spoony/spoony/core/designsystem/type/ButtonStyles.kt @@ -0,0 +1,9 @@ +package com.spoony.spoony.core.designsystem.type + +enum class ButtonSize { + Xlarge, Large, Medium, Small, Xsmall +} + +enum class ButtonStyle { + Primary, Secondary, Tertiary +} diff --git a/app/src/main/java/com/spoony/spoony/core/util/extension/ModifierExt.kt b/app/src/main/java/com/spoony/spoony/core/util/extension/ModifierExt.kt new file mode 100644 index 00000000..1fd624eb --- /dev/null +++ b/app/src/main/java/com/spoony/spoony/core/util/extension/ModifierExt.kt @@ -0,0 +1,17 @@ +package com.spoony.spoony.core.util.extension + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.composed + +@Composable +inline fun Modifier.noRippleClickable(crossinline onClick: () -> Unit): Modifier = composed { + this.clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() }, + onClick = { onClick() } + ) +} diff --git a/app/src/main/res/drawable/ic_add_map_gray400_24.xml b/app/src/main/res/drawable/ic_add_map_gray400_24.xml new file mode 100644 index 00000000..6818e549 --- /dev/null +++ b/app/src/main/res/drawable/ic_add_map_gray400_24.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_add_map_main400_24.xml b/app/src/main/res/drawable/ic_add_map_main400_24.xml new file mode 100644 index 00000000..bc0a91f0 --- /dev/null +++ b/app/src/main/res/drawable/ic_add_map_main400_24.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_add_pin_main400_24.xml b/app/src/main/res/drawable/ic_add_pin_main400_24.xml new file mode 100644 index 00000000..abab13e8 --- /dev/null +++ b/app/src/main/res/drawable/ic_add_pin_main400_24.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_american_24.xml b/app/src/main/res/drawable/ic_american_24.xml new file mode 100644 index 00000000..73e44b34 --- /dev/null +++ b/app/src/main/res/drawable/ic_american_24.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_arrow_down_24.xml b/app/src/main/res/drawable/ic_arrow_down_24.xml new file mode 100644 index 00000000..f49b2848 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_down_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_left_24.xml b/app/src/main/res/drawable/ic_arrow_left_24.xml new file mode 100644 index 00000000..63fae3d4 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_left_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_right_24.xml b/app/src/main/res/drawable/ic_arrow_right_24.xml new file mode 100644 index 00000000..a3378dab --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_right_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_up_24.xml b/app/src/main/res/drawable/ic_arrow_up_24.xml new file mode 100644 index 00000000..ea624035 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_up_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_bar_24.xml b/app/src/main/res/drawable/ic_bar_24.xml new file mode 100644 index 00000000..fe8efe66 --- /dev/null +++ b/app/src/main/res/drawable/ic_bar_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_button_spoon_32.xml b/app/src/main/res/drawable/ic_button_spoon_32.xml new file mode 100644 index 00000000..57a517d4 --- /dev/null +++ b/app/src/main/res/drawable/ic_button_spoon_32.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_cafe_24.xml b/app/src/main/res/drawable/ic_cafe_24.xml new file mode 100644 index 00000000..00f3e99e --- /dev/null +++ b/app/src/main/res/drawable/ic_cafe_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_chinese_24.xml b/app/src/main/res/drawable/ic_chinese_24.xml new file mode 100644 index 00000000..411145a4 --- /dev/null +++ b/app/src/main/res/drawable/ic_chinese_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_close_24.xml b/app/src/main/res/drawable/ic_close_24.xml new file mode 100644 index 00000000..8000aca0 --- /dev/null +++ b/app/src/main/res/drawable/ic_close_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_delete_filled_24.xml b/app/src/main/res/drawable/ic_delete_filled_24.xml new file mode 100644 index 00000000..62070162 --- /dev/null +++ b/app/src/main/res/drawable/ic_delete_filled_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_delete_filled_gray100_24.xml b/app/src/main/res/drawable/ic_delete_filled_gray100_24.xml new file mode 100644 index 00000000..9ca0983f --- /dev/null +++ b/app/src/main/res/drawable/ic_delete_filled_gray100_24.xml @@ -0,0 +1,13 @@ + + + + diff --git a/app/src/main/res/drawable/ic_delete_outlined_24.xml b/app/src/main/res/drawable/ic_delete_outlined_24.xml new file mode 100644 index 00000000..ea508347 --- /dev/null +++ b/app/src/main/res/drawable/ic_delete_outlined_24.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/ic_error_24.xml b/app/src/main/res/drawable/ic_error_24.xml new file mode 100644 index 00000000..833a6339 --- /dev/null +++ b/app/src/main/res/drawable/ic_error_24.xml @@ -0,0 +1,17 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_explore_24.xml b/app/src/main/res/drawable/ic_explore_24.xml new file mode 100644 index 00000000..b7e249e3 --- /dev/null +++ b/app/src/main/res/drawable/ic_explore_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_filter_24.xml b/app/src/main/res/drawable/ic_filter_24.xml new file mode 100644 index 00000000..1b215dd9 --- /dev/null +++ b/app/src/main/res/drawable/ic_filter_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_japanese_24.xml b/app/src/main/res/drawable/ic_japanese_24.xml new file mode 100644 index 00000000..dc843d62 --- /dev/null +++ b/app/src/main/res/drawable/ic_japanese_24.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_korean_24.xml b/app/src/main/res/drawable/ic_korean_24.xml new file mode 100644 index 00000000..4a2431b7 --- /dev/null +++ b/app/src/main/res/drawable/ic_korean_24.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_map_gray400_24.xml b/app/src/main/res/drawable/ic_map_gray400_24.xml new file mode 100644 index 00000000..19a6f158 --- /dev/null +++ b/app/src/main/res/drawable/ic_map_gray400_24.xml @@ -0,0 +1,13 @@ + + + + diff --git a/app/src/main/res/drawable/ic_map_main400_24.xml b/app/src/main/res/drawable/ic_map_main400_24.xml new file mode 100644 index 00000000..43f36678 --- /dev/null +++ b/app/src/main/res/drawable/ic_map_main400_24.xml @@ -0,0 +1,13 @@ + + + + diff --git a/app/src/main/res/drawable/ic_pin_24.xml b/app/src/main/res/drawable/ic_pin_24.xml new file mode 100644 index 00000000..ef9b96c5 --- /dev/null +++ b/app/src/main/res/drawable/ic_pin_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_plus_24.xml b/app/src/main/res/drawable/ic_plus_24.xml new file mode 100644 index 00000000..e9be061b --- /dev/null +++ b/app/src/main/res/drawable/ic_plus_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_radio_off_24.xml b/app/src/main/res/drawable/ic_radio_off_24.xml new file mode 100644 index 00000000..c1134ea7 --- /dev/null +++ b/app/src/main/res/drawable/ic_radio_off_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_radio_on_24.xml b/app/src/main/res/drawable/ic_radio_on_24.xml new file mode 100644 index 00000000..eb0a74ac --- /dev/null +++ b/app/src/main/res/drawable/ic_radio_on_24.xml @@ -0,0 +1,13 @@ + + + + diff --git a/app/src/main/res/drawable/ic_register_24.xml b/app/src/main/res/drawable/ic_register_24.xml new file mode 100644 index 00000000..fb1b768b --- /dev/null +++ b/app/src/main/res/drawable/ic_register_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_scooped_up_gray500_24.xml b/app/src/main/res/drawable/ic_scooped_up_gray500_24.xml new file mode 100644 index 00000000..5d6acd53 --- /dev/null +++ b/app/src/main/res/drawable/ic_scooped_up_gray500_24.xml @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_search_24.xml b/app/src/main/res/drawable/ic_search_24.xml new file mode 100644 index 00000000..02ae24ac --- /dev/null +++ b/app/src/main/res/drawable/ic_search_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_spoon_24.xml b/app/src/main/res/drawable/ic_spoon_24.xml new file mode 100644 index 00000000..b9dd7147 --- /dev/null +++ b/app/src/main/res/drawable/ic_spoon_24.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_spoon_cross_24.xml b/app/src/main/res/drawable/ic_spoon_cross_24.xml new file mode 100644 index 00000000..539f67e4 --- /dev/null +++ b/app/src/main/res/drawable/ic_spoon_cross_24.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_views_grad_24.xml b/app/src/main/res/drawable/ic_views_grad_24.xml new file mode 100644 index 00000000..e105ce44 --- /dev/null +++ b/app/src/main/res/drawable/ic_views_grad_24.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_world_24.xml b/app/src/main/res/drawable/ic_world_24.xml new file mode 100644 index 00000000..29dbbc70 --- /dev/null +++ b/app/src/main/res/drawable/ic_world_24.xml @@ -0,0 +1,18 @@ + + + + + +