Skip to content

Commit 1e59b15

Browse files
Merge pull request #80 from SOLPLY/feature/#77-maps-api
[Feature/#77] onboarding, maps api
2 parents 6a6609e + e9a839c commit 1e59b15

39 files changed

Lines changed: 669 additions & 338 deletions

File tree

core/designsystem/src/main/java/com/teamsolply/solply/designsystem/component/textfield/SolplyTextField.kt

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import androidx.compose.ui.text.input.VisualTransformation
3232
import androidx.compose.ui.unit.dp
3333
import com.teamsolply.solply.designsystem.R
3434
import com.teamsolply.solply.designsystem.theme.SolplyTheme
35-
import kotlinx.coroutines.delay
3635

3736
@Composable
3837
private fun BaseTextField(
@@ -116,6 +115,7 @@ fun SolplyNicknameTextField(
116115
value: String,
117116
isNicknameDuplicate: Boolean,
118117
onValueChange: (String) -> Unit,
118+
changeNicknameValidate: (Boolean) -> Unit,
119119
modifier: Modifier = Modifier,
120120
placeholder: String = "여기에 입력하세요.",
121121
maxLength: Int = 8,
@@ -132,33 +132,40 @@ fun SolplyNicknameTextField(
132132
) ||
133133
(validationState == NickNameValidateState.Empty && value.isNotEmpty())
134134

135-
LaunchedEffect(value) {
135+
LaunchedEffect(value, isNicknameDuplicate) {
136136
if (value.isNotEmpty()) {
137137
isTyping = true
138-
delay(300)
139-
140138
if (value.length < minLength) {
141139
validationState = NickNameValidateState.TooShort
140+
changeNicknameValidate(false)
142141
isTyping = false
143142
return@LaunchedEffect
144143
}
145144
if (value.length == maxLength) {
146145
validationState = NickNameValidateState.MaxLength
146+
changeNicknameValidate(false)
147147
isTyping = false
148148
return@LaunchedEffect
149149
}
150150

151151
val hasInvalidChars = !checkNicknameValidate(value)
152152
if (hasInvalidChars) {
153153
validationState = NickNameValidateState.Invalid
154+
changeNicknameValidate(false)
154155
isTyping = false
155156
} else {
156-
validationState =
157-
if (isNicknameDuplicate) NickNameValidateState.Duplicate else NickNameValidateState.Valid
157+
if (isNicknameDuplicate) {
158+
validationState = NickNameValidateState.Duplicate
159+
changeNicknameValidate(false)
160+
} else {
161+
validationState = NickNameValidateState.Valid
162+
changeNicknameValidate(true)
163+
}
158164
isTyping = false
159165
}
160166
} else {
161167
validationState = NickNameValidateState.Empty
168+
changeNicknameValidate(false)
162169
isTyping = false
163170
}
164171
}

core/ui/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ plugins {
55
android {
66
namespace = "com.teamsolply.solply.ui"
77
}
8+
9+
dependencies {
10+
implementation(libs.bundles.coil)
11+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.teamsolply.solply.ui.image
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.compose.ui.Modifier
5+
import androidx.compose.ui.layout.ContentScale
6+
import androidx.compose.ui.platform.LocalContext
7+
import coil.ImageLoader
8+
import coil.compose.AsyncImage
9+
import coil.decode.GifDecoder
10+
import coil.decode.SvgDecoder
11+
import coil.request.ImageRequest
12+
13+
@Composable
14+
fun AdaptationImage(
15+
modifier: Modifier = Modifier,
16+
imageUrl: String,
17+
contentScale: ContentScale = ContentScale.Fit,
18+
contentDescription: String? = null
19+
) {
20+
val context = LocalContext.current
21+
22+
val isSvg = containsExtension(imageUrl, "svg")
23+
val isGif = containsExtension(imageUrl, "gif")
24+
25+
val imageLoader = ImageLoader.Builder(context)
26+
.components {
27+
when {
28+
isSvg -> add(SvgDecoder.Factory())
29+
isGif -> add(GifDecoder.Factory())
30+
}
31+
}
32+
.build()
33+
34+
val request = ImageRequest.Builder(context)
35+
.data(imageUrl)
36+
.crossfade(true)
37+
.build()
38+
39+
AsyncImage(
40+
model = request,
41+
imageLoader = imageLoader,
42+
contentScale = contentScale,
43+
contentDescription = contentDescription,
44+
modifier = modifier
45+
)
46+
}
47+
48+
private fun containsExtension(url: String, extension: String): Boolean {
49+
val regex = Regex("\\.$extension(\\?|$)", RegexOption.IGNORE_CASE)
50+
return regex.containsMatchIn(url)
51+
}

remote/maps/src/main/java/com/teamsolply/solply/maps/dto/request/SaveCourseRequestDto.kt renamed to data/maps/src/main/java/com/teamsolply/solply/maps/dto/SaveCourseRequestDto.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.teamsolply.solply.maps.dto.request
1+
package com.teamsolply.solply.maps.dto
22

33
import kotlinx.serialization.SerialName
44
import kotlinx.serialization.Serializable
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.teamsolply.solply.maps.dto.response
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
6+
@Serializable
7+
data class CoursesResponseDto(
8+
@SerialName("courses")
9+
val courses: List<CourseDto>
10+
)
11+
12+
@Serializable
13+
data class CourseDto(
14+
@SerialName("courseId")
15+
val courseId: Long,
16+
17+
@SerialName("title")
18+
val title: String,
19+
20+
@SerialName("placeCount")
21+
val placeCount: Int,
22+
23+
@SerialName("thumbnailImage")
24+
val thumbnailImage: String,
25+
26+
@SerialName("mainTags")
27+
val mainTags: List<String>,
28+
29+
@SerialName("isBookmarked")
30+
val isBookmarked: Boolean,
31+
32+
@SerialName("isActive")
33+
val isActive: Boolean
34+
)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.teamsolply.solply.maps.dto.response
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
6+
@Serializable
7+
data class CourseDetailResponseDto(
8+
@SerialName("courseId")
9+
val courseId: Long,
10+
11+
@SerialName("courseName")
12+
val courseName: String,
13+
14+
@SerialName("introduction")
15+
val introduction: String,
16+
17+
@SerialName("isBookmarked")
18+
val isBookmarked: Boolean,
19+
20+
@SerialName("places")
21+
val places: List<CoursePlaceDto>
22+
)
23+
24+
@Serializable
25+
data class CoursePlaceDto(
26+
@SerialName("placeId")
27+
val placeId: Long,
28+
29+
@SerialName("placeName")
30+
val placeName: String,
31+
32+
@SerialName("thumbnailUrl")
33+
val thumbnailUrl: String,
34+
35+
@SerialName("primaryTag")
36+
val primaryTag: String,
37+
38+
@SerialName("address")
39+
val address: String,
40+
41+
@SerialName("isBookmarked")
42+
val isBookmarked: Boolean,
43+
44+
@SerialName("placeOrder")
45+
val placeOrder: Int,
46+
47+
@SerialName("latitude")
48+
val latitude: String,
49+
50+
@SerialName("longitude")
51+
val longitude: String,
52+
53+
@SerialName("placeType")
54+
val placeType: String,
55+
56+
@SerialName("placeDefaultId")
57+
val placeDefaultId: Long
58+
)
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.teamsolply.solply.maps.dto.response
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
6+
@Serializable
7+
data class GetPlaceDetailResponseDto(
8+
9+
@SerialName("placeId")
10+
val placeId: Long,
11+
12+
@SerialName("placeName")
13+
val placeName: String,
14+
15+
@SerialName("primaryTag")
16+
val primaryTag: String,
17+
18+
@SerialName("introduction")
19+
val introduction: String,
20+
21+
@SerialName("imageInfos")
22+
val imageInfoDtos: List<ImageInfoDto>,
23+
24+
@SerialName("address")
25+
val address: String,
26+
27+
@SerialName("latitude")
28+
val latitude: String,
29+
30+
@SerialName("longitude")
31+
val longitude: String,
32+
33+
@SerialName("contactNumber")
34+
val contactNumber: String?,
35+
36+
@SerialName("openingHours")
37+
val openingHours: String,
38+
39+
@SerialName("snsLinks")
40+
val snsLinkDtos: List<SnsLinkDto>,
41+
42+
@SerialName("isBookmarked")
43+
val isBookmarked: Boolean,
44+
45+
@SerialName("placeType")
46+
val placeType: String,
47+
48+
@SerialName("placeDefaultId")
49+
val placeDefaultId: Long
50+
)
51+
52+
@Serializable
53+
data class ImageInfoDto(
54+
@SerialName("displayOrder")
55+
val displayOrder: Int,
56+
57+
@SerialName("url")
58+
val url: String
59+
)
60+
61+
@Serializable
62+
data class SnsLinkDto(
63+
@SerialName("snsPlatform")
64+
val snsPlatform: String,
65+
66+
@SerialName("url")
67+
val url: String
68+
)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.teamsolply.solply.maps.mapper
2+
3+
import com.teamsolply.solply.maps.dto.response.CourseDetailResponseDto
4+
import com.teamsolply.solply.maps.dto.response.CoursePlaceDto
5+
import com.teamsolply.solply.maps.model.CourseDetailEntity
6+
import com.teamsolply.solply.maps.model.Place
7+
8+
fun CourseDetailResponseDto.toEntity(): CourseDetailEntity {
9+
return CourseDetailEntity(
10+
courseId = courseId,
11+
courseName = courseName,
12+
introduction = introduction,
13+
isBookmarked = isBookmarked,
14+
places = places.map { it.toEntity() }
15+
)
16+
}
17+
18+
fun CoursePlaceDto.toEntity(): Place {
19+
return Place(
20+
placeId = placeId,
21+
placeName = placeName,
22+
thumbnailUrl = thumbnailUrl,
23+
primaryTag = primaryTag,
24+
address = address,
25+
isBookmarked = isBookmarked,
26+
placeOrder = placeOrder,
27+
latitude = latitude,
28+
longitude = longitude,
29+
placeTag = placeType,
30+
placeDefaultId = placeDefaultId.toInt()
31+
)
32+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.teamsolply.solply.maps.mapper
2+
3+
import com.teamsolply.solply.maps.dto.response.CourseDto
4+
import com.teamsolply.solply.maps.model.CourseInfoEntity
5+
import com.teamsolply.solply.model.PlaceType
6+
7+
fun CourseDto.toEntity(): CourseInfoEntity {
8+
return CourseInfoEntity(
9+
courseId = this.courseId.toInt(),
10+
title = this.title,
11+
placeCount = this.placeCount,
12+
thumbnailImage = this.thumbnailImage,
13+
mainTag = this.mainTags.map { PlaceType.valueOf(it) },
14+
isBookmarked = this.isBookmarked,
15+
isActive = this.isActive
16+
)
17+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import com.teamsolply.solply.maps.dto.response.GetPlaceDetailResponseDto
2+
import com.teamsolply.solply.maps.dto.response.ImageInfoDto
3+
import com.teamsolply.solply.maps.dto.response.SnsLinkDto
4+
import com.teamsolply.solply.maps.model.ImageInfo
5+
import com.teamsolply.solply.maps.model.PlaceDetailEntity
6+
import com.teamsolply.solply.maps.model.SnsLink
7+
import com.teamsolply.solply.model.PlaceType
8+
9+
fun GetPlaceDetailResponseDto.toEntity(): PlaceDetailEntity {
10+
return PlaceDetailEntity(
11+
placeId = placeId,
12+
placeName = placeName,
13+
primaryTag = PlaceType.valueOf(primaryTag),
14+
introduction = introduction,
15+
imageInfos = imageInfoDtos.map { it.toEntity() },
16+
address = address,
17+
latitude = latitude.toDouble(),
18+
longitude = longitude.toDouble(),
19+
contactNumber = contactNumber ?: "",
20+
openingHours = openingHours,
21+
snsLinks = snsLinkDtos.map { it.toEntity() },
22+
isBookmarked = isBookmarked,
23+
placeType = placeType,
24+
placeDefaultId = placeDefaultId
25+
)
26+
}
27+
28+
fun ImageInfoDto.toEntity(): ImageInfo {
29+
return ImageInfo(
30+
displayOrder = displayOrder,
31+
url = url
32+
)
33+
}
34+
35+
fun SnsLinkDto.toEntity(): SnsLink {
36+
return SnsLink(
37+
snsPlatform = snsPlatform,
38+
url = url
39+
)
40+
}

0 commit comments

Comments
 (0)