Skip to content

Commit 1845432

Browse files
authored
Merge pull request #77 from ikseong00/feat/menufolder-api
[FEAT] 메뉴판 삭제, 순서변경 Api 구현
2 parents 3467eea + b2be1ce commit 1845432

13 files changed

Lines changed: 542 additions & 22 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.kuit.ourmenu.data.model.menuFolder.request
2+
3+
import kotlinx.serialization.Serializable
4+
5+
@Serializable
6+
data class MenuFolderIndexRequest(
7+
val index: Int,
8+
)

app/src/main/java/com/kuit/ourmenu/data/repository/MenuFolderRepository.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.kuit.ourmenu.data.repository
22

33
import com.kuit.ourmenu.data.model.base.handleBaseResponse
4+
import com.kuit.ourmenu.data.model.menuFolder.request.MenuFolderIndexRequest
45
import com.kuit.ourmenu.data.service.MenuFolderService
56
import javax.inject.Inject
67
import javax.inject.Singleton
@@ -40,4 +41,20 @@ class MenuFolderRepository @Inject constructor(
4041
sortOrder = sortOrder
4142
).handleBaseResponse().getOrThrow()
4243
}
44+
45+
suspend fun deleteMenuFolder(
46+
menuFolderId: Long
47+
) = runCatching {
48+
menuFolderService.deleteMenuFolder(menuFolderId).handleBaseResponse().getOrThrow()
49+
}
50+
51+
suspend fun updateMenuFolderIndex(
52+
menuFolderId: Long,
53+
request: MenuFolderIndexRequest
54+
) = runCatching {
55+
menuFolderService.updateMenuFolderIndex(
56+
menuFolderId = menuFolderId,
57+
request = request
58+
).handleBaseResponse().getOrThrow()
59+
}
4360
}

app/src/main/java/com/kuit/ourmenu/data/service/MenuFolderService.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package com.kuit.ourmenu.data.service
22

33
import com.kuit.ourmenu.data.model.base.BaseResponse
4+
import com.kuit.ourmenu.data.model.menuFolder.request.MenuFolderIndexRequest
45
import com.kuit.ourmenu.data.model.menuFolder.response.MenuFolderAllResponse
56
import com.kuit.ourmenu.data.model.menuFolder.response.MenuFolderDetailResponse
67
import com.kuit.ourmenu.data.model.menuFolder.response.MenuFolderResponse
8+
import retrofit2.http.Body
9+
import retrofit2.http.DELETE
710
import retrofit2.http.GET
11+
import retrofit2.http.PATCH
812
import retrofit2.http.Path
913
import retrofit2.http.Query
1014

