diff --git a/core/designresource/src/main/res/drawable/ic_chat.xml b/core/designresource/src/main/res/drawable/ic_chat.xml
index fca6a43ea..0ad34e910 100644
--- a/core/designresource/src/main/res/drawable/ic_chat.xml
+++ b/core/designresource/src/main/res/drawable/ic_chat.xml
@@ -1,9 +1,9 @@
-
+ android:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="32"
+ android:viewportHeight="32">
+
diff --git a/core/designresource/src/main/res/drawable/ic_chat_checked.xml b/core/designresource/src/main/res/drawable/ic_chat_checked.xml
new file mode 100644
index 000000000..71e2dfc58
--- /dev/null
+++ b/core/designresource/src/main/res/drawable/ic_chat_checked.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/core/designresource/src/main/res/drawable/ic_home.xml b/core/designresource/src/main/res/drawable/ic_home.xml
index 939c2e1d8..926c5fd22 100644
--- a/core/designresource/src/main/res/drawable/ic_home.xml
+++ b/core/designresource/src/main/res/drawable/ic_home.xml
@@ -4,6 +4,6 @@
android:viewportWidth="32"
android:viewportHeight="32">
diff --git a/core/designresource/src/main/res/drawable/ic_job_posting.xml b/core/designresource/src/main/res/drawable/ic_job_posting.xml
index 9b3b99cf0..8c0b7a35a 100644
--- a/core/designresource/src/main/res/drawable/ic_job_posting.xml
+++ b/core/designresource/src/main/res/drawable/ic_job_posting.xml
@@ -4,7 +4,7 @@
android:viewportWidth="32"
android:viewportHeight="32">
diff --git a/core/domain/src/main/kotlin/com/idle/domain/usecase/chatting/GetChatRoomListUseCase.kt b/core/domain/src/main/kotlin/com/idle/domain/usecase/chatting/GetChatRoomListUseCase.kt
index f94e7ce89..59c0c1cfa 100644
--- a/core/domain/src/main/kotlin/com/idle/domain/usecase/chatting/GetChatRoomListUseCase.kt
+++ b/core/domain/src/main/kotlin/com/idle/domain/usecase/chatting/GetChatRoomListUseCase.kt
@@ -15,7 +15,7 @@ class GetChatRoomListUseCase @Inject constructor(
createdAt = LocalDateTime.now().minusDays(1),
lastMessage = "안녕하세요!안녕하세요!안녕하세요!안녕하세요!안녕하세요!안녕하세요!",
lastSentAt = LocalDateTime.now().minusHours(1),
- unReadMessageCount = 3,
+ unReadMessageCount = 99,
profileImageUrl = "",
),
ChatRoom(
@@ -25,7 +25,7 @@ class GetChatRoomListUseCase @Inject constructor(
createdAt = LocalDateTime.now().minusDays(3),
lastMessage = "오늘 만날 수 있을까요?",
lastSentAt = LocalDateTime.now().minusHours(5),
- unReadMessageCount = 2,
+ unReadMessageCount = 100,
profileImageUrl = "",
),
ChatRoom(
diff --git a/core/domain/src/main/kotlin/com/idle/domain/util/NumberUtil.kt b/core/domain/src/main/kotlin/com/idle/domain/util/NumberUtil.kt
index 3b9f67680..fb98ba0d7 100644
--- a/core/domain/src/main/kotlin/com/idle/domain/util/NumberUtil.kt
+++ b/core/domain/src/main/kotlin/com/idle/domain/util/NumberUtil.kt
@@ -39,4 +39,12 @@ fun formatBusinessRegistrationNumber(businessRegistrationNumber: String): String
else -> throw IllegalArgumentException("사업자 등록번호 형식이 맞지 않습니다.")
}
+}
+
+fun Int.formatUnReadNumber(): String {
+ return when {
+ this < 0 -> "0"
+ this >= 100 -> "99+"
+ else -> this.toString()
+ }
}
\ No newline at end of file
diff --git a/core/domain/src/test/kotlin/com/idle/domain/util/NumberUtilTest.kt b/core/domain/src/test/kotlin/com/idle/domain/util/NumberUtilTest.kt
index fc376ab83..9caea9ed3 100644
--- a/core/domain/src/test/kotlin/com/idle/domain/util/NumberUtilTest.kt
+++ b/core/domain/src/test/kotlin/com/idle/domain/util/NumberUtilTest.kt
@@ -118,4 +118,40 @@ class NumberUtilTest {
formatBusinessRegistrationNumber(businessRegistrationNumber)
}
}
+
+ @Test
+ fun `음수일 경우 0으로 반환된다`() {
+ // Given
+ val number = -5
+
+ // When
+ val result = number.formatUnReadNumber()
+
+ // Then
+ assertEquals("0", result)
+ }
+
+ @Test
+ fun `99 이하의 숫자는 그대로 문자열로 반환된다`() {
+ // Given
+ val number = 99
+
+ // When
+ val result = number.formatUnReadNumber()
+
+ // Then
+ assertEquals("99", result)
+ }
+
+ @Test
+ fun `100 이상의 숫자는 '99+'로 반환된다`() {
+ // Given
+ val number = 100
+
+ // When
+ val result = number.formatUnReadNumber()
+
+ // Then
+ assertEquals("99+", result)
+ }
}
\ No newline at end of file
diff --git a/core/network/src/main/java/com/idle/network/source/auth/AuthDataSource.kt b/core/network/src/main/java/com/idle/network/source/auth/AuthDataSource.kt
index 2bd63c271..a6607653c 100644
--- a/core/network/src/main/java/com/idle/network/source/auth/AuthDataSource.kt
+++ b/core/network/src/main/java/com/idle/network/source/auth/AuthDataSource.kt
@@ -16,9 +16,11 @@ import com.idle.network.model.token.TokenResponse
import com.idle.network.util.safeApiCall
import kotlinx.coroutines.suspendCancellableCoroutine
import javax.inject.Inject
+import javax.inject.Singleton
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
+@Singleton
class AuthDataSource @Inject constructor(
private val authApi: AuthApi,
private val firebaseMessaging: FirebaseMessaging,
diff --git a/core/network/src/main/java/com/idle/network/source/jobposting/JobPostingDataSource.kt b/core/network/src/main/java/com/idle/network/source/jobposting/JobPostingDataSource.kt
index 4ce235fa9..60f3ebe29 100644
--- a/core/network/src/main/java/com/idle/network/source/jobposting/JobPostingDataSource.kt
+++ b/core/network/src/main/java/com/idle/network/source/jobposting/JobPostingDataSource.kt
@@ -16,7 +16,9 @@ import com.idle.network.model.jobposting.GetWorkerJobPostingDetailResponse
import com.idle.network.model.jobposting.JobPostingRequest
import com.idle.network.util.safeApiCall
import javax.inject.Inject
+import javax.inject.Singleton
+@Singleton
class JobPostingDataSource @Inject constructor(
private val jobPostingApi: JobPostingApi
) {
diff --git a/core/network/src/main/java/com/idle/network/source/notification/NotificationDataSource.kt b/core/network/src/main/java/com/idle/network/source/notification/NotificationDataSource.kt
index 579d92bd8..8f8c50a0e 100644
--- a/core/network/src/main/java/com/idle/network/source/notification/NotificationDataSource.kt
+++ b/core/network/src/main/java/com/idle/network/source/notification/NotificationDataSource.kt
@@ -6,7 +6,9 @@ import com.idle.network.model.notification.GetMyNotificationResponse
import com.idle.network.model.notification.GetUnreadNotificationCountResponse
import com.idle.network.util.safeApiCall
import javax.inject.Inject
+import javax.inject.Singleton
+@Singleton
class NotificationDataSource @Inject constructor(
private val notificationApi: NotificationApi
) {
diff --git a/core/network/src/main/java/com/idle/network/source/profile/ProfileDataSource.kt b/core/network/src/main/java/com/idle/network/source/profile/ProfileDataSource.kt
index 6f9648f1b..55d9c8841 100644
--- a/core/network/src/main/java/com/idle/network/source/profile/ProfileDataSource.kt
+++ b/core/network/src/main/java/com/idle/network/source/profile/ProfileDataSource.kt
@@ -15,7 +15,9 @@ import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.InputStream
import javax.inject.Inject
+import javax.inject.Singleton
+@Singleton
class ProfileDataSource @Inject constructor(
private val userApi: UserApi,
) {
diff --git a/core/network/src/main/java/com/idle/network/source/remoteconfig/ConfigDataSource.kt b/core/network/src/main/java/com/idle/network/source/remoteconfig/ConfigDataSource.kt
index d1c0ae6c2..7c3e3a414 100644
--- a/core/network/src/main/java/com/idle/network/source/remoteconfig/ConfigDataSource.kt
+++ b/core/network/src/main/java/com/idle/network/source/remoteconfig/ConfigDataSource.kt
@@ -6,9 +6,11 @@ import com.google.firebase.remoteconfig.get
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.serialization.json.Json
import javax.inject.Inject
+import javax.inject.Singleton
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
+@Singleton
class ConfigDataSource @Inject constructor(
private val remoteConfig: FirebaseRemoteConfig,
) {
diff --git a/feature/center/chatting/src/main/java/com/idle/center/chatting/CenterChattingFragment.kt b/feature/center/chatting/src/main/java/com/idle/center/chatting/CenterChattingFragment.kt
index 3f6581e0d..9dd675311 100644
--- a/feature/center/chatting/src/main/java/com/idle/center/chatting/CenterChattingFragment.kt
+++ b/feature/center/chatting/src/main/java/com/idle/center/chatting/CenterChattingFragment.kt
@@ -44,6 +44,7 @@ import com.idle.designsystem.compose.foundation.CareTheme
import com.idle.domain.model.auth.UserType
import com.idle.domain.model.chatting.ChatRoom
import com.idle.domain.util.formatRelativeDateTime
+import com.idle.domain.util.formatUnReadNumber
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
@@ -87,20 +88,47 @@ internal fun CenterChattingScreen(
.fillMaxSize()
) {
chatRoomList?.let {
- LazyColumn(
- modifier = Modifier
- .fillMaxSize()
- .padding(top = 20.dp, bottom = 36.dp),
- ) {
- items(
- items = chatRoomList,
- key = { it.id },
- ) { chatRoom ->
- ChatRoomItem(
- chatRoom = chatRoom,
- navigateTo = navigateTo,
+ if (chatRoomList.isEmpty()) {
+ Column(
+ modifier = Modifier
+ .align(Alignment.Center)
+ .padding(bottom = 60.dp),
+ ) {
+ Text(
+ text = "아직 채팅 내역이 없어요",
+ style = CareTheme.typography.heading2,
+ color = CareTheme.colors.black,
+ textAlign = TextAlign.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(bottom = 8.dp),
+ )
+
+ Text(
+ text = "센터에 궁금한 점이 있다면 해당 공고에서\n" +
+ "‘채팅하기’ 버튼을 눌러 채팅을 시작할 수 있어요.",
+ style = CareTheme.typography.body3,
+ textAlign = TextAlign.Center,
+ color = CareTheme.colors.gray300,
+ modifier = Modifier.fillMaxWidth(),
)
}
+ } else {
+ LazyColumn(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(top = 20.dp, bottom = 36.dp),
+ ) {
+ items(
+ items = chatRoomList,
+ key = { it.id },
+ ) { chatRoom ->
+ ChatRoomItem(
+ chatRoom = chatRoom,
+ navigateTo = navigateTo,
+ )
+ }
+ }
}
} ?: LoadingCircle(modifier = Modifier.align(Alignment.Center))
}
@@ -207,7 +235,7 @@ internal fun ChatRoomItem(
) {
Text(
text = if (chatRoom.unReadMessageCount != 0)
- chatRoom.unReadMessageCount.toString() else "",
+ chatRoom.unReadMessageCount.formatUnReadNumber() else "",
style = CareTheme.typography.caption1.copy(fontWeight = FontWeight.Bold),
color = CareTheme.colors.white000,
textAlign = TextAlign.Center,
diff --git a/feature/chatting-detail/src/main/java/com/idle/chatting_detail/component/CareChatTextBubble.kt b/feature/chatting-detail/src/main/java/com/idle/chatting_detail/component/CareChatTextBubble.kt
index 1a3b83963..7548ed000 100644
--- a/feature/chatting-detail/src/main/java/com/idle/chatting_detail/component/CareChatTextBubble.kt
+++ b/feature/chatting-detail/src/main/java/com/idle/chatting_detail/component/CareChatTextBubble.kt
@@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
@@ -100,7 +101,7 @@ fun CareChatSenderTextBubbleWithImage(
horizontalAlignment = Alignment.Start,
modifier = Modifier
.padding(start = 4.dp)
- .width(35.dp)
+ .wrapContentWidth()
.align(Alignment.Bottom),
) {
if (isRead) {
diff --git a/feature/worker/chatting/src/main/java/com/idle/worker/chatting/WorkerChattingFragment.kt b/feature/worker/chatting/src/main/java/com/idle/worker/chatting/WorkerChattingFragment.kt
index 2f0c6535b..620668079 100644
--- a/feature/worker/chatting/src/main/java/com/idle/worker/chatting/WorkerChattingFragment.kt
+++ b/feature/worker/chatting/src/main/java/com/idle/worker/chatting/WorkerChattingFragment.kt
@@ -8,8 +8,11 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.widthIn
+import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
@@ -44,6 +47,7 @@ import com.idle.designsystem.compose.foundation.CareTheme
import com.idle.domain.model.auth.UserType
import com.idle.domain.model.chatting.ChatRoom
import com.idle.domain.util.formatRelativeDateTime
+import com.idle.domain.util.formatUnReadNumber
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
@@ -87,20 +91,47 @@ internal fun WorkerChattingScreen(
.fillMaxSize()
) {
chatRoomList?.let {
- LazyColumn(
- modifier = Modifier
- .fillMaxSize()
- .padding(top = 20.dp, bottom = 36.dp),
- ) {
- items(
- items = chatRoomList,
- key = { it.id },
- ) { chatRoom ->
- ChatRoomItem(
- chatRoom = chatRoom,
- navigateTo = navigateTo,
+ if (chatRoomList.isEmpty()) {
+ Column(
+ modifier = Modifier
+ .align(Alignment.Center)
+ .padding(bottom = 60.dp),
+ ) {
+ Text(
+ text = "아직 채팅 내역이 없어요",
+ style = CareTheme.typography.heading2,
+ color = CareTheme.colors.black,
+ textAlign = TextAlign.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(bottom = 8.dp),
+ )
+
+ Text(
+ text = "센터에 궁금한 점이 있다면 해당 공고에서\n" +
+ "‘채팅하기’ 버튼을 눌러 채팅을 시작할 수 있어요.",
+ style = CareTheme.typography.body3,
+ textAlign = TextAlign.Center,
+ color = CareTheme.colors.gray300,
+ modifier = Modifier.fillMaxWidth(),
)
}
+ } else {
+ LazyColumn(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(top = 20.dp, bottom = 36.dp),
+ ) {
+ items(
+ items = chatRoomList,
+ key = { it.id },
+ ) { chatRoom ->
+ ChatRoomItem(
+ chatRoom = chatRoom,
+ navigateTo = navigateTo,
+ )
+ }
+ }
}
} ?: LoadingCircle(modifier = Modifier.align(Alignment.Center))
}
@@ -201,17 +232,21 @@ internal fun ChatRoomItem(
Box(
modifier = Modifier
- .size(22.dp)
+ .height(22.dp)
+ .wrapContentWidth()
+ .widthIn(min = 22.dp)
.clip(RoundedCornerShape(300.dp))
.background(unReadMessageColor),
) {
Text(
text = if (chatRoom.unReadMessageCount != 0)
- chatRoom.unReadMessageCount.toString() else "",
+ chatRoom.unReadMessageCount.formatUnReadNumber() else "",
style = CareTheme.typography.caption1.copy(fontWeight = FontWeight.Bold),
color = CareTheme.colors.white000,
textAlign = TextAlign.Center,
- modifier = Modifier.align(Alignment.Center),
+ modifier = Modifier
+ .padding(horizontal = 6.dp)
+ .align(Alignment.Center),
)
}
}
diff --git a/feature/worker/home/src/main/java/com/idle/worker/home/WorkerHomeFragment.kt b/feature/worker/home/src/main/java/com/idle/worker/home/WorkerHomeFragment.kt
index 0676bed5a..10dd93b05 100644
--- a/feature/worker/home/src/main/java/com/idle/worker/home/WorkerHomeFragment.kt
+++ b/feature/worker/home/src/main/java/com/idle/worker/home/WorkerHomeFragment.kt
@@ -566,7 +566,7 @@ private fun WorkerWorkNetCard(
)
Row(
- verticalAlignment = Alignment.Top,
+ verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 2.dp)
@@ -580,12 +580,11 @@ private fun WorkerWorkNetCard(
text = "${jobPosting.workingSchedule} | ${jobPosting.workingTime}",
style = CareTheme.typography.body3,
color = CareTheme.colors.gray500,
- modifier = Modifier.padding(top = 1.dp),
)
}
Row(
- verticalAlignment = Alignment.Top,
+ verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth(),
) {
Image(
@@ -597,7 +596,6 @@ private fun WorkerWorkNetCard(
text = jobPosting.payInfo,
style = CareTheme.typography.body3,
color = CareTheme.colors.gray500,
- modifier = Modifier.padding(top = 1.dp),
)
}
}
diff --git a/presentation/src/main/res/drawable/selector_menu_chat.xml b/presentation/src/main/res/drawable/selector_menu_chat.xml
new file mode 100644
index 000000000..c7dbf9f24
--- /dev/null
+++ b/presentation/src/main/res/drawable/selector_menu_chat.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/presentation/src/main/res/menu/menu_center.xml b/presentation/src/main/res/menu/menu_center.xml
index e5c402ed9..6427f5c58 100644
--- a/presentation/src/main/res/menu/menu_center.xml
+++ b/presentation/src/main/res/menu/menu_center.xml
@@ -6,7 +6,7 @@
android:title="홈" />