Skip to content

Commit

Permalink
Merge branch 'develop' into feat/#16-snackbar
Browse files Browse the repository at this point in the history
  • Loading branch information
Roel4990 committed Jan 13, 2025
2 parents d8558c6 + b6d98d4 commit 9170a1a
Show file tree
Hide file tree
Showing 38 changed files with 939 additions and 1 deletion.
84 changes: 83 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,83 @@
# 35-APPJAM-ANDROID-SPOONY
# SPOONY
<img src="https://github.com/user-attachments/assets/e25de1b2-a2df-465b-a4ff-c6ff8d85b5b4">


**장소의 찐 리스트를 공유하며 신뢰할 수 있는 추천으로 나만의 지도를 완성하는 앱 서비스**

<br>

**‘Spoony’** 는 리뷰 작성자의 신뢰도와 영향력에 기반해, 유저가 믿을 수 있는 장소 정보를 탐색하고 공유하며 나만의 찐 리스트 지도를 만들어가는 앱 서비스입니다.

🌟Spoony와 함께 새로운 장소를 발견하고 나만의 지도를 완성해보세요!🌟

<br>


> 🥄 **Spoony 만의 특별한 사용법** <br><br>
1️⃣ **장소 등록하고 수저 획득하기**<br>
나만 알고 싶은 맛집, 아늑한 카페, 분위기 좋은 펍 등 찐 **장소를 등록하고 수저를 획득**하세요!<br><br>
2️⃣**신뢰도 높은 찐 리스트 떠먹기**<br>
획득한 수저로 다른 사람의 찐 리스트를 떠먹어 보세요! 원하는 유저를 팔로우하고 로컬 사용자와 지역별 랭킹을 통해 **신뢰도 높은 리뷰**를 확인해보세요.<br><br>
3️⃣ **나만의 지도 완성하기**<br>
떠먹은 리스트 중 **마음에 드는 장소를** 추가해 나만의 **찐 리스트 지도**를 만들어보세요!<br>
<br>

## CONTRIBUTORS
| 👑박효빈<br/>([@Hyobeen-Park](https://github.com/Hyobeen-Park)) | 한민재<br/>([@angryPodo](https://github.com/angryPodo)) | 안세홍<br/>([@Roel4990](https://github.com/Roel4990)) | 박동민<br/>([@chattymin](https://github.com/chattymin)) |
|:---------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------:|
| <img width="200px" src="https://avatars.githubusercontent.com/u/98209004?v=4"/> | <img width="200px" src="https://avatars.githubusercontent.com/u/160750136?v=4"/> | <img width="200px" src="https://avatars.githubusercontent.com/u/93641814?v=4"/> | <img width="200px" src="https://avatars.githubusercontent.com/u/52882799?v=4"/> |
| `메인 지도`<br/>`탐색하기`<br/> | `장소 등록하기`<br/> | `장소 상세 페이지`<br/>`신고하기`<br/> | `멘토`<br/>


<br>

## PACKAGE CONVENTION

```
📁 core
┣ 📁 designsystem
┣ 📁 util
┣ 📁 state
┗ 📁navigation
📁 data
┣ 📁 dto
┃ ┣ 📁 response
┃ ┣ 📁 request
┣ 📁 datasource
┣ 📁 datasourceImpl
┣ 📁 di
┣ 📁 local
┣ 📁 mapper
┣ 📁 repositoryImpl
┗ 📁 service
📁 domain
┣ 📁 entity
┗ 📁 repository
📁 presentation
┗ 📁 기능 별 패키징
```

<br>

## 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 |\
</br>

## Convention
[안드푼스들의 깃 컨벤션](https://creative-suede-cad.notion.site/Git-Convention-4038dc7126e34df6aa042b400284b188?pvs=4)
<br/>
[안드푼스들의 코딩 컨벤션](https://creative-suede-cad.notion.site/Android-Coding-Convention-71015e22d6a44f28b07aa756c81b2cf3?pvs=4)
Original file line number Diff line number Diff line change
@@ -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<ButtonStyle> {
override val values: Sequence<ButtonStyle> = 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)
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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() }
)
}
Loading

0 comments on commit 9170a1a

Please sign in to comment.