@@ -27,4 +31,15 @@ interface MenuFolderService {
2731
@Query("size") size: Int,
2832
@Query("sortOrder") sortOrder: String,
2933
): BaseResponse<List<MenuFolderAllResponse>>
34+
35+
@DELETE("api/menu-folders/{menuFolderId}")
36+
suspend fun deleteMenuFolder(
37+
@Path("menuFolderId") menuFolderId: Long
38+
): BaseResponse<Unit>
39+
40+
@PATCH("api/menu-folders/{menuFolderId}/index")
41+
suspend fun updateMenuFolderIndex(
42+
@Path("menuFolderId") menuFolderId: Long,
43+
@Body request: MenuFolderIndexRequest
44+
): BaseResponse<MenuFolderDetailResponse>
3045
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package com.kuit.ourmenu.ui.menuFolder.component
2+
3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.clickable
5+
import androidx.compose.foundation.layout.Column
6+
import androidx.compose.foundation.layout.Row
7+
import androidx.compose.foundation.layout.Spacer
8+
import androidx.compose.foundation.layout.fillMaxWidth
9+
import androidx.compose.foundation.layout.height
10+
import androidx.compose.foundation.layout.padding
11+
import androidx.compose.foundation.layout.size
12+
import androidx.compose.foundation.layout.width
13+
import androidx.compose.foundation.shape.RoundedCornerShape
14+
import androidx.compose.material3.Button
15+
import androidx.compose.material3.ButtonDefaults
16+
import androidx.compose.material3.Icon
17+
import androidx.compose.material3.Text
18+
import androidx.compose.runtime.Composable
19+
import androidx.compose.ui.Alignment
20+
import androidx.compose.ui.Modifier
21+
import androidx.compose.ui.graphics.Color
22+
import androidx.compose.ui.res.painterResource
23+
import androidx.compose.ui.res.stringResource
24+
import androidx.compose.ui.text.style.TextAlign
25+
import androidx.compose.ui.tooling.preview.Preview
26+
import androidx.compose.ui.unit.dp
27+
import androidx.compose.ui.window.Dialog
28+
import com.kuit.ourmenu.R
29+
import com.kuit.ourmenu.ui.my.component.LogoutModal
30+
import com.kuit.ourmenu.ui.theme.Neutral400
31+
import com.kuit.ourmenu.ui.theme.Neutral500
32+
import com.kuit.ourmenu.ui.theme.Neutral900
33+
import com.kuit.ourmenu.ui.theme.NeutralWhite
34+
import com.kuit.ourmenu.ui.theme.Primary500Main
35+
import com.kuit.ourmenu.ui.theme.ourMenuTypography
36+
37+
@Composable
38+
fun DeleteMenuFolderModal(
39+
onDismiss: () -> Unit,
40+
onConfirm: () -> Unit
41+
) {
42+
Dialog(onDismissRequest = onDismiss) {
43+
Column(
44+
modifier = Modifier
45+
.background(NeutralWhite, shape = RoundedCornerShape(16.dp))
46+
.padding(20.dp)
47+
.width(288.dp),
48+
horizontalAlignment = Alignment.CenterHorizontally
49+
) {
50+
// 닫기 아이콘
51+
Icon(
52+
painter = painterResource(R.drawable.ic_close_24_n400),
53+
contentDescription = null,
54+
tint = Color.Unspecified,
55+
modifier = Modifier
56+
.align(Alignment.End)
57+
.clickable { onDismiss() }
58+
.size(24.dp)
59+
)
60+
61+
Spacer(modifier = Modifier.height(8.dp))
62+
63+
// 제목
64+
Text(
65+
text = stringResource(R.string.delete_menu_folder_modal_title),
66+
style = ourMenuTypography().pretendard_700_18,
67+
color = Neutral900,
68+
textAlign = TextAlign.Center,
69+
modifier = Modifier.fillMaxWidth()
70+
)
71+
72+
Spacer(modifier = Modifier.height(12.dp))
73+
74+
Text(
75+
text = stringResource(R.string.delete_menu_folder_modal_content),
76+
style = ourMenuTypography().pretendard_500_14,
77+
color = Neutral500,
78+
textAlign = TextAlign.Center,
79+
modifier = Modifier.fillMaxWidth()
80+
)
81+
82+
Spacer(modifier = Modifier.height(16.dp))
83+
84+
// 버튼 Row
85+
Column(
86+
modifier = Modifier.fillMaxWidth()
87+
) {
88+
89+
Button(
90+
onClick = {
91+
onConfirm()
92+
onDismiss()
93+
},
94+
modifier = Modifier
95+
.fillMaxWidth()
96+
.height(48.dp),
97+
shape = RoundedCornerShape(8.dp),
98+
colors = ButtonDefaults.buttonColors(
99+
containerColor = Primary500Main,
100+
contentColor = NeutralWhite
101+
),
102+
) {
103+
Text(
104+
text = stringResource(R.string.delete),
105+
style = ourMenuTypography().pretendard_700_18,
106+
color = NeutralWhite
107+
)
108+
}
109+
110+
Spacer(modifier = Modifier.height(8.dp))
111+
112+
Button(
113+
onClick = {
114+
onDismiss()
115+
},
116+
modifier = Modifier
117+
.fillMaxWidth()
118+
.height(48.dp),
119+
shape = RoundedCornerShape(8.dp),
120+
colors = ButtonDefaults.buttonColors(
121+
containerColor = Neutral400,
122+
contentColor = NeutralWhite
123+
),
124+
) {
125+
Text(
126+
text = stringResource(R.string.cancel),
127+
style = ourMenuTypography().pretendard_700_18,
128+
color = NeutralWhite
129+
)
130+
}
131+
}
132+
}
133+
}
134+
}
135+
136+
@Preview(showBackground = true)
137+
@Composable
138+
private fun DeleteMenuFolderModalPreview() {
139+
DeleteMenuFolderModal(
140+
onDismiss = {},
141+
onConfirm = {}
142+
)
143+
}

