Skip to content

Commit a606f3f

Browse files
authored
Merge #86 -> develop
[Feat/#86] 게시물 리스트 api 연동중
2 parents c09b983 + 4c7580c commit a606f3f

27 files changed

+475
-208
lines changed

app/src/main/java/com/paw/key/core/designsystem/component/CourseCard.kt

Lines changed: 37 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,13 @@ package com.paw.key.core.designsystem.component
22

33
import androidx.compose.foundation.Image
44
import androidx.compose.foundation.background
5-
import androidx.compose.foundation.clickable
6-
import androidx.compose.foundation.layout.Box
7-
import androidx.compose.foundation.layout.Column
8-
import androidx.compose.foundation.layout.Row
9-
import androidx.compose.foundation.layout.Spacer
10-
import androidx.compose.foundation.layout.aspectRatio
11-
import androidx.compose.foundation.layout.fillMaxSize
12-
import androidx.compose.foundation.layout.fillMaxWidth
13-
import androidx.compose.foundation.layout.height
14-
import androidx.compose.foundation.layout.padding
15-
import androidx.compose.foundation.layout.size
16-
import androidx.compose.foundation.layout.width
5+
import androidx.compose.foundation.layout.*
176
import androidx.compose.foundation.shape.CircleShape
187
import androidx.compose.foundation.shape.RoundedCornerShape
198
import androidx.compose.material3.HorizontalDivider
209
import androidx.compose.material3.Icon
2110
import androidx.compose.material3.Text
2211
import androidx.compose.runtime.Composable
23-
import androidx.compose.runtime.mutableStateOf
24-
import androidx.compose.runtime.remember
2512
import androidx.compose.ui.Alignment
2613
import androidx.compose.ui.Modifier
2714
import androidx.compose.ui.draw.clip
@@ -31,7 +18,6 @@ import androidx.compose.ui.graphics.vector.ImageVector
3118
import androidx.compose.ui.layout.ContentScale
3219
import androidx.compose.ui.platform.LocalConfiguration
3320
import androidx.compose.ui.platform.LocalContext
34-
import androidx.compose.ui.res.painterResource
3521
import androidx.compose.ui.res.vectorResource
3622
import androidx.compose.ui.tooling.preview.Preview
3723
import androidx.compose.ui.unit.dp
@@ -43,7 +29,16 @@ import com.paw.key.core.util.noRippleClickable
4329

4430
@Composable
4531
fun CourseCard(
32+
postId: Long,
4633
title: String,
34+
createdAt: String,
35+
representativeImageUrl: String,
36+
petName: String,
37+
petProfileImageUrl: String,
38+
descriptionTags: List<String>,
39+
isLiked: Boolean,
40+
onClickItem: () -> Unit,
41+
modifier: Modifier = Modifier
4742
petName: String,
4843
date: String,
4944
representativeImageUrl: String? = null, // 추가
@@ -71,9 +66,7 @@ fun CourseCard(
7166
.fillMaxWidth()
7267
.size(width = 328.dp, height = 240.dp)
7368
.background(Color.White, shape = RoundedCornerShape(20.dp))
74-
.noRippleClickable {
75-
onCLickItem()
76-
}
69+
.noRippleClickable { onClickItem() }
7770
) {
7871
// 지도 썸네일
7972
Box(
@@ -82,6 +75,8 @@ fun CourseCard(
8275
.aspectRatio(343f / 172f)
8376
.clip(RoundedCornerShape(10.dp))
8477
) {
78+
79+
8580
// 서버 이미지 또는 기본 이미지
8681
if (representativeImageUrl != null) {
8782
AsyncImage(
@@ -128,7 +123,6 @@ fun CourseCard(
128123
.clip(RoundedCornerShape(8.dp))
129124
)
130125

131-
// 프로필 + 제목
132126
Row(
133127
verticalAlignment = Alignment.CenterVertically,
134128
modifier = Modifier
@@ -182,46 +176,22 @@ fun CourseCard(
182176
)
183177
Spacer(modifier = Modifier.width(8.dp))
184178
Text(
179+
text = createdAt,
185180
text = formatDate(date), // 포맷된 날짜 사용
186181
style = PawKeyTheme.typography.caption12R,
187182
color = PawKeyTheme.colors.gray100
188183
)
189184
}
190185
}
191186
Spacer(modifier = Modifier.weight(1f))
192-
193-
when {
194-
isShared -> {
195-
Icon(
196-
imageVector = ImageVector.vectorResource(id = R.drawable.ic_eye_linear_valid),
197-
contentDescription = "공유됨",
198-
tint = PawKeyTheme.colors.gray200,
199-
)
200-
}
201-
isRecord -> {
202-
val isLiked = remember { mutableStateOf(false) }
203-
204-
Icon(
205-
imageVector = if (isLiked.value) {
206-
ImageVector.vectorResource(id = R.drawable.ic_heart_filled)
207-
} else {
208-
ImageVector.vectorResource(id = R.drawable.ic_heart_default)
209-
},
210-
contentDescription = "좋아요",
211-
tint = Color.Unspecified,
212-
modifier = Modifier.clickable {
213-
isLiked.value = !isLiked.value
214-
}
215-
)
216-
}
217-
else -> {
218-
Icon(
219-
imageVector = ImageVector.vectorResource(id = R.drawable.ic_eye_linear_invalid),
220-
contentDescription = "공유 안됨",
221-
tint = PawKeyTheme.colors.gray200,
222-
)
223-
}
224-
}
187+
Icon(
188+
imageVector = if (isLiked)
189+
ImageVector.vectorResource(id = R.drawable.ic_heart_filled)
190+
else
191+
ImageVector.vectorResource(id = R.drawable.ic_heart_default),
192+
contentDescription = "좋아요",
193+
tint = Color.Unspecified
194+
)
225195
}
226196
}
227197

@@ -235,23 +205,29 @@ fun CourseCard(
235205
)
236206

237207
Spacer(modifier = Modifier.height(12.dp))
238-
}
239208

240-
HorizontalDivider(
241-
color = PawKeyTheme.colors.gray50,
242-
thickness = 1.dp,
243-
modifier = Modifier.padding(start = 16.dp, end = 16.dp)
244-
)
209+
HorizontalDivider(
210+
color = PawKeyTheme.colors.gray50,
211+
thickness = 1.dp,
212+
modifier = Modifier.padding(start = 16.dp, end = 16.dp)
213+
)
214+
}
245215
}
216+
246217
@Preview(showBackground = true)
247218
@Composable
248219
fun CourseCardPreview() {
249220
PawKeyTheme {
250221
CourseCard(
222+
postId = 1L,
251223
title = "홍대 주변 좋은 산책 코스",
252-
petName = "반려견 이름",
253-
date = "2025/05/17",
254-
onCLickItem = {}
224+
createdAt = "2025/07/16",
225+
representativeImageUrl = "https://pawkey-server.com/image.jpg",
226+
petName = "후추",
227+
petProfileImageUrl = "https://pawkey-server.com/profile.jpg",
228+
descriptionTags = listOf("이륜차 거의 없음", "물그릇 비치", "쉴 곳 있음"),
229+
isLiked = true,
230+
onClickItem = {}
255231
)
256232
}
257233
}

app/src/main/java/com/paw/key/data/di/RepositoryModule.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package com.paw.key.data.di
22

3+
import com.paw.key.data.repositoryimpl.ArchivedListRepositoryImpl
34
import com.paw.key.data.repositoryimpl.DummyRepositoryImpl
45
import com.paw.key.data.repositoryimpl.PetProfileRepositoryImpl
56
import com.paw.key.data.repositoryimpl.onboarding.OnboardingInfoRepositoryImpl
67
import com.paw.key.data.repositoryimpl.onboarding.OnboardingRegionRepositoryImpl
78
import com.paw.key.data.repositoryimpl.onboarding.OnboardingRepositoryImpl
89
import com.paw.key.data.repositoryimpl.RegionRepositoryImpl
10+
import com.paw.key.data.repositoryimpl.SavedListRepositoryImpl
911
import com.paw.key.data.repositoryimpl.WalkCourseRepositoryImpl
1012
import com.paw.key.data.repositoryimpl.WalkSharedResultRepositoryImpl
1113
import com.paw.key.data.repositoryimpl.filter.FilterOptionRepositoryImpl
@@ -14,11 +16,13 @@ import com.paw.key.data.repositoryimpl.home.HomeRegionRepositoryImpl
1416
import com.paw.key.data.repositoryimpl.list.PostsListRepositoryImpl
1517
import com.paw.key.data.repositoryimpl.walklist.WalkListDetailRepositoryImpl
1618
import com.paw.key.data.repositoryimpl.walkreview.WalkReviewRepositoryImpl
19+
import com.paw.key.domain.repository.ArchivedListRepository
1720
import com.paw.key.domain.repository.DummyRepository
1821
import com.paw.key.domain.repository.onboarding.OnboardingInfoRepository
1922
import com.paw.key.domain.repository.onboarding.OnboardingRegionRepository
2023
import com.paw.key.domain.repository.onboarding.OnboardingRepository
2124
import com.paw.key.domain.repository.RegionRepository
25+
import com.paw.key.domain.repository.SavedListRepository
2226
import com.paw.key.domain.repository.WalkSharedResultRepository
2327
import com.paw.key.domain.repository.filter.FilterOptionRepository
2428
import com.paw.key.domain.repository.sharedwalk.SharedWalkRepository
@@ -100,6 +104,18 @@ interface RepositoryModule {
100104
impl: PetProfileRepositoryImpl
101105
): PetProfileRepository
102106

107+
@Binds
108+
@Singleton
109+
fun bindSavedListRepository(
110+
impl: SavedListRepositoryImpl
111+
): SavedListRepository
112+
113+
@Binds
114+
@Singleton
115+
fun bindArchivedListRepository(
116+
impl: ArchivedListRepositoryImpl
117+
): ArchivedListRepository
118+
103119
@Binds
104120
@Singleton
105121
fun bindWalkReviewRepository(

app/src/main/java/com/paw/key/data/di/ServiceModule.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package com.paw.key.data.di
22

3+
import com.paw.key.data.service.ArchivedListService
34
import com.paw.key.data.service.DummyService
45
import com.paw.key.data.service.PetProfileService
56
import com.paw.key.data.service.onboarding.OnboardingInfoService
67
import com.paw.key.data.service.onboarding.OnboardingPetsService
78
import com.paw.key.data.service.onboarding.OnboardingRegionService
89
import com.paw.key.data.service.RegionService
10+
import com.paw.key.data.service.SavedListService
911
import com.paw.key.data.service.filter.FilterOptionService
1012
import com.paw.key.data.service.sharedwalk.SharedWalkService
1113
import com.paw.key.data.service.home.HomeRegionService
@@ -71,6 +73,16 @@ object ServiceModule {
7173
fun providePetProfileService(retrofit: Retrofit): PetProfileService =
7274
retrofit.create()
7375

76+
@Provides
77+
@Singleton
78+
fun provideSavedListService(retrofit: Retrofit): SavedListService =
79+
retrofit.create()
80+
81+
@Provides
82+
@Singleton
83+
fun provideArchivedListService(retrofit: Retrofit): ArchivedListService =
84+
retrofit.create()
85+
7486
@Provides
7587
@Singleton
7688
fun provideWalkReviewService(retrofit: Retrofit): WalkReviewService =
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.paw.key.data.dto.response
2+
3+
import com.paw.key.domain.model.entity.archivedlist.ArchivedListEntity
4+
import com.paw.key.domain.model.entity.archivedlist.ArchivedListPostsEntity
5+
import com.paw.key.domain.model.entity.archivedlist.WriterEntity
6+
import kotlinx.serialization.SerialName
7+
import kotlinx.serialization.Serializable
8+
9+
@Serializable
10+
data class ArchivedListResponseDto(
11+
@SerialName("code")
12+
val code: String,
13+
@SerialName("message")
14+
val message: String,
15+
@SerialName("data")
16+
val data: ArchivedListResponseDataDto
17+
)
18+
19+
@Serializable
20+
data class ArchivedListResponseDataDto(
21+
val posts: List<ArchivedDto>
22+
) {
23+
fun toEntity() = ArchivedListPostsEntity(
24+
posts = posts.map { it.toEntity() }
25+
)
26+
}
27+
28+
@Serializable
29+
data class ArchivedDto(
30+
@SerialName("postId")
31+
val postId: Int,
32+
@SerialName("createdAt")
33+
val createdAt: String,
34+
@SerialName("isLike")
35+
val isLike: Boolean,
36+
@SerialName("title")
37+
val title: String,
38+
@SerialName("representativeImageUrl")
39+
val representativeImageUrl: String? = null,
40+
@SerialName("routeId")
41+
val routeId: String,
42+
@SerialName("writer")
43+
val writer: WriterDto,
44+
@SerialName("descriptionTags")
45+
val descriptionTags: List<String>
46+
) {
47+
fun toEntity() = ArchivedListEntity(
48+
postId = postId.toLong(),
49+
createdAt = createdAt,
50+
isLiked = isLike,
51+
title = title,
52+
representativeImageUrl = representativeImageUrl ?: "",
53+
writer = listOf(writer.toEntity()),
54+
descriptionTags = descriptionTags
55+
)
56+
}
57+
58+
@Serializable
59+
data class WriterDto(
60+
@SerialName("userId")
61+
val userId: Int,
62+
@SerialName("petName")
63+
val petName: String,
64+
@SerialName("petProfileImageUrl")
65+
val petProfileImageUrl: String
66+
) {
67+
fun toEntity() = WriterEntity (
68+
userId = userId.toLong(),
69+
petName = petName,
70+
petProfileImageUrl = petProfileImageUrl
71+
)
72+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.paw.key.data.dto.response
2+
3+
import com.paw.key.domain.model.entity.savedlist.SavedListEntity
4+
import com.paw.key.domain.model.entity.savedlist.SavedWriterEntity
5+
import kotlinx.serialization.SerialName
6+
import kotlinx.serialization.Serializable
7+
8+
@Serializable
9+
data class SavedListResponseDto(
10+
@SerialName("postId")
11+
val postId: Long,
12+
13+
@SerialName("createdAt")
14+
val createdAt: String,
15+
16+
@SerialName("isLiked")
17+
val isLiked: Boolean,
18+
19+
@SerialName("title")
20+
val title: String,
21+
22+
@SerialName("representativeImageUrl")
23+
val representativeImageUrl: String,
24+
25+
@SerialName("writer")
26+
val writer: List<SavedWriterDto>,
27+
28+
@SerialName("descriptionTags")
29+
val descriptionTags: List<String>
30+
31+
){
32+
fun toEntity() = SavedListEntity(
33+
postId = postId,
34+
createdAt = createdAt,
35+
isLiked = isLiked,
36+
title = title,
37+
representativeImageUrl = representativeImageUrl,
38+
writer = writer.map { it.toEntity() },
39+
descriptionTags = descriptionTags
40+
)
41+
}
42+
43+
@Serializable
44+
data class SavedWriterDto(
45+
@SerialName("userId")
46+
val userId: Long,
47+
48+
@SerialName("petName")
49+
val petName: String,
50+
51+
@SerialName("petProfileImageUrl")
52+
val petProfileImageUrl: String
53+
){
54+
fun toEntity() = SavedWriterEntity(
55+
userId = userId,
56+
petName = petName,
57+
petProfileImageUrl = petProfileImageUrl
58+
)
59+
}

0 commit comments

Comments
 (0)