Skip to content

Commit 973f69f

Browse files
authored
Merge pull request #23 from casper-jr/ui/myclubcomponent
[UI] 동아리 목록 컴포넌트 구현
2 parents 726873a + 442ba72 commit 973f69f

4 files changed

Lines changed: 241 additions & 15 deletions

File tree

Lines changed: 11 additions & 0 deletions
Loading
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.whosin.client.data.dto.response
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
6+
@Serializable
7+
data class MyClubResponseDto(
8+
@SerialName("success")
9+
val success: Boolean,
10+
@SerialName("status")
11+
val status: Int,
12+
@SerialName("message")
13+
val message: String,
14+
@SerialName("data")
15+
val data: UserClubs
16+
)
17+
18+
@Serializable
19+
data class UserClubs(
20+
@SerialName("userClubs")
21+
val userClubs: List<ClubData>
22+
)
23+
24+
@Serializable
25+
data class ClubData(
26+
@SerialName("clubId")
27+
val clubId: Int,
28+
@SerialName("clubName")
29+
val clubName: String
30+
)

composeApp/src/commonMain/kotlin/org/whosin/client/presentation/mypage/MyPageScreen.kt

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ import androidx.compose.foundation.layout.Column
77
import androidx.compose.foundation.layout.Spacer
88
import androidx.compose.foundation.layout.fillMaxSize
99
import androidx.compose.foundation.layout.fillMaxWidth
10-
import androidx.compose.foundation.layout.height
1110
import androidx.compose.foundation.layout.padding
11+
import androidx.compose.foundation.layout.size
1212
import androidx.compose.foundation.shape.RoundedCornerShape
1313
import androidx.compose.material3.OutlinedTextField
1414
import androidx.compose.material3.OutlinedTextFieldDefaults
1515
import androidx.compose.material3.Text
1616
import androidx.compose.runtime.Composable
17-
import androidx.compose.runtime.derivedStateOf
1817
import androidx.compose.runtime.getValue
1918
import androidx.compose.runtime.mutableStateOf
2019
import androidx.compose.runtime.remember
2120
import androidx.compose.runtime.setValue
21+
import androidx.compose.ui.Alignment
2222
import androidx.compose.ui.Modifier
2323
import androidx.compose.ui.graphics.Color
2424
import androidx.compose.ui.text.TextStyle
@@ -27,23 +27,50 @@ import androidx.compose.ui.unit.dp
2727
import androidx.compose.ui.unit.sp
2828
import org.jetbrains.compose.resources.stringResource
2929
import org.jetbrains.compose.ui.tooling.preview.Preview
30+
import org.koin.compose.viewmodel.koinViewModel
31+
import org.whosin.client.data.dto.response.ClubData
32+
import org.whosin.client.presentation.mypage.component.MyClubComponent
3033
import org.whosin.client.presentation.mypage.component.MyPageButton
3134
import org.whosin.client.presentation.mypage.component.MyPageTopAppBar
3235
import whosinclient.composeapp.generated.resources.Res
33-
import whosinclient.composeapp.generated.resources.complete_edit
3436
import whosinclient.composeapp.generated.resources.edit_my_information
3537
import whosinclient.composeapp.generated.resources.my_information
3638
import whosinclient.composeapp.generated.resources.nickname
39+
3740
@Composable
38-
fun MyPageScreen(modifier: Modifier = Modifier, onNavigateToAddClub:() -> Unit,onNavigateBack: () -> Unit, onNavigateToEdit: () -> Unit) {
41+
fun MyPageScreen(
42+
modifier: Modifier = Modifier,
43+
onNavigateToAddClub: () -> Unit,
44+
onNavigateBack: () -> Unit,
45+
onNavigateToEdit: () -> Unit
46+
) {
47+
val viewModel: MyPageViewModel = koinViewModel()
3948
var nickName by remember { mutableStateOf("조익성") }
49+
val myClubs = listOf(
50+
ClubData(clubId = 1, clubName = "메이커스팜"),
51+
ClubData(clubId = 2, clubName = "KUIT"),
52+
ClubData(clubId = 1, clubName = "메이커스팜"),
53+
ClubData(clubId = 2, clubName = "KUIT"),
54+
ClubData(clubId = 1, clubName = "메이커스팜"),
55+
ClubData(clubId = 2, clubName = "KUIT"),
56+
ClubData(clubId = 1, clubName = "메이커스팜"),
57+
ClubData(clubId = 2, clubName = "KUIT"),
58+
ClubData(clubId = 1, clubName = "메이커스팜"),
59+
ClubData(clubId = 2, clubName = "KUIT"),
60+
ClubData(clubId = 1, clubName = "메이커스팜"),
61+
ClubData(clubId = 2, clubName = "KUIT"),
62+
)
4063
Box(
41-
modifier = modifier.fillMaxSize().background(Color.White).padding(16.dp)
64+
modifier = modifier
65+
.fillMaxSize()
66+
.background(Color.White)
67+
.padding(16.dp)
4268
) {
4369
Column(
44-
verticalArrangement = Arrangement.spacedBy(32.dp)
70+
modifier = Modifier.fillMaxWidth()
4571
) {
4672
MyPageTopAppBar(onNavigateBack)
73+
Spacer(modifier = Modifier.size(16.dp))
4774
Text(
4875
text = stringResource(Res.string.my_information),
4976
fontSize = 24.sp,
@@ -52,6 +79,7 @@ fun MyPageScreen(modifier: Modifier = Modifier, onNavigateToAddClub:() -> Unit,o
5279
fontWeight = FontWeight.SemiBold,
5380
modifier = Modifier.fillMaxWidth()
5481
)
82+
Spacer(modifier = Modifier.size(32.dp))
5583
Column(
5684
modifier = Modifier.fillMaxWidth()
5785
) {
@@ -79,23 +107,40 @@ fun MyPageScreen(modifier: Modifier = Modifier, onNavigateToAddClub:() -> Unit,o
79107
shape = RoundedCornerShape(10.dp)
80108
)
81109
}
110+
Spacer(modifier = Modifier.size(32.dp))
82111
// 내 동아리 / 학과 목록
83-
Column(
84-
modifier = Modifier.fillMaxWidth().background(Color.Gray).height(271.dp)
85-
) {
86-
Text(text = "내 동아리 / 학과 목록")
87-
}
88-
Spacer(modifier = Modifier.weight(1f))
89-
// 내 정보 수정 버튼
90-
MyPageButton(onClick = onNavigateToEdit, text = stringResource(Res.string.edit_my_information), enabled = nickName.isNotEmpty())
112+
MyClubComponent(
113+
modifier = Modifier
114+
.fillMaxWidth()
115+
.weight(1f)
116+
.padding(bottom = 72.dp),
117+
myClubs = myClubs,
118+
onDeleteClub = {
119+
// TODO: 동아리 삭제
120+
// viewModel.deleteClub(it)
121+
},
122+
onNavigateToAddClub = onNavigateToAddClub
123+
)
91124
}
125+
126+
// 내 정보 수정 버튼 - 하단에 고정
127+
MyPageButton(
128+
onClick = onNavigateToEdit,
129+
text = stringResource(Res.string.edit_my_information),
130+
enabled = nickName.isNotEmpty(),
131+
modifier = Modifier.align(Alignment.BottomCenter)
132+
)
92133
}
93134

94135
}
95136

96137
@Preview
97138
@Composable
98139
private fun MyPageScreenPreview() {
99-
MyPageScreen(onNavigateBack = {}, onNavigateToEdit = {}, onNavigateToAddClub = {} )
140+
MyPageScreen(
141+
onNavigateBack = {},
142+
onNavigateToEdit = {},
143+
onNavigateToAddClub = {}
144+
)
100145
}
101146

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package org.whosin.client.presentation.mypage.component
2+
3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.border
5+
import androidx.compose.foundation.clickable
6+
import androidx.compose.foundation.layout.Arrangement
7+
import androidx.compose.foundation.layout.Column
8+
import androidx.compose.foundation.layout.PaddingValues
9+
import androidx.compose.foundation.layout.Row
10+
import androidx.compose.foundation.layout.Spacer
11+
import androidx.compose.foundation.layout.fillMaxSize
12+
import androidx.compose.foundation.layout.fillMaxWidth
13+
import androidx.compose.foundation.layout.padding
14+
import androidx.compose.foundation.layout.size
15+
import androidx.compose.foundation.lazy.LazyColumn
16+
import androidx.compose.foundation.lazy.items
17+
import androidx.compose.foundation.shape.RoundedCornerShape
18+
import androidx.compose.material3.Text
19+
import androidx.compose.runtime.Composable
20+
import androidx.compose.ui.Alignment
21+
import androidx.compose.ui.Modifier
22+
import androidx.compose.ui.graphics.Color
23+
import androidx.compose.ui.text.font.FontWeight
24+
import androidx.compose.ui.text.style.TextDecoration
25+
import androidx.compose.ui.unit.dp
26+
import androidx.compose.ui.unit.sp
27+
import coil3.compose.AsyncImage
28+
import org.jetbrains.compose.ui.tooling.preview.Preview
29+
import org.whosin.client.data.dto.response.ClubData
30+
import ui.theme.pretendardFontFamily
31+
import whosinclient.composeapp.generated.resources.Res
32+
33+
@Composable
34+
fun MyClubComponent(
35+
modifier: Modifier = Modifier,
36+
myClubs: List<ClubData>,
37+
onDeleteClub: (Int) -> Unit,
38+
onNavigateToAddClub: () -> Unit
39+
) {
40+
Column(
41+
modifier = modifier
42+
){
43+
Row(
44+
modifier = Modifier
45+
.fillMaxWidth(),
46+
verticalAlignment = Alignment.CenterVertically,
47+
horizontalArrangement = Arrangement.SpaceBetween
48+
) {
49+
Text(
50+
text = "내 동아리/학과 목록",
51+
color = Color.Black,
52+
fontFamily = pretendardFontFamily(),
53+
fontWeight = FontWeight.SemiBold,
54+
fontSize = 16.sp
55+
)
56+
Text(
57+
modifier = Modifier
58+
.clickable(onClick = onNavigateToAddClub),
59+
text = "추가하기",
60+
color = Color(0xFFF89531),
61+
fontFamily = pretendardFontFamily(),
62+
fontSize = 16.sp,
63+
textDecoration = TextDecoration.Underline
64+
)
65+
}
66+
Spacer(modifier = Modifier.size(20.dp))
67+
LazyColumn(
68+
modifier = Modifier
69+
.fillMaxWidth()
70+
.border(
71+
width = 1.dp,
72+
color = Color(0xFFE5E5E5),
73+
shape = RoundedCornerShape(20.dp)
74+
),
75+
contentPadding = PaddingValues(16.dp),
76+
verticalArrangement = Arrangement.spacedBy(24.dp)
77+
) {
78+
items(myClubs) { clubData ->
79+
MyClubItem(
80+
modifier = Modifier,
81+
clubName = clubData.clubName
82+
) {
83+
println("clicked clubId : ${clubData.clubId}")
84+
onDeleteClub(clubData.clubId)
85+
}
86+
}
87+
}
88+
}
89+
}
90+
91+
@Composable
92+
fun MyClubItem(
93+
modifier: Modifier = Modifier,
94+
clubName: String,
95+
onDeleteClub: () -> Unit
96+
) {
97+
Row(
98+
modifier = Modifier
99+
.fillMaxWidth(),
100+
verticalAlignment = Alignment.CenterVertically,
101+
horizontalArrangement = Arrangement.SpaceBetween
102+
) {
103+
Text(
104+
text = clubName,
105+
color = Color.Black,
106+
fontFamily = pretendardFontFamily(),
107+
fontSize = 16.sp
108+
)
109+
AsyncImage(
110+
model = Res.getUri("files/ic_x.svg"),
111+
contentDescription = "Delete Club",
112+
modifier = Modifier
113+
.size(24.dp)
114+
.clickable(onClick = onDeleteClub)
115+
)
116+
}
117+
}
118+
119+
@Preview
120+
@Composable
121+
fun MyClubComponentPreview(
122+
123+
) {
124+
val dummyClubs = listOf(
125+
ClubData(clubId = 1, clubName = "메이커스팜"),
126+
ClubData(clubId = 2, clubName = "KUIT"),
127+
)
128+
Column(
129+
modifier = Modifier
130+
.fillMaxSize()
131+
.background(Color.White)
132+
.padding(horizontal = 20.dp)
133+
) {
134+
MyClubComponent(
135+
myClubs = dummyClubs,
136+
onDeleteClub = {},
137+
onNavigateToAddClub = {}
138+
)
139+
}
140+
}

0 commit comments

Comments
 (0)