app/src/main/java/com/kuit/ourmenu/ui/menuFolder/component/MenuFolderButton.kt

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.kuit.ourmenu.ui.menuFolder.component
22

3+
import androidx.compose.animation.core.Animatable
34
import androidx.compose.foundation.Image
45
import androidx.compose.foundation.background
56
import androidx.compose.foundation.clickable
@@ -19,21 +20,21 @@ import androidx.compose.foundation.layout.width
1920
import androidx.compose.foundation.shape.RoundedCornerShape
2021
import androidx.compose.material3.Text
2122
import androidx.compose.runtime.Composable
22-
import androidx.compose.runtime.getValue
23-
import androidx.compose.runtime.mutableFloatStateOf
23+
import androidx.compose.runtime.LaunchedEffect
2424
import androidx.compose.runtime.remember
2525
import androidx.compose.runtime.rememberCoroutineScope
26-
import androidx.compose.runtime.setValue
2726
import androidx.compose.ui.Alignment
2827
import androidx.compose.ui.Modifier
2928
import androidx.compose.ui.draw.clip
3029
import androidx.compose.ui.graphics.Brush
3130
import androidx.compose.ui.graphics.Color
3231
import androidx.compose.ui.input.pointer.pointerInput
3332
import androidx.compose.ui.layout.ContentScale
33+
import androidx.compose.ui.platform.LocalDensity
3434
import androidx.compose.ui.res.painterResource
3535
import androidx.compose.ui.res.stringResource
3636
import androidx.compose.ui.tooling.preview.Preview
37+
import androidx.compose.ui.unit.IntOffset
3738
import androidx.compose.ui.unit.dp
3839
import coil3.compose.AsyncImage
3940
import com.kuit.ourmenu.R
@@ -44,10 +45,12 @@ import com.kuit.ourmenu.ui.theme.NeutralWhite
4445
import com.kuit.ourmenu.ui.theme.Primary500Main
4546
import com.kuit.ourmenu.ui.theme.ourMenuTypography
4647
import kotlinx.coroutines.launch
48+
import kotlin.math.roundToInt
4749

4850

