diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
index 867745c29..0c0c33838 100644
--- a/.idea/deploymentTargetDropDown.xml
+++ b/.idea/deploymentTargetDropDown.xml
@@ -3,20 +3,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/app/src/main/java/com/wap/wapp/navigation/WappNavHost.kt b/app/src/main/java/com/wap/wapp/navigation/WappNavHost.kt
index 80ba7518b..6b1280927 100644
--- a/app/src/main/java/com/wap/wapp/navigation/WappNavHost.kt
+++ b/app/src/main/java/com/wap/wapp/navigation/WappNavHost.kt
@@ -9,6 +9,7 @@ import androidx.navigation.navOptions
import com.wap.designsystem.WappTheme
import com.wap.wapp.core.domain.usecase.auth.SignInUseCase
import com.wap.wapp.feature.auth.signin.navigation.navigateToSignIn
+import com.wap.wapp.feature.auth.signin.navigation.signInNavigationRoute
import com.wap.wapp.feature.auth.signin.navigation.signInScreen
import com.wap.wapp.feature.auth.signup.navigation.navigateToSignUp
import com.wap.wapp.feature.auth.signup.navigation.signUpScreen
@@ -17,9 +18,9 @@ import com.wap.wapp.feature.management.event.navigation.navigateToEventEdit
import com.wap.wapp.feature.management.event.navigation.navigateToEventRegistration
import com.wap.wapp.feature.management.navigation.managementScreen
import com.wap.wapp.feature.management.navigation.navigateToManagement
+import com.wap.wapp.feature.management.survey.navigation.managementSurveyNavGraph
import com.wap.wapp.feature.management.survey.navigation.navigateToSurveyFormEdit
import com.wap.wapp.feature.management.survey.navigation.navigateToSurveyFormRegistration
-import com.wap.wapp.feature.management.survey.navigation.managementSurveyNavGraph
import com.wap.wapp.feature.notice.navigation.navigateToNotice
import com.wap.wapp.feature.notice.navigation.noticeScreen
import com.wap.wapp.feature.profile.navigation.navigateToProfile
@@ -93,7 +94,7 @@ fun WappNavHost(
)
profileScreen(
navigateToProfileSetting = navController::navigateToProfileSetting,
- navigateToSignInScreen = {
+ navigateToSignIn = {
navController.navigateToSignIn(
navOptions {
popUpTo(profileNavigationRoute)
@@ -102,6 +103,13 @@ fun WappNavHost(
},
)
profileSettingScreen(
+ navigateToSignIn = {
+ navController.navigateToSignIn(
+ navOptions {
+ popUpTo(signInNavigationRoute) { inclusive = true }
+ },
+ )
+ },
navigateToProfile = {
navController.navigateToProfile(
navOptions {
diff --git a/core/data/src/main/java/com/wap/wapp/core/data/repository/event/EventRepository.kt b/core/data/src/main/java/com/wap/wapp/core/data/repository/event/EventRepository.kt
index 77e299eb0..a052f9131 100644
--- a/core/data/src/main/java/com/wap/wapp/core/data/repository/event/EventRepository.kt
+++ b/core/data/src/main/java/com/wap/wapp/core/data/repository/event/EventRepository.kt
@@ -5,10 +5,14 @@ import java.time.LocalDate
import java.time.LocalDateTime
interface EventRepository {
- suspend fun getEventList(): Result>
-
suspend fun getMonthEventList(date: LocalDate): Result>
+ suspend fun getDateEventList(date: LocalDate): Result>
+
+ suspend fun getEventListFromDate(date: LocalDate): Result>
+
+ suspend fun getEventList(): Result>
+
suspend fun getEvent(eventId: String): Result
suspend fun postEvent(
diff --git a/core/data/src/main/java/com/wap/wapp/core/data/repository/event/EventRepositoryImpl.kt b/core/data/src/main/java/com/wap/wapp/core/data/repository/event/EventRepositoryImpl.kt
index 454c5a67e..cecbfd55d 100644
--- a/core/data/src/main/java/com/wap/wapp/core/data/repository/event/EventRepositoryImpl.kt
+++ b/core/data/src/main/java/com/wap/wapp/core/data/repository/event/EventRepositoryImpl.kt
@@ -10,18 +10,32 @@ import javax.inject.Inject
class EventRepositoryImpl @Inject constructor(
private val eventDataSource: EventDataSource,
) : EventRepository {
+ override suspend fun getMonthEventList(date: LocalDate): Result> =
+ eventDataSource.getMonthEventList(date).mapCatching { eventResponses ->
+ eventResponses.map { eventResponse ->
+ eventResponse.toDomain()
+ }.sortedBy { it.startDateTime }
+ }
+
override suspend fun getEventList(): Result> =
eventDataSource.getEventList().mapCatching { eventResponses ->
eventResponses.map { eventResponse ->
eventResponse.toDomain()
- }
+ }.sortedBy { it.startDateTime }
}
- override suspend fun getMonthEventList(date: LocalDate): Result> =
- eventDataSource.getMonthEventList(date).mapCatching { eventResponses ->
+ override suspend fun getDateEventList(date: LocalDate): Result> =
+ eventDataSource.getDateEventList(date).mapCatching { eventResponses ->
+ eventResponses.map { eventResponse ->
+ eventResponse.toDomain()
+ }.sortedBy { it.startDateTime }
+ }
+
+ override suspend fun getEventListFromDate(date: LocalDate): Result> =
+ eventDataSource.getEventListFromDate(date).mapCatching { eventResponses ->
eventResponses.map { eventResponse ->
eventResponse.toDomain()
- }
+ }.sortedBy { it.startDateTime }
}
override suspend fun getEvent(eventId: String): Result =
diff --git a/core/data/src/main/java/com/wap/wapp/core/data/repository/survey/SurveyRepository.kt b/core/data/src/main/java/com/wap/wapp/core/data/repository/survey/SurveyRepository.kt
index 46fbfd7ce..79f635b8e 100644
--- a/core/data/src/main/java/com/wap/wapp/core/data/repository/survey/SurveyRepository.kt
+++ b/core/data/src/main/java/com/wap/wapp/core/data/repository/survey/SurveyRepository.kt
@@ -7,6 +7,8 @@ import java.time.LocalDateTime
interface SurveyRepository {
suspend fun getSurveyList(): Result>
+ suspend fun getUserRespondedSurveyList(userId: String): Result>
+
suspend fun getSurvey(surveyId: String): Result
suspend fun postSurvey(
diff --git a/core/data/src/main/java/com/wap/wapp/core/data/repository/survey/SurveyRepositoryImpl.kt b/core/data/src/main/java/com/wap/wapp/core/data/repository/survey/SurveyRepositoryImpl.kt
index ad5825839..be67814c7 100644
--- a/core/data/src/main/java/com/wap/wapp/core/data/repository/survey/SurveyRepositoryImpl.kt
+++ b/core/data/src/main/java/com/wap/wapp/core/data/repository/survey/SurveyRepositoryImpl.kt
@@ -28,6 +28,22 @@ class SurveyRepositoryImpl @Inject constructor(
}
}
+ override suspend fun getUserRespondedSurveyList(userId: String): Result> =
+ surveyDataSource.getUserRespondedSurveyList(userId).mapCatching { surveyList ->
+ surveyList.map { surveyResponse ->
+ userDataSource.getUserProfile(userId = surveyResponse.userId)
+ .mapCatching { userProfileResponse ->
+ val userName = userProfileResponse.toDomain().userName
+
+ noticeNameResponse.mapCatching { noticeNameResponse ->
+ val eventName = noticeNameResponse.toDomain()
+
+ surveyResponse.toDomain(userName = userName, eventName = eventName)
+ }.getOrThrow()
+ }.getOrThrow()
+ }
+ }
+
override suspend fun getSurvey(surveyId: String): Result =
surveyDataSource.getSurvey(surveyId).mapCatching { surveyResponse ->
userDataSource.getUserProfile(userId = surveyResponse.userId)
diff --git a/core/designsystem/src/main/java/com/wap/designsystem/component/MainTopBar.kt b/core/designsystem/src/main/java/com/wap/designsystem/component/MainTopBar.kt
index ad19a3282..31cac16e4 100644
--- a/core/designsystem/src/main/java/com/wap/designsystem/component/MainTopBar.kt
+++ b/core/designsystem/src/main/java/com/wap/designsystem/component/MainTopBar.kt
@@ -92,7 +92,6 @@ fun WappMainTopBarWithButton() {
titleRes = R.string.notice,
contentRes = R.string.notice,
showSettingButton = true,
- onClickSettingButton = {},
)
}
}
diff --git a/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/event/GetDateEventListUseCase.kt b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/event/GetDateEventListUseCase.kt
new file mode 100644
index 000000000..f3406db4f
--- /dev/null
+++ b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/event/GetDateEventListUseCase.kt
@@ -0,0 +1,13 @@
+package com.wap.wapp.core.domain.usecase.event
+
+import com.wap.wapp.core.data.repository.event.EventRepository
+import com.wap.wapp.core.model.event.Event
+import java.time.LocalDate
+import javax.inject.Inject
+
+class GetDateEventListUseCase @Inject constructor(
+ private val eventRepository: EventRepository,
+) {
+ suspend operator fun invoke(date: LocalDate): Result> =
+ eventRepository.getMonthEventList(date)
+}
diff --git a/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/event/GetRecentEventListUseCase.kt b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/event/GetRecentEventListUseCase.kt
new file mode 100644
index 000000000..7cd5445d3
--- /dev/null
+++ b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/event/GetRecentEventListUseCase.kt
@@ -0,0 +1,19 @@
+package com.wap.wapp.core.domain.usecase.event
+
+import com.wap.wapp.core.data.repository.event.EventRepository
+import com.wap.wapp.core.model.event.Event
+import java.time.LocalDate
+import java.time.ZoneId
+import java.time.temporal.ChronoUnit
+import javax.inject.Inject
+
+class GetRecentEventListUseCase @Inject constructor(
+ private val eventRepository: EventRepository,
+) {
+ suspend operator fun invoke(registrationDate: LocalDate): Result> {
+ val currentDate = LocalDate.now(ZoneId.of("Asia/Seoul"))
+ val minimumDate = currentDate.minus(3, ChronoUnit.MONTHS)
+ val selectedDate = maxOf(registrationDate, minimumDate)
+ return eventRepository.getEventListFromDate(selectedDate)
+ }
+}
diff --git a/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/survey/GetUserRespondedSurveyListUseCase.kt b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/survey/GetUserRespondedSurveyListUseCase.kt
new file mode 100644
index 000000000..d4697af5f
--- /dev/null
+++ b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/survey/GetUserRespondedSurveyListUseCase.kt
@@ -0,0 +1,12 @@
+package com.wap.wapp.core.domain.usecase.survey
+
+import com.wap.wapp.core.data.repository.survey.SurveyRepository
+import com.wap.wapp.core.model.survey.Survey
+import javax.inject.Inject
+
+class GetUserRespondedSurveyListUseCase @Inject constructor(
+ private val surveyRepository: SurveyRepository,
+) {
+ suspend operator fun invoke(userId: String): Result> =
+ surveyRepository.getUserRespondedSurveyList(userId)
+}
diff --git a/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/user/GetUserProfileUseCase.kt b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/user/GetUserProfileUseCase.kt
new file mode 100644
index 000000000..3df73744c
--- /dev/null
+++ b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/user/GetUserProfileUseCase.kt
@@ -0,0 +1,16 @@
+package com.wap.wapp.core.domain.usecase.user
+
+import com.wap.wapp.core.data.repository.user.UserRepository
+import com.wap.wapp.core.model.user.UserProfile
+import javax.inject.Inject
+
+class GetUserProfileUseCase @Inject constructor(private val userRepository: UserRepository) {
+ suspend operator fun invoke(): Result = runCatching {
+ val userId = userRepository.getUserId().getOrThrow()
+
+ userRepository.getUserProfile(userId).fold(
+ onSuccess = { userProfile -> userProfile },
+ onFailure = { throw it },
+ )
+ }
+}
diff --git a/core/network/src/main/java/com/wap/wapp/core/network/source/event/EventDataSource.kt b/core/network/src/main/java/com/wap/wapp/core/network/source/event/EventDataSource.kt
index f0cc3efb6..95a36997a 100644
--- a/core/network/src/main/java/com/wap/wapp/core/network/source/event/EventDataSource.kt
+++ b/core/network/src/main/java/com/wap/wapp/core/network/source/event/EventDataSource.kt
@@ -4,9 +4,13 @@ import com.wap.wapp.core.network.model.event.EventResponse
import java.time.LocalDate
interface EventDataSource {
+ suspend fun getMonthEventList(date: LocalDate): Result>
+
+ suspend fun getDateEventList(date: LocalDate): Result>
+
suspend fun getEventList(): Result>
- suspend fun getMonthEventList(date: LocalDate): Result>
+ suspend fun getEventListFromDate(date: LocalDate): Result>
suspend fun getEvent(eventId: String): Result
diff --git a/core/network/src/main/java/com/wap/wapp/core/network/source/event/EventDataSourceImpl.kt b/core/network/src/main/java/com/wap/wapp/core/network/source/event/EventDataSourceImpl.kt
index 18549dc5c..54b513502 100644
--- a/core/network/src/main/java/com/wap/wapp/core/network/source/event/EventDataSourceImpl.kt
+++ b/core/network/src/main/java/com/wap/wapp/core/network/source/event/EventDataSourceImpl.kt
@@ -31,6 +31,27 @@ class EventDataSourceImpl @Inject constructor(
result
}
+ override suspend fun getEventListFromDate(date: LocalDate): Result> =
+ runCatching {
+ val result = mutableListOf()
+
+ // 선택된 날짜 1일 00시 00분 00초
+ val startDateTime = date.atStartOfDay().toISOLocalDateTimeString()
+
+ val task = firebaseFirestore.collection(EVENT_COLLECTION)
+ .whereGreaterThanOrEqualTo("startDateTime", startDateTime)
+ .get()
+ .await()
+
+ for (document in task.documents) {
+ val event = document.toObject()
+ checkNotNull(event)
+ result.add(event)
+ }
+
+ result
+ }
+
override suspend fun getMonthEventList(date: LocalDate): Result> =
runCatching {
val result = mutableListOf()
@@ -59,6 +80,28 @@ class EventDataSourceImpl @Inject constructor(
result
}
+ override suspend fun getDateEventList(date: LocalDate): Result> =
+ runCatching {
+ val result = mutableListOf()
+
+ val startDateTime = date.atStartOfDay().toISOLocalDateTimeString()
+ val endDateTime = date.atTime(LocalTime.MAX).toISOLocalDateTimeString()
+
+ val task = firebaseFirestore.collection(EVENT_COLLECTION)
+ .whereGreaterThanOrEqualTo("startDateTime", startDateTime)
+ .whereLessThanOrEqualTo("startDateTime", endDateTime)
+ .get()
+ .await()
+
+ for (document in task.documents) {
+ val event = document.toObject()
+ checkNotNull(event)
+ result.add(event)
+ }
+
+ result
+ }
+
override suspend fun getEvent(eventId: String): Result =
runCatching {
val document = firebaseFirestore.collection(EVENT_COLLECTION)
diff --git a/core/network/src/main/java/com/wap/wapp/core/network/source/survey/SurveyDataSource.kt b/core/network/src/main/java/com/wap/wapp/core/network/source/survey/SurveyDataSource.kt
index 20b3efcdd..6022af5e1 100644
--- a/core/network/src/main/java/com/wap/wapp/core/network/source/survey/SurveyDataSource.kt
+++ b/core/network/src/main/java/com/wap/wapp/core/network/source/survey/SurveyDataSource.kt
@@ -11,6 +11,8 @@ interface SurveyDataSource {
suspend fun getSurveyList(): Result>
+ suspend fun getUserRespondedSurveyList(userId: String): Result>
+
suspend fun getSurvey(surveyId: String): Result
suspend fun postSurvey(
diff --git a/core/network/src/main/java/com/wap/wapp/core/network/source/survey/SurveyDataSourceImpl.kt b/core/network/src/main/java/com/wap/wapp/core/network/source/survey/SurveyDataSourceImpl.kt
index ff7f7c90b..2916973f2 100644
--- a/core/network/src/main/java/com/wap/wapp/core/network/source/survey/SurveyDataSourceImpl.kt
+++ b/core/network/src/main/java/com/wap/wapp/core/network/source/survey/SurveyDataSourceImpl.kt
@@ -29,6 +29,25 @@ class SurveyDataSourceImpl @Inject constructor(
result
}
+ override suspend fun getUserRespondedSurveyList(userId: String): Result> =
+ runCatching {
+ val result: MutableList = mutableListOf()
+
+ val task = firebaseFirestore.collection(SURVEY_COLLECTION)
+ .whereEqualTo("userId", userId)
+ .get()
+ .await()
+
+ for (document in task.documents) {
+ val surveyResponse = document.toObject(SurveyResponse::class.java)
+ checkNotNull(surveyResponse)
+
+ result.add(surveyResponse)
+ }
+
+ result
+ }
+
override suspend fun getSurvey(surveyId: String): Result = runCatching {
val result = firebaseFirestore.collection(SURVEY_COLLECTION)
.document(surveyId)
diff --git a/feature/management-survey/src/main/java/com/wap/wapp/feature/management/survey/edit/SurveyFormEditViewModel.kt b/feature/management-survey/src/main/java/com/wap/wapp/feature/management/survey/edit/SurveyFormEditViewModel.kt
index 4dcbb7e11..d04800da4 100644
--- a/feature/management-survey/src/main/java/com/wap/wapp/feature/management/survey/edit/SurveyFormEditViewModel.kt
+++ b/feature/management-survey/src/main/java/com/wap/wapp/feature/management/survey/edit/SurveyFormEditViewModel.kt
@@ -113,12 +113,11 @@ class SurveyFormEditViewModel @Inject constructor(
}
fun getEventList() = viewModelScope.launch {
- getEventListUseCase()
- .onSuccess { eventList ->
- _eventList.value = EventsState.Success(eventList)
- }.onFailure { throwable ->
- _surveyFormEditUiEvent.emit(SurveyFormEditUiEvent.Failure(throwable))
- }
+ getEventListUseCase().onSuccess { eventList ->
+ _eventList.value = EventsState.Success(eventList)
+ }.onFailure { throwable ->
+ _surveyFormEditUiEvent.emit(SurveyFormEditUiEvent.Failure(throwable))
+ }
}
fun validateSurveyForm(currentState: SurveyFormState): Boolean {
diff --git a/feature/management-survey/src/main/java/com/wap/wapp/feature/management/survey/registration/SurveyFormRegistrationViewModel.kt b/feature/management-survey/src/main/java/com/wap/wapp/feature/management/survey/registration/SurveyFormRegistrationViewModel.kt
index 5eedc8b64..308d4dd7c 100644
--- a/feature/management-survey/src/main/java/com/wap/wapp/feature/management/survey/registration/SurveyFormRegistrationViewModel.kt
+++ b/feature/management-survey/src/main/java/com/wap/wapp/feature/management/survey/registration/SurveyFormRegistrationViewModel.kt
@@ -67,12 +67,11 @@ class SurveyFormRegistrationViewModel @Inject constructor(
val surveyDateDeadline = _surveyDateDeadline.asStateFlow()
fun getEventList() = viewModelScope.launch {
- getEventListUseCase()
- .onSuccess { eventList ->
- _eventList.value = EventsState.Success(eventList)
- }.onFailure { throwable ->
- _surveyRegistrationEvent.emit(SurveyRegistrationEvent.Failure(throwable))
- }
+ getEventListUseCase().onSuccess { eventList ->
+ _eventList.value = EventsState.Success(eventList)
+ }.onFailure { throwable ->
+ _surveyRegistrationEvent.emit(SurveyRegistrationEvent.Failure(throwable))
+ }
}
fun registerSurvey() = viewModelScope.launch {
diff --git a/feature/notice/src/main/java/com/wap/wapp/feature/notice/BottomSheetContent.kt b/feature/notice/src/main/java/com/wap/wapp/feature/notice/BottomSheetContent.kt
index df47cf482..02999c1af 100644
--- a/feature/notice/src/main/java/com/wap/wapp/feature/notice/BottomSheetContent.kt
+++ b/feature/notice/src/main/java/com/wap/wapp/feature/notice/BottomSheetContent.kt
@@ -12,7 +12,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.itemsIndexed
+import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Divider
import androidx.compose.material.Text
@@ -33,7 +33,6 @@ import com.wap.wapp.core.commmon.util.DateUtil.MONTH_DATE_START_INDEX
import com.wap.wapp.core.commmon.util.DateUtil.yyyyMMddFormatter
import com.wap.wapp.core.model.event.Event
import java.time.LocalDate
-import java.time.format.DateTimeFormatter
import java.time.format.TextStyle
import java.util.Locale
@@ -72,16 +71,16 @@ private fun HandleEventsState(events: NoticeViewModel.EventsState) = when (event
@Composable
private fun EventsList(events: List) {
- if (events.size > 0) {
+ if (events.isNotEmpty()) {
LazyColumn(
contentPadding = PaddingValues(horizontal = 15.dp),
verticalArrangement = Arrangement.spacedBy(12.dp),
modifier = Modifier.fillMaxWidth(),
) {
- itemsIndexed(
+ items(
items = events,
- key = { _, event -> event.eventId },
- ) { _, event ->
+ key = { event -> event.eventId },
+ ) { event ->
EventItem(event = event)
}
}
@@ -110,8 +109,6 @@ private fun EventsList(events: List) {
@Composable
private fun EventItem(event: Event) {
- val formatter = DateTimeFormatter.ofPattern("MM-dd")
-
Column {
Row(
modifier = Modifier
diff --git a/feature/notice/src/main/java/com/wap/wapp/feature/notice/NoticeViewModel.kt b/feature/notice/src/main/java/com/wap/wapp/feature/notice/NoticeViewModel.kt
index 1d3027735..fc3dfd97a 100644
--- a/feature/notice/src/main/java/com/wap/wapp/feature/notice/NoticeViewModel.kt
+++ b/feature/notice/src/main/java/com/wap/wapp/feature/notice/NoticeViewModel.kt
@@ -3,6 +3,7 @@ package com.wap.wapp.feature.notice
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wap.wapp.core.commmon.util.DateUtil
+import com.wap.wapp.core.domain.usecase.event.GetDateEventListUseCase
import com.wap.wapp.core.domain.usecase.event.GetMonthEventListUseCase
import com.wap.wapp.core.model.event.Event
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -16,6 +17,7 @@ import javax.inject.Inject
@HiltViewModel
class NoticeViewModel @Inject constructor(
private val getMonthEventListUseCase: GetMonthEventListUseCase,
+ private val getDateEventListUseCase: GetDateEventListUseCase,
) : ViewModel() {
private val _monthEvents = MutableStateFlow(EventsState.Loading)
val monthEvents: StateFlow = _monthEvents.asStateFlow()
@@ -43,10 +45,8 @@ class NoticeViewModel @Inject constructor(
fun getSelectedDateEvents() {
_selectedDateEvents.value = EventsState.Loading
viewModelScope.launch {
- getMonthEventListUseCase(_selectedDate.value).onSuccess {
- _selectedDateEvents.value = EventsState.Success(
- it.filter { it.startDateTime.toLocalDate() == _selectedDate.value },
- )
+ getDateEventListUseCase(_selectedDate.value).onSuccess { eventList ->
+ _selectedDateEvents.value = EventsState.Success(eventList)
}.onFailure { _selectedDateEvents.value = EventsState.Failure(it) }
}
}
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/ProfileScreen.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/ProfileScreen.kt
index 13954b45d..fc3383ebc 100644
--- a/feature/profile/src/main/java/com/wap/wapp/feature/profile/ProfileScreen.kt
+++ b/feature/profile/src/main/java/com/wap/wapp/feature/profile/ProfileScreen.kt
@@ -2,116 +2,180 @@ package com.wap.wapp.feature.profile
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.SnackbarHost
+import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.wap.designsystem.WappTheme
+import com.wap.designsystem.component.CircleLoader
import com.wap.designsystem.component.WappMainTopBar
+import com.wap.wapp.core.commmon.extensions.toSupportingText
import com.wap.wapp.core.designresource.R.drawable
import com.wap.wapp.core.designresource.R.string
+import com.wap.wapp.core.model.user.UserProfile
+import com.wap.wapp.core.model.user.UserRole
+import com.wap.wapp.feature.profile.ProfileViewModel.UserRoleState
import com.wap.wapp.feature.profile.component.WappProfileCard
-import com.wap.wapp.feature.profile.screen.GuestProfile
-import com.wap.wapp.feature.profile.screen.UserProfile
+import com.wap.wapp.feature.profile.profilesetting.component.GuestProfile
+import com.wap.wapp.feature.profile.profilesetting.component.UserProfile
+import kotlinx.coroutines.flow.collectLatest
@Composable
internal fun ProfileRoute(
viewModel: ProfileViewModel = hiltViewModel(),
- navigateToProfileSetting: () -> Unit,
- navigateToSignInScreen: () -> Unit,
+ navigateToProfileSetting: (String) -> Unit,
+ navigateToSignIn: () -> Unit,
) {
- val eventsState by viewModel.todayEvents.collectAsStateWithLifecycle()
+ val todayEventsState by viewModel.todayEvents.collectAsStateWithLifecycle()
+ val recentEventsState by viewModel.recentEvents.collectAsStateWithLifecycle()
+ val userRespondedSurveysState by viewModel.userRespondedSurveys.collectAsStateWithLifecycle()
+ val userRoleState by viewModel.userRole.collectAsStateWithLifecycle()
+ val userProfile by viewModel.userProfile.collectAsStateWithLifecycle()
+ val snackBarHostState = remember { SnackbarHostState() }
+
+ LaunchedEffect(true) {
+ viewModel.errorFlow.collectLatest { throwable ->
+ snackBarHostState.showSnackbar(
+ message = throwable.toSupportingText(),
+ )
+ }
+ }
ProfileScreen(
- eventsState = eventsState,
+ todayEventsState = todayEventsState,
+ recentEventsState = recentEventsState,
+ userRoleState = userRoleState,
+ userProfile = userProfile,
+ userRespondedSurveysState = userRespondedSurveysState,
+ snackBarHostState = snackBarHostState,
navigateToProfileSetting = navigateToProfileSetting,
- navigateToSignInScreen = navigateToSignInScreen,
+ navigateToSignIn = navigateToSignIn,
)
}
@Composable
internal fun ProfileScreen(
- role: Role = Role.MANAGER,
- userName: String = "",
- eventsState: ProfileViewModel.EventsState,
- navigateToProfileSetting: () -> Unit,
- navigateToSignInScreen: () -> Unit,
+ userRoleState: UserRoleState,
+ userProfile: UserProfile,
+ todayEventsState: ProfileViewModel.EventsState,
+ recentEventsState: ProfileViewModel.EventsState,
+ userRespondedSurveysState: ProfileViewModel.SurveysState,
+ snackBarHostState: SnackbarHostState,
+ navigateToProfileSetting: (String) -> Unit,
+ navigateToSignIn: () -> Unit,
) {
val scrollState = rememberScrollState()
- Column(
- modifier = Modifier
- .fillMaxSize()
- .verticalScroll(scrollState)
- .background(WappTheme.colors.backgroundBlack),
- ) {
- WappMainTopBar(
- titleRes = string.profile,
- contentRes = R.string.profile_content,
- settingButtonDescriptionRes = R.string.profile_setting_description,
- showSettingButton = role != Role.GUEST,
- onClickSettingButton = navigateToProfileSetting,
- )
+ Scaffold(
+ contentWindowInsets = WindowInsets(0.dp),
+ snackbarHost = { SnackbarHost(snackBarHostState) },
+ ) { paddingValues ->
+ Column(
+ modifier = Modifier
+ .padding(paddingValues)
+ .fillMaxSize()
+ .verticalScroll(scrollState)
+ .background(WappTheme.colors.backgroundBlack),
+ ) {
+ when (userRoleState) {
+ is UserRoleState.Loading -> {
+ Spacer(modifier = Modifier.weight(1f))
+ CircleLoader(
+ modifier = Modifier
+ .fillMaxSize()
+ .weight(1f),
+ )
+ Spacer(modifier = Modifier.weight(1f))
+ }
- when (role) {
- Role.MANAGER -> {
- WappProfileCard(
- position = stringResource(R.string.manager),
- githubImage = drawable.ic_manager_github,
- catImage = drawable.ic_manager_cat,
- brush = Brush.horizontalGradient(
- listOf(
- WappTheme.colors.blue2FF,
- WappTheme.colors.blue4FF,
- WappTheme.colors.blue1FF,
- ),
- ),
- userName = "$userName 님",
- )
+ is UserRoleState.Success -> {
+ WappMainTopBar(
+ titleRes = string.profile,
+ contentRes = R.string.profile_content,
+ settingButtonDescriptionRes = R.string.profile_setting_description,
+ showSettingButton = userRoleState.userRole != UserRole.GUEST,
+ onClickSettingButton = { navigateToProfileSetting(userProfile.userId) },
+ )
- UserProfile(eventsState = eventsState)
- }
+ when (userRoleState.userRole) {
+ UserRole.MANAGER -> {
+ WappProfileCard(
+ position = stringResource(R.string.manager),
+ githubImage = drawable.ic_manager_github,
+ catImage = drawable.ic_manager_cat,
+ brush = Brush.horizontalGradient(
+ listOf(
+ WappTheme.colors.blue2FF,
+ WappTheme.colors.blue4FF,
+ WappTheme.colors.blue1FF,
+ ),
+ ),
+ userName = "${userProfile.userName} 님",
+ )
- Role.NORMAL -> {
- WappProfileCard(
- position = stringResource(R.string.normal),
- githubImage = drawable.ic_normal_github,
- catImage = drawable.ic_normal_cat,
- brush = Brush.horizontalGradient(
- listOf(
- WappTheme.colors.yellow3C,
- WappTheme.colors.yellow34,
- WappTheme.colors.yellowA4,
- ),
- ),
- userName = "$userName 님",
- )
+ UserProfile(
+ todayEventsState = todayEventsState,
+ recentEventsState = recentEventsState,
+ userRespondedSurveysState = userRespondedSurveysState,
+ )
+ }
- UserProfile(eventsState = eventsState)
- }
+ UserRole.MEMBER -> {
+ WappProfileCard(
+ position = stringResource(R.string.normal),
+ githubImage = drawable.ic_normal_github,
+ catImage = drawable.ic_normal_cat,
+ brush = Brush.horizontalGradient(
+ listOf(
+ WappTheme.colors.yellow3C,
+ WappTheme.colors.yellow34,
+ WappTheme.colors.yellowA4,
+ ),
+ ),
+ userName = "${userProfile.userName} 님",
+ )
+
+ UserProfile(
+ todayEventsState = todayEventsState,
+ recentEventsState = recentEventsState,
+ userRespondedSurveysState = userRespondedSurveysState,
+ )
+ }
- Role.GUEST -> {
- WappProfileCard(
- position = stringResource(R.string.guest),
- githubImage = drawable.ic_guest_github,
- catImage = drawable.ic_guest_cat,
- brush = Brush.horizontalGradient(
- listOf(
- WappTheme.colors.grayA2,
- WappTheme.colors.gray7C,
- WappTheme.colors.gray4A,
- ),
- ),
- userName = stringResource(id = R.string.non_user),
- )
+ UserRole.GUEST -> {
+ WappProfileCard(
+ position = stringResource(R.string.guest),
+ githubImage = drawable.ic_guest_github,
+ catImage = drawable.ic_guest_cat,
+ brush = Brush.horizontalGradient(
+ listOf(
+ WappTheme.colors.grayA2,
+ WappTheme.colors.gray7C,
+ WappTheme.colors.gray4A,
+ ),
+ ),
+ userName = stringResource(id = R.string.non_user),
+ )
- GuestProfile(navigateToSignInScreen = navigateToSignInScreen)
+ GuestProfile(navigateToSignIn = navigateToSignIn)
+ }
+ }
+ }
}
}
}
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/ProfileViewModel.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/ProfileViewModel.kt
index 1c464d9f6..063bdb87f 100644
--- a/feature/profile/src/main/java/com/wap/wapp/feature/profile/ProfileViewModel.kt
+++ b/feature/profile/src/main/java/com/wap/wapp/feature/profile/ProfileViewModel.kt
@@ -3,46 +3,135 @@ package com.wap.wapp.feature.profile
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wap.wapp.core.commmon.util.DateUtil
-import com.wap.wapp.core.domain.usecase.event.GetMonthEventListUseCase
+import com.wap.wapp.core.domain.usecase.event.GetDateEventListUseCase
+import com.wap.wapp.core.domain.usecase.event.GetRecentEventListUseCase
+import com.wap.wapp.core.domain.usecase.survey.GetUserRespondedSurveyListUseCase
+import com.wap.wapp.core.domain.usecase.user.GetUserProfileUseCase
+import com.wap.wapp.core.domain.usecase.user.GetUserRoleUseCase
import com.wap.wapp.core.model.event.Event
+import com.wap.wapp.core.model.survey.Survey
+import com.wap.wapp.core.model.user.UserProfile
+import com.wap.wapp.core.model.user.UserRole
import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.async
+import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
+import java.time.LocalDate
import javax.inject.Inject
@HiltViewModel
class ProfileViewModel @Inject constructor(
- private val getMonthEventListUseCase: GetMonthEventListUseCase,
+ private val getUserRoleUseCase: GetUserRoleUseCase,
+ private val getUserProfileUseCase: GetUserProfileUseCase,
+ private val getRecentEventListUseCase: GetRecentEventListUseCase,
+ private val getDateEventListUseCase: GetDateEventListUseCase,
+ private val getUserRespondedSurveyListUseCase: GetUserRespondedSurveyListUseCase,
) : ViewModel() {
+ private val _errorFlow: MutableSharedFlow = MutableSharedFlow()
+ val errorFlow: SharedFlow = _errorFlow.asSharedFlow()
+
private val _todayEvents = MutableStateFlow(EventsState.Loading)
val todayEvents: StateFlow = _todayEvents.asStateFlow()
+ private val _recentEvents = MutableStateFlow(EventsState.Loading)
+ val recentEvents: StateFlow = _recentEvents.asStateFlow()
+
+ private val _userRespondedSurveys = MutableStateFlow(SurveysState.Loading)
+ val userRespondedSurveys: StateFlow = _userRespondedSurveys.asStateFlow()
+
+ private val _userRole = MutableStateFlow(UserRoleState.Loading)
+ val userRole: StateFlow = _userRole.asStateFlow()
+
+ private val _userProfile = MutableStateFlow(DEFAULT_USER_PROFILE)
+ val userProfile: StateFlow = _userProfile.asStateFlow()
+
init {
- getTodayDateEvents()
+ checkUserInformationAndGetEvents()
+ }
+
+ private fun checkUserInformationAndGetEvents() = viewModelScope.launch {
+ getUserRoleUseCase()
+ .onFailure { exception -> _errorFlow.emit(exception) }
+ .onSuccess { userRole ->
+ when (userRole) {
+ // 비회원 일 경우, 바로 UserCard 갱신
+ UserRole.GUEST -> _userRole.value = UserRoleState.Success(userRole)
+
+ // 일반 회원 혹은 운영진 일 경우,
+ // 오늘 일정 정보, UserProfile 정보를 가져온 뒤 한꺼번에 갱신
+ UserRole.MEMBER, UserRole.MANAGER -> {
+ getTodayDateEvents()
+ val userProfile = async { getUserProfileUseCase() }
+
+ userProfile.await().onSuccess {
+ _userRole.value = UserRoleState.Success(userRole)
+ _userProfile.value = it
+ launch { getRecentEventsForAttendanceCheck() }
+ getUserRespondedSurveys()
+ }.onFailure { exception -> _errorFlow.emit(exception) }
+ }
+ }
+ }
}
private fun getTodayDateEvents() {
_todayEvents.value = EventsState.Loading
viewModelScope.launch {
- getMonthEventListUseCase(DateUtil.generateNowDate()).fold(
- onSuccess = {
- _todayEvents.value =
- EventsState.Success(
- it.filter {
- it.endDateTime == DateUtil.generateNowDateTime()
- },
- )
- },
- onFailure = { _todayEvents.value = EventsState.Failure(it) },
- )
+ getDateEventListUseCase(DateUtil.generateNowDate()).onSuccess { eventList ->
+ _todayEvents.value = EventsState.Success(eventList)
+ }.onFailure { exception -> _errorFlow.emit(exception) }
+ }
+ }
+
+ private suspend fun getUserRespondedSurveys() {
+ getUserRespondedSurveyListUseCase(_userProfile.value.userId).onSuccess { surveyList ->
+ _userRespondedSurveys.value = SurveysState.Success(surveyList)
+ }.onFailure { exception -> _errorFlow.emit(exception) }
+ }
+
+ private suspend fun getRecentEventsForAttendanceCheck() {
+ val registeredAt = _userProfile.value.registeredAt
+ val (registeredYear, registeredSemester) = registeredAt.split(" ")
+ val registrationDate =
+ createRegistrationDate(registeredYear.toInt(), registeredSemester)
+
+ getRecentEventListUseCase(registrationDate)
+ .onSuccess {
+ _recentEvents.value = EventsState.Success(it)
+ }.onFailure { _errorFlow.emit(it) }
+ }
+
+ private fun createRegistrationDate(year: Int, semester: String): LocalDate {
+ // 학기에 따른 기준 날짜 설정 (예: 1학기는 3월 1일, 2학기는 9월 1일)
+ val semesterNumber = semester.removeSuffix("학기").toInt()
+
+ if (semesterNumber == 1) {
+ return LocalDate.of(year, 3, 1)
}
+ return LocalDate.of(year, 9, 1)
}
sealed class EventsState {
data object Loading : EventsState()
data class Success(val events: List) : EventsState()
- data class Failure(val throwable: Throwable) : EventsState()
+ }
+
+ sealed class SurveysState {
+ data object Loading : SurveysState()
+ data class Success(val surveys: List) : SurveysState()
+ }
+
+ sealed class UserRoleState {
+ data object Loading : UserRoleState()
+ data class Success(val userRole: UserRole) : UserRoleState()
+ }
+
+ companion object {
+ val DEFAULT_USER_PROFILE = UserProfile("", "", "", "")
}
}
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/Role.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/Role.kt
deleted file mode 100644
index 94048aa68..000000000
--- a/feature/profile/src/main/java/com/wap/wapp/feature/profile/Role.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.wap.wapp.feature.profile
-
-enum class Role {
- MANAGER, NORMAL, GUEST
-}
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/component/WappAttendanceRow.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/component/WappAttendanceRow.kt
index 5df5054b4..60d1fc991 100644
--- a/feature/profile/src/main/java/com/wap/wapp/feature/profile/component/WappAttendanceRow.kt
+++ b/feature/profile/src/main/java/com/wap/wapp/feature/profile/component/WappAttendanceRow.kt
@@ -12,19 +12,20 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.wap.designsystem.WappTheme
+import com.wap.wapp.core.commmon.util.DateUtil
import com.wap.wapp.core.designresource.R
+import com.wap.wapp.core.model.event.Event
@Composable
internal fun WappAttendacneRow(
+ event: Event,
isAttendance: Boolean,
onClick: () -> Unit = {},
modifier: Modifier = Modifier,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
- modifier = modifier
- .padding(horizontal = 10.dp)
- .clickable { onClick() },
+ modifier = modifier.clickable { onClick() },
) {
Row(
verticalAlignment = Alignment.CenterVertically,
@@ -32,7 +33,7 @@ internal fun WappAttendacneRow(
) {
WappAttendanceBadge(isAttendance = isAttendance)
Text(
- text = "프로젝트 세미나",
+ text = event.title,
style = WappTheme.typography.labelRegular,
color = WappTheme.colors.white,
maxLines = 1,
@@ -41,7 +42,7 @@ internal fun WappAttendacneRow(
)
}
Text(
- text = "09월 04일",
+ text = event.startDateTime.format(DateUtil.HHmmFormatter),
style = WappTheme.typography.labelRegular,
color = WappTheme.colors.gray95,
modifier = Modifier.padding(start = 10.dp),
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/component/WappSurveyHistoryRow.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/component/WappSurveyHistoryRow.kt
index 318dae019..da585a5f1 100644
--- a/feature/profile/src/main/java/com/wap/wapp/feature/profile/component/WappSurveyHistoryRow.kt
+++ b/feature/profile/src/main/java/com/wap/wapp/feature/profile/component/WappSurveyHistoryRow.kt
@@ -13,9 +13,11 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.wap.designsystem.WappTheme
import com.wap.wapp.core.designresource.R
+import com.wap.wapp.core.model.survey.Survey
@Composable
internal fun WappSurveyHistoryRow(
+ survey: Survey,
modifier: Modifier = Modifier,
onClick: () -> Unit = {},
) {
@@ -35,7 +37,7 @@ internal fun WappSurveyHistoryRow(
)
Text(
- text = "프로젝트 세미나에서 보완해야 할 점이 많아요 아싸라비야",
+ text = survey.title,
style = WappTheme.typography.labelRegular,
color = WappTheme.colors.white,
maxLines = 1,
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/navigation/ProfileNavigation.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/navigation/ProfileNavigation.kt
index fc1a8337a..8f1fe340c 100644
--- a/feature/profile/src/main/java/com/wap/wapp/feature/profile/navigation/ProfileNavigation.kt
+++ b/feature/profile/src/main/java/com/wap/wapp/feature/profile/navigation/ProfileNavigation.kt
@@ -14,13 +14,13 @@ fun NavController.navigateToProfile(navOptions: NavOptions? = navOptions {}) {
}
fun NavGraphBuilder.profileScreen(
- navigateToProfileSetting: () -> Unit,
- navigateToSignInScreen: () -> Unit,
+ navigateToProfileSetting: (String) -> Unit,
+ navigateToSignIn: () -> Unit,
) {
composable(route = profileNavigationRoute) {
ProfileRoute(
navigateToProfileSetting = navigateToProfileSetting,
- navigateToSignInScreen = navigateToSignInScreen,
+ navigateToSignIn = navigateToSignIn,
)
}
}
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/ProfileSettingScreen.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/ProfileSettingScreen.kt
index 5c870c026..d64724280 100644
--- a/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/ProfileSettingScreen.kt
+++ b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/ProfileSettingScreen.kt
@@ -7,13 +7,22 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Divider
import androidx.compose.material.Text
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.SnackbarHost
+import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
@@ -25,179 +34,166 @@ import androidx.hilt.navigation.compose.hiltViewModel
import com.wap.designsystem.WappTheme
import com.wap.designsystem.component.WappRowBar
import com.wap.designsystem.component.WappSubTopBar
+import com.wap.wapp.core.commmon.extensions.toSupportingText
import com.wap.wapp.core.designresource.R
import com.wap.wapp.feature.profile.R.string
+import com.wap.wapp.feature.profile.profilesetting.ProfileSettingViewModel.EventResult.Failure
+import com.wap.wapp.feature.profile.profilesetting.ProfileSettingViewModel.EventResult.Success
+import com.wap.wapp.feature.profile.profilesetting.component.ProfileSettingDialog
@Composable
internal fun ProfileSettingRoute(
+ userId: String,
navigateToProfile: () -> Unit,
+ navigateToSignIn: () -> Unit,
viewModel: ProfileSettingViewModel = hiltViewModel(),
) {
- val context = LocalContext.current
+ val snackBarHostState = remember { SnackbarHostState() }
+
+ LaunchedEffect(true) {
+ viewModel.eventFlow.collect { eventResult ->
+ when (eventResult) {
+ is Failure ->
+ snackBarHostState.showSnackbar(eventResult.throwable.toSupportingText())
+ is Success -> navigateToSignIn()
+ }
+ }
+ }
ProfileSettingScreen(
+ withdrawal = { viewModel.withdrawal(userId) },
+ signOut = viewModel::signOut,
+ snackBarHostState = snackBarHostState,
navigateToProfile = navigateToProfile,
- onClickedPrivacyPolicy = {
- navigateToUri(
- context,
- PRIVACY_POLICY_URL,
- )
- },
- onClickedFAQ = {
- navigateToUri(
- context,
- FAQ_URL,
- )
- },
- onClickedInquiry = {
- navigateToUri(
- context,
- INQUIRY_URL,
- )
- },
- onClickedTermsAndPolicies = {
- navigateToUri(
- context,
- TERMS_AND_POLICIES_URL,
- )
- },
)
}
-private fun navigateToUri(context: Context, url: String) = startActivity(
- context,
- generateUriIntent(url),
- null,
-)
-
-private fun generateUriIntent(url: String) = Intent(Intent.ACTION_VIEW, url.toUri())
-
@Composable
internal fun ProfileSettingScreen(
navigateToProfile: () -> Unit,
- onClickedAlarmSetting: () -> Unit = {},
- onClickedSignOut: () -> Unit = {},
- onClickedWithdrawal: () -> Unit = {},
- onClickedInquiry: () -> Unit,
- onClickedFAQ: () -> Unit,
- onClickedTermsAndPolicies: () -> Unit,
- onClickedPrivacyPolicy: () -> Unit,
+ withdrawal: () -> Unit,
+ signOut: () -> Unit,
+ snackBarHostState: SnackbarHostState,
) {
- val dividerThickness = 1.dp
+ var showWithdrawalDialog by remember { mutableStateOf(false) }
+ var showLogoutDialog by remember { mutableStateOf(false) }
val dividerColor = WappTheme.colors.black42
val scrollState = rememberScrollState()
+ val context = LocalContext.current
- Column(
- modifier = Modifier
- .fillMaxSize()
- .verticalScroll(scrollState)
- .background(color = WappTheme.colors.backgroundBlack),
- ) {
- WappSubTopBar(
- titleRes = string.more,
- showLeftButton = true,
- onClickLeftButton = navigateToProfile,
- modifier = Modifier.padding(top = 20.dp),
- )
-
- Row(
- horizontalArrangement = Arrangement.spacedBy(15.dp),
- modifier = Modifier.padding(start = 15.dp, top = 20.dp, bottom = 25.dp),
- ) {
- Image(
- painter = painterResource(id = R.drawable.ic_account_setting),
- contentDescription = "",
- )
- Text(
- text = stringResource(id = com.wap.wapp.feature.profile.R.string.account_setting),
- style = WappTheme.typography.titleBold,
- color = WappTheme.colors.white,
- )
- }
-
- WappRowBar(
- title = stringResource(id = com.wap.wapp.feature.profile.R.string.alarm_setting),
- onClicked = onClickedAlarmSetting,
- )
-
- Divider(
- color = dividerColor,
- thickness = dividerThickness,
+ if (showWithdrawalDialog) {
+ ProfileSettingDialog(
+ onDismissRequest = { showWithdrawalDialog = false },
+ onConfirmRequest = withdrawal,
+ title = string.withdrawal,
)
+ }
- WappRowBar(
- title = stringResource(id = com.wap.wapp.feature.profile.R.string.sign_out),
- onClicked = onClickedSignOut,
+ if (showLogoutDialog) {
+ ProfileSettingDialog(
+ onDismissRequest = { showLogoutDialog = false },
+ onConfirmRequest = signOut,
+ title = string.logout,
)
+ }
- Divider(
- color = dividerColor,
- thickness = dividerThickness,
- )
+ Scaffold(
+ contentWindowInsets = WindowInsets(0.dp),
+ snackbarHost = { SnackbarHost(snackBarHostState) },
+ ) { paddingValues ->
+ Column(
+ modifier = Modifier
+ .padding(paddingValues)
+ .fillMaxSize()
+ .verticalScroll(scrollState)
+ .background(color = WappTheme.colors.backgroundBlack),
+ ) {
+ WappSubTopBar(
+ titleRes = string.more,
+ showLeftButton = true,
+ onClickLeftButton = navigateToProfile,
+ modifier = Modifier.padding(top = 20.dp),
+ )
- WappRowBar(
- title = stringResource(id = com.wap.wapp.feature.profile.R.string.withdrawal),
- onClicked = onClickedWithdrawal,
- )
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(15.dp),
+ modifier = Modifier.padding(start = 15.dp, top = 20.dp, bottom = 25.dp),
+ ) {
+ Image(
+ painter = painterResource(id = R.drawable.ic_account_setting),
+ contentDescription = "",
+ )
+ Text(
+ text = stringResource(id = string.account_setting),
+ style = WappTheme.typography.titleBold,
+ color = WappTheme.colors.white,
+ )
+ }
+
+ WappRowBar(
+ title = stringResource(id = string.logout),
+ onClicked = { showLogoutDialog = true },
+ )
- Divider(
- color = dividerColor,
- thickness = dividerThickness,
- )
+ Divider(color = dividerColor)
- Row(
- horizontalArrangement = Arrangement.spacedBy(15.dp),
- modifier = Modifier.padding(start = 15.dp, top = 25.dp, bottom = 25.dp),
- ) {
- Image(
- painter = painterResource(id = R.drawable.ic_profile_more),
- contentDescription = "",
- )
- Text(
- text = stringResource(id = com.wap.wapp.feature.profile.R.string.more),
- style = WappTheme.typography.titleBold,
- color = WappTheme.colors.white,
+ WappRowBar(
+ title = stringResource(id = string.withdrawal),
+ onClicked = { showWithdrawalDialog = true },
)
- }
- WappRowBar(
- title = stringResource(id = com.wap.wapp.feature.profile.R.string.inquiry),
- onClicked = onClickedInquiry,
- )
+ Divider(color = dividerColor)
+
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(15.dp),
+ modifier = Modifier.padding(start = 15.dp, top = 25.dp, bottom = 25.dp),
+ ) {
+ Image(
+ painter = painterResource(id = R.drawable.ic_profile_more),
+ contentDescription = "",
+ )
+ Text(
+ text = stringResource(id = string.more),
+ style = WappTheme.typography.titleBold,
+ color = WappTheme.colors.white,
+ )
+ }
+
+ WappRowBar(
+ title = stringResource(id = string.inquiry),
+ onClicked = { navigateToUri(context, INQUIRY_URL) },
+ )
- Divider(
- color = dividerColor,
- thickness = dividerThickness,
- )
+ Divider(color = dividerColor)
- WappRowBar(
- title = stringResource(id = com.wap.wapp.feature.profile.R.string.faq),
- onClicked = onClickedFAQ,
- )
+ WappRowBar(
+ title = stringResource(id = string.faq),
+ onClicked = { navigateToUri(context, FAQ_URL) },
+ )
- Divider(
- color = dividerColor,
- thickness = dividerThickness,
- )
+ Divider(color = dividerColor)
- WappRowBar(
- title = stringResource(id = com.wap.wapp.feature.profile.R.string.terms_and_policies),
- onClicked = onClickedTermsAndPolicies,
- )
+ WappRowBar(
+ title = stringResource(id = string.terms_and_policies),
+ onClicked = { navigateToUri(context, TERMS_AND_POLICIES_URL) },
+ )
- Divider(
- color = dividerColor,
- thickness = dividerThickness,
- )
+ Divider(color = dividerColor)
- WappRowBar(
- title = stringResource(id = com.wap.wapp.feature.profile.R.string.privacy_policy),
- onClicked = onClickedPrivacyPolicy,
- )
+ WappRowBar(
+ title = stringResource(id = string.privacy_policy),
+ onClicked = { navigateToUri(context, PRIVACY_POLICY_URL) },
+ )
- Divider(
- color = dividerColor,
- thickness = dividerThickness,
- )
+ Divider(color = dividerColor)
+ }
}
}
+
+private fun navigateToUri(context: Context, url: String) = startActivity(
+ context,
+ generateUriIntent(url),
+ null,
+)
+
+private fun generateUriIntent(url: String) = Intent(Intent.ACTION_VIEW, url.toUri())
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/ProfileSettingViewModel.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/ProfileSettingViewModel.kt
index e8c255eb9..a0e11e3ce 100644
--- a/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/ProfileSettingViewModel.kt
+++ b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/ProfileSettingViewModel.kt
@@ -1,8 +1,36 @@
package com.wap.wapp.feature.profile.profilesetting
import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.wap.wapp.core.domain.usecase.auth.DeleteUserUseCase
+import com.wap.wapp.core.domain.usecase.auth.SignOutUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.asSharedFlow
+import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
-class ProfileSettingViewModel @Inject constructor() : ViewModel()
+class ProfileSettingViewModel @Inject constructor(
+ private val signOutUseCase: SignOutUseCase,
+ private val deleteUserUseCase: DeleteUserUseCase,
+) : ViewModel() {
+ private val _eventFlow: MutableSharedFlow = MutableSharedFlow()
+ val eventFlow: SharedFlow = _eventFlow.asSharedFlow()
+
+ fun signOut() = viewModelScope.launch {
+ signOutUseCase().onSuccess { _eventFlow.emit(EventResult.Success) }
+ .onFailure { _eventFlow.emit(EventResult.Failure(it)) }
+ }
+
+ fun withdrawal(userId: String) = viewModelScope.launch {
+ deleteUserUseCase(userId).onSuccess { _eventFlow.emit(EventResult.Success) }
+ .onFailure { _eventFlow.emit(EventResult.Failure(it)) }
+ }
+
+ sealed class EventResult {
+ data class Failure(val throwable: Throwable) : EventResult()
+ data object Success : EventResult()
+ }
+}
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/screen/GuestProfile.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/component/GuestProfile.kt
similarity index 93%
rename from feature/profile/src/main/java/com/wap/wapp/feature/profile/screen/GuestProfile.kt
rename to feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/component/GuestProfile.kt
index 54c1f9bfb..62ba49dda 100644
--- a/feature/profile/src/main/java/com/wap/wapp/feature/profile/screen/GuestProfile.kt
+++ b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/component/GuestProfile.kt
@@ -1,4 +1,4 @@
-package com.wap.wapp.feature.profile.screen
+package com.wap.wapp.feature.profile.profilesetting.component
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.fillMaxWidth
@@ -22,7 +22,7 @@ import com.wap.designsystem.WappTheme
import com.wap.wapp.feature.profile.R
@Composable
-internal fun GuestProfile(navigateToSignInScreen: () -> Unit) {
+internal fun GuestProfile(navigateToSignIn: () -> Unit) {
Text(
text = SpannableGuestText(),
color = WappTheme.colors.white,
@@ -41,7 +41,7 @@ internal fun GuestProfile(navigateToSignInScreen: () -> Unit) {
.padding(top = 40.dp)
.height(50.dp)
.fillMaxWidth()
- .clickable { navigateToSignInScreen() },
+ .clickable { navigateToSignIn() },
) {
Text(
text = stringResource(id = R.string.navigate_to_login),
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/component/NoContentColumn.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/component/NoContentColumn.kt
new file mode 100644
index 000000000..d25dc9f6b
--- /dev/null
+++ b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/component/NoContentColumn.kt
@@ -0,0 +1,36 @@
+package com.wap.wapp.feature.profile.profilesetting.component
+
+import androidx.annotation.StringRes
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.wap.designsystem.WappTheme
+
+@Composable
+internal fun NothingToShow(@StringRes title: Int) {
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = Modifier
+ .padding(10.dp)
+ .height(130.dp),
+ ) {
+ Spacer(modifier = Modifier.weight(1f))
+ Text(
+ text = stringResource(id = title),
+ style = WappTheme.typography.contentRegular.copy(fontSize = 20.sp),
+ color = WappTheme.colors.white,
+ textAlign = TextAlign.Center,
+ modifier = Modifier.weight(1f),
+ )
+ Spacer(modifier = Modifier.weight(1f))
+ }
+}
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/component/ProfileSettingDialog.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/component/ProfileSettingDialog.kt
new file mode 100644
index 000000000..0796aa7a9
--- /dev/null
+++ b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/component/ProfileSettingDialog.kt
@@ -0,0 +1,140 @@
+package com.wap.wapp.feature.profile.profilesetting.component
+
+import androidx.annotation.StringRes
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Divider
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.SpanStyle
+import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.style.TextDecoration
+import androidx.compose.ui.text.withStyle
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.compose.ui.window.Dialog
+import androidx.compose.ui.window.DialogProperties
+import com.wap.designsystem.WappTheme
+import com.wap.wapp.feature.profile.R.string
+
+@Composable
+internal fun ProfileSettingDialog(
+ onDismissRequest: () -> Unit,
+ onConfirmRequest: () -> Unit = {},
+ @StringRes title: Int,
+) {
+ Dialog(
+ onDismissRequest = onDismissRequest,
+ properties = DialogProperties(
+ usePlatformDefaultWidth = false,
+ ),
+ ) {
+ Column(
+ verticalArrangement = Arrangement.spacedBy(16.dp),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = Modifier
+ .wrapContentSize()
+ .padding(horizontal = 30.dp)
+ .clip(RoundedCornerShape(8.dp))
+ .background(WappTheme.colors.black25),
+ ) {
+ Text(
+ text = stringResource(title),
+ style = WappTheme.typography.contentBold.copy(fontSize = 20.sp),
+ color = WappTheme.colors.yellow34,
+ modifier = Modifier.padding(top = 16.dp),
+ )
+
+ Divider(
+ color = WappTheme.colors.gray82,
+ modifier = Modifier.padding(horizontal = 12.dp),
+ )
+
+ Text(
+ text = generateDialogContentString(title = title),
+ style = WappTheme.typography.contentRegular,
+ color = WappTheme.colors.white,
+ modifier = Modifier.padding(top = 12.dp, start = 12.dp, end = 12.dp),
+ )
+
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(20.dp),
+ modifier = Modifier.padding(horizontal = 12.dp, vertical = 16.dp),
+ ) {
+ Button(
+ onClick = onConfirmRequest,
+ shape = RoundedCornerShape(8.dp),
+ colors = ButtonDefaults.buttonColors(
+ containerColor = WappTheme.colors.yellow34,
+ ),
+ contentPadding = PaddingValues(vertical = 12.dp),
+ modifier = Modifier.weight(1f),
+ ) {
+ Text(
+ text = stringResource(string.complete),
+ style = WappTheme.typography.titleRegular,
+ color = WappTheme.colors.black,
+ )
+ }
+
+ Button(
+ onClick = onDismissRequest,
+ shape = RoundedCornerShape(10.dp),
+ colors = ButtonDefaults.buttonColors(
+ containerColor = WappTheme.colors.black25,
+ ),
+ contentPadding = PaddingValues(vertical = 12.dp),
+ modifier = Modifier
+ .weight(1f)
+ .border(
+ width = 1.dp,
+ color = WappTheme.colors.yellow34,
+ shape = RoundedCornerShape(8.dp),
+ ),
+ ) {
+ Text(
+ text = stringResource(string.cancel),
+ style = WappTheme.typography.titleRegular,
+ color = WappTheme.colors.yellow34,
+ )
+ }
+ }
+ }
+ }
+}
+
+@Composable
+private fun generateDialogContentString(@StringRes title: Int) = buildAnnotatedString {
+ append("정말로 ")
+ withStyle(
+ style = SpanStyle(
+ textDecoration = TextDecoration.Underline,
+ color = WappTheme.colors.yellow34,
+ ),
+ ) {
+ append(stringResource(title))
+ }
+ append("을 원하신다면 ")
+ withStyle(
+ style = SpanStyle(
+ textDecoration = TextDecoration.Underline,
+ color = WappTheme.colors.yellow34,
+ ),
+ ) {
+ append("완료")
+ }
+ append(" 버튼을 눌러주세요.")
+}
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/component/UserProfile.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/component/UserProfile.kt
new file mode 100644
index 000000000..00fc9949f
--- /dev/null
+++ b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/component/UserProfile.kt
@@ -0,0 +1,237 @@
+package com.wap.wapp.feature.profile.profilesetting.component
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+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.wrapContentHeight
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.SpanStyle
+import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextDecoration
+import androidx.compose.ui.text.withStyle
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.wap.designsystem.WappTheme
+import com.wap.designsystem.component.CircleLoader
+import com.wap.designsystem.component.WappCard
+import com.wap.wapp.core.commmon.util.DateUtil
+import com.wap.wapp.core.designresource.R.drawable
+import com.wap.wapp.core.model.event.Event
+import com.wap.wapp.feature.profile.ProfileViewModel
+import com.wap.wapp.feature.profile.R
+import com.wap.wapp.feature.profile.component.WappAttendacneRow
+import com.wap.wapp.feature.profile.component.WappSurveyHistoryRow
+
+@Composable
+internal fun UserProfile(
+ todayEventsState: ProfileViewModel.EventsState,
+ recentEventsState: ProfileViewModel.EventsState,
+ userRespondedSurveysState: ProfileViewModel.SurveysState,
+) {
+ Column(modifier = Modifier.padding(horizontal = 10.dp)) {
+ ProfileAttendanceCard(
+ todayEventsState = todayEventsState,
+ modifier = Modifier.padding(top = 20.dp),
+ )
+
+ MyAttendanceStatus(
+ recentEventsState = recentEventsState,
+ modifier = Modifier.padding(top = 20.dp),
+ )
+
+ MySurveyHistory(
+ userRespondedSurveysState = userRespondedSurveysState,
+ modifier = Modifier.padding(vertical = 20.dp),
+ )
+ }
+}
+
+@Composable
+private fun ProfileAttendanceCard(
+ todayEventsState: ProfileViewModel.EventsState,
+ modifier: Modifier,
+) {
+ when (todayEventsState) {
+ is ProfileViewModel.EventsState.Loading -> CircleLoader(modifier = Modifier.fillMaxSize())
+ is ProfileViewModel.EventsState.Success -> {
+ WappCard(
+ modifier = modifier
+ .fillMaxWidth()
+ .wrapContentHeight(),
+ ) {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 15.dp, vertical = 10.dp),
+ ) {
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Text(
+ text = stringResource(id = R.string.wap_attendance),
+ style = WappTheme.typography.captionBold.copy(fontSize = 20.sp),
+ color = WappTheme.colors.white,
+ )
+
+ Image(
+ painter = painterResource(id = drawable.ic_check),
+ contentDescription = "",
+ modifier = Modifier.padding(start = 10.dp),
+ )
+ }
+ Text(
+ text = DateUtil.generateNowDate().format(DateUtil.yyyyMMddFormatter),
+ style = WappTheme.typography.contentRegular,
+ color = WappTheme.colors.white,
+ modifier = Modifier.padding(top = 20.dp),
+ )
+
+ if (todayEventsState.events.isEmpty()) {
+ Text(
+ text = stringResource(id = R.string.no_event_today),
+ style = WappTheme.typography.contentRegular.copy(fontSize = 20.sp),
+ color = WappTheme.colors.white,
+ modifier = Modifier.padding(top = 5.dp),
+ )
+ } else {
+ Text(
+ text = generateTodayEventString(events = todayEventsState.events),
+ style = WappTheme.typography.contentRegular.copy(fontSize = 20.sp),
+ color = WappTheme.colors.white,
+ modifier = Modifier.padding(top = 5.dp),
+ )
+ }
+ }
+ }
+ }
+ }
+}
+
+@Composable
+private fun MyAttendanceStatus(
+ recentEventsState: ProfileViewModel.EventsState,
+ modifier: Modifier = Modifier,
+) {
+ Column(modifier = modifier) {
+ Text(
+ text = stringResource(id = R.string.my_attendance),
+ style = WappTheme.typography.titleBold.copy(fontSize = 20.sp),
+ color = WappTheme.colors.white,
+ modifier = Modifier.padding(start = 5.dp),
+ )
+
+ WappCard(
+ modifier = Modifier
+ .fillMaxWidth()
+ .wrapContentHeight()
+ .padding(top = 10.dp),
+ ) {
+ when (recentEventsState) {
+ is ProfileViewModel.EventsState.Loading -> CircleLoader(
+ modifier = Modifier
+ .padding(vertical = 10.dp)
+ .height(130.dp),
+ )
+
+ is ProfileViewModel.EventsState.Success -> {
+ if (recentEventsState.events.isEmpty()) {
+ NothingToShow(title = R.string.no_events_recently)
+ return@WappCard
+ }
+
+ LazyColumn(
+ verticalArrangement = Arrangement.spacedBy(10.dp),
+ modifier = Modifier
+ .padding(10.dp)
+ .height(130.dp),
+ ) {
+ items(
+ items = recentEventsState.events,
+ key = { event -> event.eventId },
+ ) { event ->
+ WappAttendacneRow(isAttendance = true, event = event)
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+@Composable
+private fun MySurveyHistory(
+ userRespondedSurveysState: ProfileViewModel.SurveysState,
+ modifier: Modifier = Modifier,
+) {
+ Column(modifier = modifier) {
+ Text(
+ text = stringResource(id = R.string.survey_i_did),
+ style = WappTheme.typography.titleBold.copy(fontSize = 20.sp),
+ color = WappTheme.colors.white,
+ modifier = Modifier.padding(start = 5.dp),
+ )
+
+ WappCard(
+ modifier = Modifier
+ .fillMaxWidth()
+ .wrapContentHeight()
+ .padding(top = 10.dp),
+ ) {
+ when (userRespondedSurveysState) {
+ is ProfileViewModel.SurveysState.Loading -> CircleLoader(
+ modifier = Modifier
+ .padding(vertical = 10.dp)
+ .height(130.dp),
+ )
+
+ is ProfileViewModel.SurveysState.Success -> {
+ if (userRespondedSurveysState.surveys.isEmpty()) {
+ NothingToShow(title = R.string.no_surveys_after_sign_up)
+ return@WappCard
+ }
+
+ LazyColumn(
+ verticalArrangement = Arrangement.spacedBy(10.dp),
+ modifier = Modifier
+ .padding(10.dp)
+ .height(130.dp),
+ ) {
+ items(
+ items = userRespondedSurveysState.surveys,
+ key = { survey -> survey.surveyId },
+ ) { survey ->
+ WappSurveyHistoryRow(survey)
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+@Composable
+private fun generateTodayEventString(events: List) = buildAnnotatedString {
+ append("오늘은 ")
+
+ withStyle(
+ style = SpanStyle(
+ fontWeight = FontWeight.Bold,
+ textDecoration = TextDecoration.Underline,
+ ),
+ ) {
+ append(events.map { it.title }.joinToString(separator = ", "))
+ }
+
+ append(" 날 이에요!")
+}
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/navigation/ProfileSettingNavigation.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/navigation/ProfileSettingNavigation.kt
index fbea9ac86..620e3d00b 100644
--- a/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/navigation/ProfileSettingNavigation.kt
+++ b/feature/profile/src/main/java/com/wap/wapp/feature/profile/profilesetting/navigation/ProfileSettingNavigation.kt
@@ -3,18 +3,36 @@ package com.wap.wapp.feature.profile.profilesetting.navigation
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
+import androidx.navigation.NavType
import androidx.navigation.compose.composable
+import androidx.navigation.navArgument
import androidx.navigation.navOptions
import com.wap.wapp.feature.profile.profilesetting.ProfileSettingRoute
-const val profileSettingNavigationRoute = "profile_setting_route"
+const val profileSettingNavigationRoute = "profile_setting_route/{userId}"
-fun NavController.navigateToProfileSetting(navOptions: NavOptions? = navOptions {}) {
- this.navigate(profileSettingNavigationRoute, navOptions)
+fun NavController.navigateToProfileSetting(
+ userId: String,
+ navOptions: NavOptions? = navOptions {},
+) {
+ this.navigate("profile_setting_route/$userId", navOptions)
}
-fun NavGraphBuilder.profileSettingScreen(navigateToProfile: () -> Unit) {
- composable(route = profileSettingNavigationRoute) {
- ProfileSettingRoute(navigateToProfile)
+fun NavGraphBuilder.profileSettingScreen(
+ navigateToSignIn: () -> Unit,
+ navigateToProfile: () -> Unit,
+) {
+ composable(
+ route = profileSettingNavigationRoute,
+ arguments = listOf(
+ navArgument("userId") { type = NavType.StringType },
+ ),
+ ) { navBackStackEntry ->
+ val userId = navBackStackEntry.arguments?.getString("userId") ?: ""
+ ProfileSettingRoute(
+ userId = userId,
+ navigateToSignIn = navigateToSignIn,
+ navigateToProfile = navigateToProfile,
+ )
}
}
diff --git a/feature/profile/src/main/java/com/wap/wapp/feature/profile/screen/UserProfile.kt b/feature/profile/src/main/java/com/wap/wapp/feature/profile/screen/UserProfile.kt
deleted file mode 100644
index 8f7f15096..000000000
--- a/feature/profile/src/main/java/com/wap/wapp/feature/profile/screen/UserProfile.kt
+++ /dev/null
@@ -1,190 +0,0 @@
-package com.wap.wapp.feature.profile.screen
-
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.wrapContentHeight
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.SpanStyle
-import androidx.compose.ui.text.buildAnnotatedString
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.style.TextDecoration
-import androidx.compose.ui.text.withStyle
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
-import com.wap.designsystem.WappTheme
-import com.wap.designsystem.component.CircleLoader
-import com.wap.designsystem.component.WappCard
-import com.wap.wapp.core.commmon.util.DateUtil
-import com.wap.wapp.core.designresource.R.drawable
-import com.wap.wapp.core.model.event.Event
-import com.wap.wapp.feature.profile.ProfileViewModel
-import com.wap.wapp.feature.profile.R
-import com.wap.wapp.feature.profile.component.WappAttendacneRow
-import com.wap.wapp.feature.profile.component.WappSurveyHistoryRow
-
-@Composable
-internal fun UserProfile(eventsState: ProfileViewModel.EventsState) {
- Column(modifier = Modifier.padding(horizontal = 10.dp)) {
- handleMonthEventsState(eventsState = eventsState)
-
- MyAttendanceStatus(modifier = Modifier.padding(top = 20.dp))
-
- MySurveyHistory(modifier = Modifier.padding(vertical = 20.dp))
- }
-}
-
-@Composable
-private fun handleMonthEventsState(
- eventsState: ProfileViewModel.EventsState,
-) = when (eventsState) {
- is ProfileViewModel.EventsState.Loading -> CircleLoader(modifier = Modifier.fillMaxSize())
- is ProfileViewModel.EventsState.Success -> {
- ProfileAttendanceCard(
- events = eventsState.events,
- modifier = Modifier.padding(top = 20.dp),
- )
- }
-
- is ProfileViewModel.EventsState.Failure -> {}
-}
-
-@Composable
-private fun ProfileAttendanceCard(
- events: List,
- modifier: Modifier,
-) {
- WappCard(
- modifier = modifier
- .fillMaxWidth()
- .wrapContentHeight(),
- ) {
- Column(
- modifier = Modifier
- .fillMaxWidth()
- .padding(horizontal = 15.dp, vertical = 10.dp),
- ) {
- Row(verticalAlignment = Alignment.CenterVertically) {
- Text(
- text = stringResource(id = R.string.wap_attendance),
- style = WappTheme.typography.captionBold.copy(fontSize = 20.sp),
- color = WappTheme.colors.white,
- )
-
- Image(
- painter = painterResource(id = drawable.ic_check),
- contentDescription = "",
- modifier = Modifier.padding(start = 10.dp),
- )
- }
-
- Text(
- text = DateUtil.generateNowDate().format(DateUtil.yyyyMMddFormatter),
- style = WappTheme.typography.contentRegular,
- color = WappTheme.colors.white,
- modifier = Modifier.padding(top = 20.dp),
- )
-
- if (events.isEmpty()) {
- Text(
- text = stringResource(id = R.string.no_event_today),
- style = WappTheme.typography.contentRegular.copy(fontSize = 20.sp),
- color = WappTheme.colors.white,
- modifier = Modifier.padding(top = 5.dp),
- )
- } else {
- Text(
- text = generateTodayEventString(events = events),
- style = WappTheme.typography.contentRegular.copy(fontSize = 20.sp),
- color = WappTheme.colors.white,
- modifier = Modifier.padding(top = 5.dp),
- )
- }
- }
- }
-}
-
-@Composable
-private fun MyAttendanceStatus(modifier: Modifier = Modifier) {
- Column(modifier = modifier) {
- Text(
- text = stringResource(id = R.string.my_attendance),
- style = WappTheme.typography.titleBold.copy(fontSize = 20.sp),
- color = WappTheme.colors.white,
- modifier = Modifier.padding(start = 5.dp),
- )
-
- WappCard(
- modifier = Modifier
- .fillMaxWidth()
- .wrapContentHeight()
- .padding(top = 10.dp),
- ) {
- Column(
- verticalArrangement = Arrangement.spacedBy(10.dp),
- modifier = Modifier.padding(vertical = 10.dp),
- ) {
- WappAttendacneRow(isAttendance = false)
- WappAttendacneRow(isAttendance = true)
- WappAttendacneRow(isAttendance = false)
- WappAttendacneRow(isAttendance = true)
- }
- }
- }
-}
-
-@Composable
-private fun MySurveyHistory(modifier: Modifier = Modifier) {
- Column(modifier = modifier) {
- Text(
- text = stringResource(id = R.string.survey_i_did),
- style = WappTheme.typography.titleBold.copy(fontSize = 20.sp),
- color = WappTheme.colors.white,
- modifier = Modifier.padding(start = 5.dp),
- )
-
- WappCard(
- modifier = Modifier
- .fillMaxWidth()
- .wrapContentHeight()
- .padding(top = 10.dp),
- ) {
- Column(
- verticalArrangement = Arrangement.spacedBy(10.dp),
- modifier = Modifier.padding(vertical = 10.dp),
- ) {
- WappSurveyHistoryRow()
- WappSurveyHistoryRow()
- WappSurveyHistoryRow()
- WappSurveyHistoryRow()
- }
- }
- }
-}
-
-@Composable
-private fun generateTodayEventString(events: List) = buildAnnotatedString {
- append("오늘은")
-
- withStyle(
- style = SpanStyle(
- fontWeight = FontWeight.Bold,
- textDecoration = TextDecoration.Underline,
- ),
- ) {
- events.forEach { event ->
- append(event.title + ", ")
- }
- }
-
- append("날 이에요!")
-}
diff --git a/feature/profile/src/main/res/values/strings.xml b/feature/profile/src/main/res/values/strings.xml
index 235150c4d..d56ef8a9e 100644
--- a/feature/profile/src/main/res/values/strings.xml
+++ b/feature/profile/src/main/res/values/strings.xml
@@ -11,9 +11,11 @@
내가 한 설문
계정 설정
알람 설정
- 로그아웃
- 회원 탈퇴
+ 로그아웃
+ 회원탈퇴
문의하기
+ 완료
+ 취소
더보기
FAQ
약관 및 정책
@@ -21,4 +23,6 @@
로그인 하러 가기
WAP 출석
오늘은 별 다른 행사가 없어요!
+ 가입한 이후로 참여한 설문이 없어요!
+ 가입한 이후로 진행된 일정이 없어요!