4951
@Composable
5052
fun MenuFolderButton(
53+
modifier: Modifier = Modifier,
5154
menuFolder: MenuFolderList,
5255
isSwiped: Boolean, // 현재 버튼이 스와이프된 상태인지 확인
5356
onSwipe: () -> Unit, // 새로운 버튼이 스와이프될 때 호출
@@ -56,31 +59,64 @@ fun MenuFolderButton(
5659
onEditClick: () -> Unit = {},
5760
onDeleteClick: () -> Unit = {}
5861
) {
59-
var offsetX by remember { mutableFloatStateOf(0f) }
62+
val density = LocalDensity.current
63+
val offset = remember {
64+
Animatable(initialValue = 0f)
65+
}
6066
val scope = rememberCoroutineScope()
61-
val maxSwipe = 128f // 최대 스와이프 범위 (삭제 + 수정 버튼 너비)
67+
val maxSwipe = with(density) {
68+
128.dp.toPx() // 최대 스와이프 범위를 dp에서 px로 변환
69+
}
70+
71+
LaunchedEffect(isSwiped) {
72+
if (!isSwiped) {
73+
offset.snapTo(0f)
74+
}
75+
}
6276

6377
Box(
64-
modifier = Modifier
78+
modifier = modifier
6579
.height(132.dp)
6680
.fillMaxWidth()
6781
.pointerInput(Unit) {
82+
// detectHorizontalDragGestures(
83+
// onDragEnd = {
84+
// scope.launch {
85+
// if (offsetX < -80f) {
86+
// onSwipe() // 다른 버튼을 닫고 이 버튼만 스와이프
87+
// offsetX = -maxSwipe
88+
// } else {
89+
// offsetX = 0f
90+
// onReset() // 스와이프가 닫히면 상태 초기화
91+
// }
92+
// }
93+
// }
94+
// ) { change, dragAmount ->
95+
// change.consume()
96+
// offsetX = (offsetX + dragAmount).coerceIn(-maxSwipe, 0f)
97+
// }
6898
detectHorizontalDragGestures(
69-
onDragEnd = {
99+
onHorizontalDrag = { _, dragAmount ->
70100
scope.launch {
71-
if (offsetX < -80f) {
72-
onSwipe() // 다른 버튼을 닫고 이 버튼만 스와이프
73-
offsetX = -maxSwipe
74-
} else {
75-
offsetX = 0f
76-
onReset() // 스와이프가 닫히면 상태 초기화
101+
val newOffset = (offset.value + dragAmount)
102+
.coerceIn(-maxSwipe, 0f)
103+
offset.snapTo(newOffset)
104+
}
105+
},
106+
onDragEnd = {
107+
if (offset.value < -maxSwipe / 2) {
108+
scope.launch {
109+
offset.animateTo(-maxSwipe)
110+
}
111+
onSwipe()
112+
} else {
113+
scope.launch {
114+
offset.animateTo(0f)
77115
}
116+
onReset()
78117
}
79118
}
80-
) { change, dragAmount ->
81-
change.consume()
82-
offsetX = (offsetX + dragAmount).coerceIn(-maxSwipe, 0f)
83-
}
119+
)
84120
}
85121
) {
86122
Box(
@@ -94,10 +130,12 @@ fun MenuFolderButton(
94130
// 스와이프 상태일 때만 offset 적용
95131
Box(
96132
modifier = Modifier
97-
.offset(x = if (isSwiped) offsetX.dp else 0.dp)
98-
.clickable(onClick = onButtonClick)
133+
// .offset(x = if (isSwiped) offset.value.dp else 0.dp)
134+
.offset { IntOffset(offset.value.roundToInt(), 0) }
135+
99136
) {
100137
MenuFolderContent(
138+
onClick = onButtonClick,
101139
menuFolder = menuFolder
102140
)
103141
}
@@ -161,6 +199,7 @@ fun MenuFolderDeleteButton(onDeleteClick: () -> Unit = {}) {
161199

162200
@Composable
163201
fun MenuFolderContent(
202+
onClick: () -> Unit = {},
164203
menuFolder: MenuFolderList,
165204
) {
166205
val menuCount = menuFolder.menuIds.size
@@ -176,6 +215,7 @@ fun MenuFolderContent(
176215
modifier = Modifier
177216
.fillMaxSize()
178217
.clip(RoundedCornerShape(12.dp))
218+
.clickable(onClick = onClick)
179219
)
180220

181221
Box(
@@ -239,6 +279,7 @@ private fun MenuFolderButtonPreview() {
239279
)
240280

241281
MenuFolderButton(
282+
modifier = Modifier,
242283
menuFolder = dummyMenuFolder,
243284
false, {}, {})
244285
}

0 commit comments

Comments
 (0)